From 04fcc07d47624c49dc4bec16c65fe29eb8b86991 Mon Sep 17 00:00:00 2001 From: Dmitry Ermakov <de@dimer.org.ua> Date: Sat, 12 Feb 2022 23:43:22 +0300 Subject: [PATCH] Add FH8852v100 support --- .github/workflows/fh8852v100_images.yml | 132 + .github/workflows/fh8852v210_images.yml | 38 +- .github/workflows/fh8856v100_images.yml | 132 + br-ext-chip-fullhan/Config.in | 1 + br-ext-chip-fullhan/board/fh8852v100.config | 2 + .../kernel/fh8833v100.generic.config | 1629 + .../kernel/fh8852v100.generic.config | 1634 + .../kernel/fh8856v100.generic.config | 1635 + .../overlay/include/linux/compiler-gcc7.h | 65 + .../patches/00_fh8852v100_kernel-3.0.8.patch | 141672 +++++++++++++++ .../kernel/patches/10_overlayfs.v11.patch | 3176 + .../11_fix_yylloc_for_modern_computers.patch | 11 + .../kernel/patches/12_uimage_makefile.patch | 62 + ...known_unknown_fh8833v100_openipc_defconfig | 97 + ...known_unknown_fh8852v100_openipc_defconfig | 97 + ...known_unknown_fh8856v100_openipc_defconfig | 97 + br-ext-chip-fullhan/external.mk | 1 + .../package/fullhan-osdrv-fh8852v100 | 1 + building.sh | 19 + .../fullhan-osdrv-fh8852v100/Config.in | 6 + .../files/firmware/rtthread_arc_FH8852.bin | Bin 0 -> 417944 bytes .../rtthread_arc_FH8852_human_detect.bin | Bin 0 -> 498804 bytes .../files/firmware/rtthread_arc_FH8856.bin | Bin 0 -> 417944 bytes .../rtthread_arc_FH8856_human_detect.bin | Bin 0 -> 498804 bytes .../files/kmod/bgm.ko | Bin 0 -> 55152 bytes .../files/kmod/enc.ko | Bin 0 -> 146188 bytes .../files/kmod/hevc.ko | Bin 0 -> 450052 bytes .../files/kmod/isp.ko | Bin 0 -> 60760 bytes .../files/kmod/jpeg.ko | Bin 0 -> 68852 bytes .../files/kmod/media_process.ko | Bin 0 -> 83672 bytes .../files/kmod/media_process_no_sc.ko | Bin 0 -> 82208 bytes .../files/kmod/rtvbus.ko | Bin 0 -> 45172 bytes .../files/kmod/vbus_ac.ko | Bin 0 -> 8460 bytes .../files/kmod/vmm.ko | Bin 0 -> 15908 bytes .../files/kmod/vpu.ko | Bin 0 -> 116416 bytes .../files/lib/libacw_mpi.so | Bin 0 -> 14816 bytes .../files/lib/libadvapi.so | Bin 0 -> 114960 bytes .../files/lib/libaudio_codec.so | Bin 0 -> 812896 bytes .../files/lib/libdbi.so | Bin 0 -> 42704 bytes .../files/lib/libdci.so | Bin 0 -> 13636 bytes .../files/lib/libdsp.so | Bin 0 -> 88184 bytes .../files/lib/libfh_crypto_api.so | Bin 0 -> 33616 bytes .../files/lib/libhd_arm_vbcli_linux.so | Bin 0 -> 18724 bytes .../files/lib/libisp.so | Bin 0 -> 81376 bytes .../files/lib/libispcore.so | Bin 0 -> 197484 bytes .../files/lib/libmipi.so | Bin 0 -> 14828 bytes .../files/lib/libvlcview.so | Bin 0 -> 28616 bytes .../files/lib/libvmm.so | Bin 0 -> 12636 bytes .../files/script/S95fullhan | 73 + .../files/script/load_fullhan | 34 + .../files/sensor/libgc4623_mipi.so | Bin 0 -> 24440 bytes .../files/sensor/libgc4633_mipi.so | Bin 0 -> 24620 bytes .../files/sensor/libjxf22_mipi.so | Bin 0 -> 31360 bytes .../files/sensor/libjxf23_mipi.so | Bin 0 -> 18344 bytes .../files/sensor/libmipi.so | Bin 0 -> 14828 bytes .../files/sensor/libmn34425_mipi.so | Bin 0 -> 24896 bytes .../files/sensor/libov2732_mipi.so | Bin 0 -> 22516 bytes .../files/sensor/libovos05_mipi.so | Bin 0 -> 44280 bytes .../files/sensor/libps5270_mipi.so | Bin 0 -> 25264 bytes .../files/sensor/params/gc4623_mipi_attr.hex | Bin 0 -> 2924 bytes .../sensor/params/gc4623_mipi_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/gc4633_mipi_attr.hex | Bin 0 -> 2924 bytes .../sensor/params/gc4633_mipi_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/jxf22_mipi_attr.hex | Bin 0 -> 2924 bytes .../sensor/params/jxf22_mipi_night_attr.hex | Bin 0 -> 2924 bytes .../sensor/params/jxf22_mipi_wdr_attr.hex | Bin 0 -> 2924 bytes .../params/jxf22_mipi_wdr_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/jxf23_mipi_attr.hex | Bin 0 -> 2924 bytes .../sensor/params/jxf23_mipi_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/mn34425_mipi_attr.hex | Bin 0 -> 3076 bytes .../sensor/params/mn34425_mipi_night_attr.hex | Bin 0 -> 3076 bytes .../sensor/params/mn34425_mipi_wdr_attr.hex | Bin 0 -> 2924 bytes .../params/mn34425_mipi_wdr_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/ov2732_mipi_attr.hex | Bin 0 -> 4096 bytes .../sensor/params/ov2732_mipi_night_attr.hex | Bin 0 -> 2940 bytes .../files/sensor/params/ovos05_mipi_attr.hex | Bin 0 -> 3268 bytes .../sensor/params/ovos05_mipi_night_attr.hex | Bin 0 -> 2923 bytes .../sensor/params/ovos05_mipi_wdr_attr.hex | Bin 0 -> 2924 bytes .../params/ovos05_mipi_wdr_night_attr.hex | Bin 0 -> 2924 bytes .../files/sensor/params/ps5270_mipi_attr.hex | Bin 0 -> 4096 bytes .../sensor/params/ps5270_mipi_night_attr.hex | Bin 0 -> 4096 bytes .../fullhan-osdrv-fh8852v100.mk | 38 + 82 files changed, 150633 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/fh8852v100_images.yml create mode 100644 .github/workflows/fh8856v100_images.yml create mode 100644 br-ext-chip-fullhan/board/fh8852v100.config create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/fh8833v100.generic.config create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/fh8852v100.generic.config create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/fh8856v100.generic.config create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/overlay/include/linux/compiler-gcc7.h create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/patches/00_fh8852v100_kernel-3.0.8.patch create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/patches/10_overlayfs.v11.patch create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/patches/11_fix_yylloc_for_modern_computers.patch create mode 100644 br-ext-chip-fullhan/board/fh8852v100/kernel/patches/12_uimage_makefile.patch create mode 100644 br-ext-chip-fullhan/configs/unknown_unknown_fh8833v100_openipc_defconfig create mode 100644 br-ext-chip-fullhan/configs/unknown_unknown_fh8852v100_openipc_defconfig create mode 100644 br-ext-chip-fullhan/configs/unknown_unknown_fh8856v100_openipc_defconfig create mode 120000 br-ext-chip-fullhan/package/fullhan-osdrv-fh8852v100 create mode 100644 general/package/fullhan-osdrv-fh8852v100/Config.in create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852.bin create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852_human_detect.bin create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856.bin create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856_human_detect.bin create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/bgm.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/enc.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/hevc.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/isp.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/jpeg.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process_no_sc.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/rtvbus.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/vbus_ac.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/vmm.ko create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/kmod/vpu.ko create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libacw_mpi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libadvapi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libaudio_codec.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libdbi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libdci.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libdsp.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libfh_crypto_api.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libhd_arm_vbcli_linux.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libisp.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libispcore.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libmipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libvlcview.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/lib/libvmm.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/script/S95fullhan create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/script/load_fullhan create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4623_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4633_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf22_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf23_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libmipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libmn34425_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libov2732_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libovos05_mipi.so create mode 100755 general/package/fullhan-osdrv-fh8852v100/files/sensor/libps5270_mipi.so create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_night_attr.hex create mode 100644 general/package/fullhan-osdrv-fh8852v100/fullhan-osdrv-fh8852v100.mk diff --git a/.github/workflows/fh8852v100_images.yml b/.github/workflows/fh8852v100_images.yml new file mode 100644 index 00000000..f76721a9 --- /dev/null +++ b/.github/workflows/fh8852v100_images.yml @@ -0,0 +1,132 @@ +name: "FH8852v100 " + +on: + workflow_dispatch: + +jobs: + build_core: + name: OpenIPC firmware for FH8852v100 + runs-on: ubuntu-latest + + steps: + + - name: Checkout + id: checkout + uses: actions/checkout@v2 + + - name: Install build dependencies + id: install + run: | + make install-deps + mkdir -p tmp + + - name: Free disk space + id: freshing + run: | + sudo swapoff -a + sudo rm -f /swapfile + sudo apt clean + docker rmi $(docker image ls -aq) + df -h + + - name: Prepare buildroot + id: prepare + run: | + HEAD_TAG=$(git tag --points-at HEAD) + GIT_HASH=$(git rev-parse --short $GITHUB_SHA) + BRANCH_NAME=$(echo $GITHUB_REF | cut -d'/' -f 3) + if [ -z "$HEAD_TAG" ]; then + TAG_NAME="latest" + RELEASE_NAME="Development Build" + PRERELEASE=true + else + TAG_NAME=${{ github.ref }} + RELEASE_NAME="Release ${{ github.ref }}" + PRERELEASE=false + fi + echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV + echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV + echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE + make prepare + + - name: Build FH8852v100 firmware + id: build-fh8852v100-firmware + continue-on-error: true + run: | + ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.fh8852v100-br.tgz" + echo "ARCHIVE_FW=$ARCHIVE_FW" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE + make PLATFORM=fullhan BOARD=unknown_unknown_fh8852v100_openipc all + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152... FH8852V100" >> $GITHUB_ENV && exit 1 + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880... FH8852V100" >> $GITHUB_ENV && exit 1 + cd ${GITHUB_WORKSPACE}/output/images + mv uImage uImage.fh8852v100 + mv rootfs.squashfs rootfs.squashfs.fh8852v100 + md5sum rootfs.squashfs.fh8852v100 > rootfs.squashfs.fh8852v100.md5sum + md5sum uImage.fh8852v100 > uImage.fh8852v100.md5sum + tar -cvzf $ARCHIVE_FW *fh8852v100* + + - name: Build FH8852v100 SDK + id: build-fh8852v100-sdk + continue-on-error: true + run: | + ARCHIVE_SDK="${GITHUB_WORKSPACE}/output/images/arm-openipc-linux-musleabi_sdk-buildroot.tar.gz" + echo "ARCHIVE_SDK=$ARCHIVE_SDK" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE/output + make sdk + + - name: Send warning message to telegram channel + env: + TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }} + TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }} + if: steps.build-fh8852v100-firmware.outcome != 'success' || steps.build-fh8852v100-sdk.outcome != 'success' + run: | + TG_OPTIONS="-s --connect-timeout 30 --max-time 30" + TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error... FH8852V100}" + TG_HEADER=$(echo -e "\r\n$TG_NOTIFY \r\n\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9A\xA0 GitHub Actions") + curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendMessage \ + -F chat_id=$TG_CHANNEL -F text="$TG_HEADER" + + - name: Create release + uses: actions/create-release@v1 + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.TAG_NAME }} + release_name: ${{ env.RELEASE_NAME }} + draft: false + prerelease: ${{ env.PRERELEASE }} + + - name: Upload FW to release + uses: svenstaro/upload-release-action@v2 + continue-on-error: true + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.ARCHIVE_FW }} + asset_name: "openipc.fh8852v100-br.tgz" + tag: ${{ env.TAG_NAME }} + overwrite: true + + - name: Upload SDK to release + uses: svenstaro/upload-release-action@v2 + continue-on-error: true + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.ARCHIVE_SDK }} + asset_name: "arm-openipc-fh8852v100-linux-musleabi_sdk-buildroot.tar.gz" + tag: ${{ env.TAG_NAME }} + overwrite: true + + - name: Send binary file to telegram channel + env: + TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }} + TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }} + run: | + TG_OPTIONS="-s --connect-timeout 30 --max-time 30" + TG_HEADER=$(echo -e "\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9C\x85 GitHub Actions") + curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendDocument \ + -F chat_id=$TG_CHANNEL -F document="@$ARCHIVE_FW" -F caption="$TG_HEADER" diff --git a/.github/workflows/fh8852v210_images.yml b/.github/workflows/fh8852v210_images.yml index 28f5eb39..0df08a31 100644 --- a/.github/workflows/fh8852v210_images.yml +++ b/.github/workflows/fh8852v210_images.yml @@ -1,11 +1,11 @@ -name: "FH8852v200 " +name: "FH8852v210 " on: workflow_dispatch: jobs: build_core: - name: OpenIPC firmware for FH8852v200 + name: OpenIPC firmware for FH8852v210 runs-on: ubuntu-latest steps: @@ -52,25 +52,25 @@ jobs: cd $GITHUB_WORKSPACE make prepare - - name: Build FH8852v200 firmware - id: build-fh8852v200-firmware + - name: Build FH8852v210 firmware + id: build-fh8852v210-firmware continue-on-error: true run: | - ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.fh8852v200-br.tgz" + ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.fh8852v210-br.tgz" echo "ARCHIVE_FW=$ARCHIVE_FW" >> $GITHUB_ENV cd $GITHUB_WORKSPACE - make PLATFORM=fullhan BOARD=unknown_unknown_fh8852v200_openipc all - [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152... FH8852V200" >> $GITHUB_ENV && exit 1 - [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880... FH8852V200" >> $GITHUB_ENV && exit 1 + make PLATFORM=fullhan BOARD=unknown_unknown_fh8852v210_openipc all + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152... FH8852V210" >> $GITHUB_ENV && exit 1 + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880... FH8852V210" >> $GITHUB_ENV && exit 1 cd ${GITHUB_WORKSPACE}/output/images - mv uImage uImage.fh8852v200 - mv rootfs.squashfs rootfs.squashfs.fh8852v200 - md5sum rootfs.squashfs.fh8852v200 > rootfs.squashfs.fh8852v200.md5sum - md5sum uImage.fh8852v200 > uImage.fh8852v200.md5sum - tar -cvzf $ARCHIVE_FW *fh8852v200* + mv uImage uImage.fh8852v210 + mv rootfs.squashfs rootfs.squashfs.fh8852v210 + md5sum rootfs.squashfs.fh8852v210 > rootfs.squashfs.fh8852v210.md5sum + md5sum uImage.fh8852v210 > uImage.fh8852v210.md5sum + tar -cvzf $ARCHIVE_FW *fh8852v210* - - name: Build FH8852v200 SDK - id: build-fh8852v200-sdk + - name: Build FH8852v210 SDK + id: build-fh8852v210-sdk continue-on-error: true run: | ARCHIVE_SDK="${GITHUB_WORKSPACE}/output/images/arm-openipc-linux-musleabi_sdk-buildroot.tar.gz" @@ -82,10 +82,10 @@ jobs: env: TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }} TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }} - if: steps.build-fh8852v200-firmware.outcome != 'success' || steps.build-fh8852v200-sdk.outcome != 'success' + if: steps.build-fh8852v210-firmware.outcome != 'success' || steps.build-fh8852v210-sdk.outcome != 'success' run: | TG_OPTIONS="-s --connect-timeout 30 --max-time 30" - TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error... FH8852V200}" + TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error... FH8852V210}" TG_HEADER=$(echo -e "\r\n$TG_NOTIFY \r\n\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9A\xA0 GitHub Actions") curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendMessage \ -F chat_id=$TG_CHANNEL -F text="$TG_HEADER" @@ -107,7 +107,7 @@ jobs: with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: ${{ env.ARCHIVE_FW }} - asset_name: "openipc.fh8852v200-br.tgz" + asset_name: "openipc.fh8852v210-br.tgz" tag: ${{ env.TAG_NAME }} overwrite: true @@ -117,7 +117,7 @@ jobs: with: repo_token: ${{ secrets.GITHUB_TOKEN }} file: ${{ env.ARCHIVE_SDK }} - asset_name: "arm-openipc-fh8852v200-linux-musleabi_sdk-buildroot.tar.gz" + asset_name: "arm-openipc-fh8852v210-linux-musleabi_sdk-buildroot.tar.gz" tag: ${{ env.TAG_NAME }} overwrite: true diff --git a/.github/workflows/fh8856v100_images.yml b/.github/workflows/fh8856v100_images.yml new file mode 100644 index 00000000..9b1034ad --- /dev/null +++ b/.github/workflows/fh8856v100_images.yml @@ -0,0 +1,132 @@ +name: "FH8856v100 " + +on: + workflow_dispatch: + +jobs: + build_core: + name: OpenIPC firmware for FH8856v100 + runs-on: ubuntu-latest + + steps: + + - name: Checkout + id: checkout + uses: actions/checkout@v2 + + - name: Install build dependencies + id: install + run: | + make install-deps + mkdir -p tmp + + - name: Free disk space + id: freshing + run: | + sudo swapoff -a + sudo rm -f /swapfile + sudo apt clean + docker rmi $(docker image ls -aq) + df -h + + - name: Prepare buildroot + id: prepare + run: | + HEAD_TAG=$(git tag --points-at HEAD) + GIT_HASH=$(git rev-parse --short $GITHUB_SHA) + BRANCH_NAME=$(echo $GITHUB_REF | cut -d'/' -f 3) + if [ -z "$HEAD_TAG" ]; then + TAG_NAME="latest" + RELEASE_NAME="Development Build" + PRERELEASE=true + else + TAG_NAME=${{ github.ref }} + RELEASE_NAME="Release ${{ github.ref }}" + PRERELEASE=false + fi + echo "GIT_HASH=$GIT_HASH" >> $GITHUB_ENV + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV + echo "PRERELEASE=$PRERELEASE" >> $GITHUB_ENV + echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE + make prepare + + - name: Build FH8856v100 firmware + id: build-fh8856v100-firmware + continue-on-error: true + run: | + ARCHIVE_FW="${GITHUB_WORKSPACE}/output/images/openipc.fh8856v100-br.tgz" + echo "ARCHIVE_FW=$ARCHIVE_FW" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE + make PLATFORM=fullhan BOARD=unknown_unknown_fh8856v100_openipc all + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) -gt 2097152 ]] && echo "TG_NOTIFY=Warning, kernel size exceeded : $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/uImage) vs 2097152... FH8856V100" >> $GITHUB_ENV && exit 1 + [[ $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) -gt 5242880 ]] && echo "TG_NOTIFY=Warning, rootfs size exceeded - $(stat --printf="%s" ${GITHUB_WORKSPACE}/output/images/rootfs.squashfs) vs 5242880... FH8856V100" >> $GITHUB_ENV && exit 1 + cd ${GITHUB_WORKSPACE}/output/images + mv uImage uImage.fh8856v100 + mv rootfs.squashfs rootfs.squashfs.fh8856v100 + md5sum rootfs.squashfs.fh8856v100 > rootfs.squashfs.fh8856v100.md5sum + md5sum uImage.fh8856v100 > uImage.fh8856v100.md5sum + tar -cvzf $ARCHIVE_FW *fh8856v100* + + - name: Build FH8856v100 SDK + id: build-fh8856v100-sdk + continue-on-error: true + run: | + ARCHIVE_SDK="${GITHUB_WORKSPACE}/output/images/arm-openipc-linux-musleabi_sdk-buildroot.tar.gz" + echo "ARCHIVE_SDK=$ARCHIVE_SDK" >> $GITHUB_ENV + cd $GITHUB_WORKSPACE/output + make sdk + + - name: Send warning message to telegram channel + env: + TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }} + TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }} + if: steps.build-fh8856v100-firmware.outcome != 'success' || steps.build-fh8856v100-sdk.outcome != 'success' + run: | + TG_OPTIONS="-s --connect-timeout 30 --max-time 30" + TG_NOTIFY="${TG_NOTIFY:=Warning, Buildroot compiling error... FH8856V100}" + TG_HEADER=$(echo -e "\r\n$TG_NOTIFY \r\n\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9A\xA0 GitHub Actions") + curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendMessage \ + -F chat_id=$TG_CHANNEL -F text="$TG_HEADER" + + - name: Create release + uses: actions/create-release@v1 + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.TAG_NAME }} + release_name: ${{ env.RELEASE_NAME }} + draft: false + prerelease: ${{ env.PRERELEASE }} + + - name: Upload FW to release + uses: svenstaro/upload-release-action@v2 + continue-on-error: true + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.ARCHIVE_FW }} + asset_name: "openipc.fh8856v100-br.tgz" + tag: ${{ env.TAG_NAME }} + overwrite: true + + - name: Upload SDK to release + uses: svenstaro/upload-release-action@v2 + continue-on-error: true + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ${{ env.ARCHIVE_SDK }} + asset_name: "arm-openipc-fh8856v100-linux-musleabi_sdk-buildroot.tar.gz" + tag: ${{ env.TAG_NAME }} + overwrite: true + + - name: Send binary file to telegram channel + env: + TG_TOKEN: ${{ secrets.TELEGRAM_TOKEN_BOT_OPENIPC }} + TG_CHANNEL: ${{ secrets.TELEGRAM_CHANNEL_OPENIPC_DEV }} + run: | + TG_OPTIONS="-s --connect-timeout 30 --max-time 30" + TG_HEADER=$(echo -e "\r\nCommit: $GIT_HASH \r\nBranch: $BRANCH_NAME \r\nTag: $TAG_NAME \r\n\r\n\xE2\x9C\x85 GitHub Actions") + curl $TG_OPTIONS -H "Content-Type: multipart/form-data" -X POST https://api.telegram.org/bot$TG_TOKEN/sendDocument \ + -F chat_id=$TG_CHANNEL -F document="@$ARCHIVE_FW" -F caption="$TG_HEADER" diff --git a/br-ext-chip-fullhan/Config.in b/br-ext-chip-fullhan/Config.in index e0be8e34..44511960 100644 --- a/br-ext-chip-fullhan/Config.in +++ b/br-ext-chip-fullhan/Config.in @@ -1,4 +1,5 @@ source "$BR2_EXTERNAL_FULLHAN_PATH/linux/Config.ext.in" +source "$BR2_EXTERNAL_FULLHAN_PATH/package/fullhan-osdrv-fh8852v100/Config.in" source "$BR2_EXTERNAL_FULLHAN_PATH/package/fullhan-osdrv-fh8852v200/Config.in" source "$BR2_EXTERNAL_FULLHAN_PATH/package/fullhan_patcher/Config.in" source "$BR2_EXTERNAL_FULLHAN_PATH/package/aura-httpd/Config.in" diff --git a/br-ext-chip-fullhan/board/fh8852v100.config b/br-ext-chip-fullhan/board/fh8852v100.config new file mode 100644 index 00000000..bd20a71b --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100.config @@ -0,0 +1,2 @@ +MEM_START_ADDR=0xa0000000 +KERNEL_UPLOAD_ADDR=0xa0008000 diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8833v100.generic.config b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8833v100.generic.config new file mode 100644 index 00000000..f3b921ad --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8833v100.generic.config @@ -0,0 +1,1629 @@ +# +# Automatically generated make config: don't edit +# Linux/arm 3.0.8 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_SCHED_CLOCK=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS4 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +CONFIG_ARCH_FULLHAN=y +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_CPU_FH8833=y + +# +# FullHan Implementations +# + +# +# FullHan Core Type +# +# CONFIG_ARCH_FH8810 is not set +CONFIG_ARCH_FH8833=y +# CONFIG_ARCH_FH8830 is not set +# CONFIG_ARCH_FH8856 is not set +# CONFIG_ARCH_FH8626V100 is not set +# CONFIG_ARCH_WUDANG is not set +# CONFIG_ARCH_ZY2 is not set + +# +# FullHan Board Type +# +# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set +# CONFIG_FH_SIMPLE_TIMER is not set +CONFIG_MACH_FH8833=y +CONFIG_MACH_FH8833_QFN56=y +# CONFIG_MACH_FH_NAND is not set +# CONFIG_JLINK_DEBUG is not set + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V6=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_V6=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_ARM_ERRATA_411920=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_FH_DW_I2S is not set +CONFIG_FH_PINCTRL=y +CONFIG_FH_SADC_V1=y +CONFIG_FH_EFUSE=y +CONFIG_FH_CLK_MISC=y +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +CONFIG_MII=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +CONFIG_FH_GMAC=y +CONFIG_FH_GMAC_DA=y +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_FTMAC100 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTL8192SE is not set +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTL8192C_COMMON=m +# CONFIG_WL1251 is not set +# CONFIG_WL12XX_MENU is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_SERIAL_FH=y +CONFIG_SERIAL_FH_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_FH_INTERRUPT=y +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set +CONFIG_SPI_FH=y +CONFIG_SPI_FH_SLAVE=y + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set +CONFIG_GPIO_FH=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_FH_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set +# CONFIG_MFD_SUPPORT is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_FH_OTG=y +CONFIG_FH_HOST_ONLY=y +# CONFIG_FH_DEVICE_ONLY is not set +# CONFIG_USB_S3C_OTG_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_DW is not set +CONFIG_MMC_FH=y +CONFIG_MMC_FH_IDMAC=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_FH is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC is not set +CONFIG_FH_DMAC=y +CONFIG_FH_DMAC_MISC=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_PWM=y +CONFIG_PWM_FULLHAN=y + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_OVERLAYFS_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_YAFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_XATTR is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +# CONFIG_TEST_BOOT_TIME is not set +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API=y +# CONFIG_CRYPTO_USER_API_HASH is not set +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_HW=y +CONFIG_FH_AES=y +# CONFIG_FH_AES_SELF_TEST is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=m +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_AVERAGE=y diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8852v100.generic.config b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8852v100.generic.config new file mode 100644 index 00000000..ae50e766 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8852v100.generic.config @@ -0,0 +1,1634 @@ +# +# Automatically generated make config: don't edit +# Linux/arm 3.0.8 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_SCHED_CLOCK=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS4 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +CONFIG_ARCH_FULLHAN=y +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_CPU_FH8856=y + +# +# FullHan Implementations +# + +# +# FullHan Core Type +# +# CONFIG_ARCH_FH8810 is not set +# CONFIG_ARCH_FH8833 is not set +# CONFIG_ARCH_FH8830 is not set +CONFIG_ARCH_FH8856=y +# CONFIG_ARCH_FH8626V100 is not set +# CONFIG_ARCH_WUDANG is not set +# CONFIG_ARCH_ZY2 is not set + +# +# FullHan Board Type +# +# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set +# CONFIG_FH_SIMPLE_TIMER is not set +# CONFIG_MACH_FH8856 is not set +CONFIG_MACH_FH8852=y +# CONFIG_MACH_FH_NAND is not set +# CONFIG_JLINK_DEBUG is not set + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V6=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_V6=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_ARM_ERRATA_411920=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_FH_DW_I2S is not set +CONFIG_FH_PINCTRL=y +CONFIG_FH_SADC_V1=y +CONFIG_FH_SADC_V11=y +CONFIG_FH_EFUSE=y +CONFIG_FH_CLK_MISC=y +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +CONFIG_MII=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +CONFIG_FH_GMAC=y +CONFIG_FH_GMAC_DA=y +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_FTMAC100 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTL8192SE is not set +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTL8192C_COMMON=m +# CONFIG_WL1251 is not set +# CONFIG_WL12XX_MENU is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_SERIAL_FH=y +CONFIG_SERIAL_FH_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_FH_INTERRUPT=y +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set +CONFIG_SPI_FH=y +CONFIG_SPI_FH_SLAVE=y + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set +CONFIG_GPIO_FH=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_FH_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set +# CONFIG_MFD_SUPPORT is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_FH_OTG=y +CONFIG_FH_HOST_ONLY=y +# CONFIG_FH_DEVICE_ONLY is not set +# CONFIG_USB_S3C_OTG_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_DW is not set +CONFIG_MMC_FH=y +CONFIG_MMC_FH_IDMAC=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_FH_V2=y +CONFIG_USE_TSENSOR=y +# CONFIG_USE_TSENSOR_OFFSET is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC is not set +CONFIG_FH_DMAC=y +CONFIG_FH_DMAC_MISC=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_PWM=y +CONFIG_PWM_FULLHAN=y +CONFIG_FH_PWM_NUM=8 +CONFIG_PWM_FULLHAN_V20=y + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_OVERLAYFS_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_YAFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_XATTR is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +# CONFIG_TEST_BOOT_TIME is not set +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API=y +# CONFIG_CRYPTO_USER_API_HASH is not set +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_HW=y +CONFIG_FH_AES=y +# CONFIG_FH_AES_SELF_TEST is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=m +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_AVERAGE=y diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8856v100.generic.config b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8856v100.generic.config new file mode 100644 index 00000000..acd1e044 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/fh8856v100.generic.config @@ -0,0 +1,1635 @@ +# +# Automatically generated make config: don't edit +# Linux/arm 3.0.8 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_SCHED_CLOCK=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_GENERIC_IRQ_SHOW=y +# CONFIG_SPARSE_IRQ is not set + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_CGROUPS is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS4 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +CONFIG_ARCH_FULLHAN=y +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_CPU_FH8856=y + +# +# FullHan Implementations +# + +# +# FullHan Core Type +# +# CONFIG_ARCH_FH8810 is not set +# CONFIG_ARCH_FH8833 is not set +# CONFIG_ARCH_FH8830 is not set +CONFIG_ARCH_FH8856=y +# CONFIG_ARCH_FH8626V100 is not set +# CONFIG_ARCH_WUDANG is not set +# CONFIG_ARCH_ZY2 is not set + +# +# FullHan Board Type +# +# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set +# CONFIG_FH_SIMPLE_TIMER is not set +CONFIG_MACH_FH8856=y +# CONFIG_MACH_FH8852 is not set +# CONFIG_MACH_FH_NAND is not set +# CONFIG_JLINK_DEBUG is not set + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V6=y +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_V6=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_USE_DOMAINS=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_CPU_HAS_PMU=y +CONFIG_ARM_ERRATA_411920=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_MISC_DEVICES=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_FH_DW_I2S is not set +CONFIG_FH_PINCTRL=y +CONFIG_FH_SADC_V1=y +CONFIG_FH_SADC_V11=y +CONFIG_FH_EFUSE=y +CONFIG_FH_CLK_MISC=y +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +CONFIG_MII=y +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +CONFIG_FH_GMAC=y +CONFIG_FH_GMAC_DA=y +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_FTMAC100 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_ATH_COMMON is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_HOSTAP is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +# CONFIG_RTL8192SE is not set +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTL8192C_COMMON=m +# CONFIG_WL1251 is not set +# CONFIG_WL12XX_MENU is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_WAN is not set + +# +# CAIF transport drivers +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_SERIAL_FH=y +CONFIG_SERIAL_FH_CONSOLE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_RAMOOPS is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_FH_INTERRUPT=y +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set +CONFIG_SPI_FH=y +CONFIG_SPI_FH_SLAVE=y + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_BASIC_MMIO is not set +# CONFIG_GPIO_IT8761E is not set +CONFIG_GPIO_FH=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_FH_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set +# CONFIG_MFD_SUPPORT is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_FH_OTG=y +# CONFIG_FH_OTG is not set +CONFIG_FH_HOST_ONLY=y +# CONFIG_FH_DEVICE_ONLY is not set +# CONFIG_USB_S3C_OTG_HOST is not set +# CONFIG_USB_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_DW is not set +CONFIG_MMC_FH=y +CONFIG_MMC_FH_IDMAC=y +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_NFC_DEVICES is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_FH_V2=y +CONFIG_USE_TSENSOR=y +# CONFIG_USE_TSENSOR_OFFSET is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC is not set +CONFIG_FH_DMAC=y +CONFIG_FH_DMAC_MISC=y +# CONFIG_TIMB_DMA is not set +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_PWM=y +CONFIG_PWM_FULLHAN=y +CONFIG_FH_PWM_NUM=8 +CONFIG_PWM_FULLHAN_V20=y + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_OVERLAYFS_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_YAFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +# CONFIG_SQUASHFS_XATTR is not set +# CONFIG_SQUASHFS_LZO is not set +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# +# CONFIG_TEST_BOOT_TIME is not set +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_FRAME_POINTER=y +# CONFIG_LKDTM is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API=y +# CONFIG_CRYPTO_USER_API_HASH is not set +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_HW=y +CONFIG_FH_AES=y +# CONFIG_FH_AES_SELF_TEST is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=m +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_AVERAGE=y diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/overlay/include/linux/compiler-gcc7.h b/br-ext-chip-fullhan/board/fh8852v100/kernel/overlay/include/linux/compiler-gcc7.h new file mode 100644 index 00000000..613f9936 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/overlay/include/linux/compiler-gcc7.h @@ -0,0 +1,65 @@ +#ifndef __LINUX_COMPILER_H +#error "Please don't include <linux/compiler-gcc7.h> directly, include <linux/compiler.h> instead." +#endif + +#define __used __attribute__((__used__)) +#define __must_check __attribute__((warn_unused_result)) +#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) + +/* Mark functions as cold. gcc will assume any path leading to a call + to them will be unlikely. This means a lot of manual unlikely()s + are unnecessary now for any paths leading to the usual suspects + like BUG(), printk(), panic() etc. [but let's keep them for now for + older compilers] + + Early snapshots of gcc 4.3 don't support this and we can't detect this + in the preprocessor, but we can live with this because they're unreleased. + Maketime probing would be overkill here. + + gcc also has a __attribute__((__hot__)) to move hot functions into + a special section, but I don't see any sense in this right now in + the kernel context */ +#define __cold __attribute__((__cold__)) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#ifndef __CHECKER__ +# define __compiletime_warning(message) __attribute__((warning(message))) +# define __compiletime_error(message) __attribute__((error(message))) +#endif /* __CHECKER__ */ + +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() + +/* Mark a function definition as prohibited from being cloned. */ +#define __noclone __attribute__((__noclone__)) + +/* + * Tell the optimizer that something else uses this function or variable. + */ +#define __visible __attribute__((externally_visible)) + +/* + * GCC 'asm goto' miscompiles certain code sequences: + * + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 + * + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. + * + * (asm goto is automatically volatile - the naming reflects this.) + */ +#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) + +#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP +#define __HAVE_BUILTIN_BSWAP32__ +#define __HAVE_BUILTIN_BSWAP64__ +#define __HAVE_BUILTIN_BSWAP16__ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/00_fh8852v100_kernel-3.0.8.patch b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/00_fh8852v100_kernel-3.0.8.patch new file mode 100644 index 00000000..3f340849 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/00_fh8852v100_kernel-3.0.8.patch @@ -0,0 +1,141672 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 91c84cbe..28ac5c82 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -858,6 +858,20 @@ config ARCH_OMAP + help + Support for TI's OMAP platform (OMAP1/2/3/4). + ++config ARCH_FULLHAN ++ bool "FullHan" ++ select GENERIC_CLOCKEVENTS ++# select GENERIC_TIME ++ select HAVE_SCHED_CLOCK ++ select ARCH_REQUIRE_GPIOLIB ++# select ZONE_DMA ++ select CLKDEV_LOOKUP ++ select GENERIC_ALLOCATOR ++# select GENERIC_IRQ_CHIP ++ select HAVE_SYSCALL_TRACEPOINTS ++ help ++ Support for FullHan's FH platform. ++ + config PLAT_SPEAR + bool "ST SPEAr" + select ARM_AMBA +@@ -900,6 +914,8 @@ source "arch/arm/mach-dove/Kconfig" + + source "arch/arm/mach-ep93xx/Kconfig" + ++source "arch/arm/mach-fh/Kconfig" ++ + source "arch/arm/mach-footbridge/Kconfig" + + source "arch/arm/mach-gemini/Kconfig" +@@ -1577,7 +1593,8 @@ config LEDS + ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ + ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ + ARCH_AT91 || ARCH_DAVINCI || \ +- ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW ++ ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW || \ ++ ARCH_FULLHAN + help + If you say Y here, the LEDs on your machine will be used + to provide useful information about your current system status. +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index f5b2b390..20ef496c 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -139,6 +139,7 @@ machine-$(CONFIG_ARCH_DAVINCI) := davinci + machine-$(CONFIG_ARCH_DOVE) := dove + machine-$(CONFIG_ARCH_EBSA110) := ebsa110 + machine-$(CONFIG_ARCH_EP93XX) := ep93xx ++machine-$(CONFIG_ARCH_FULLHAN) := fh + machine-$(CONFIG_ARCH_GEMINI) := gemini + machine-$(CONFIG_ARCH_H720X) := h720x + machine-$(CONFIG_ARCH_INTEGRATOR) := integrator +diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c +index 832d3723..0bcea2c1 100644 +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -169,6 +169,23 @@ asmlinkage void __div0(void) + + extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); + ++#ifdef CONFIG_TEST_BOOT_TIME ++#define SET_TIMING_GPIO(port, level) \ ++ do { \ ++ unsigned char *p_gpio = (unsigned char *) 0xf0300000; \ ++ int data = *(p_gpio + 0x0004); \ ++ data |= 1 << (port); \ ++ *(p_gpio + 0x0004) = data; \ ++ data = *(p_gpio); \ ++ if ((level) == 0) \ ++ data &= ~(1 << (port)); \ ++ else \ ++ data |= 1 << (port); \ ++ *(p_gpio) = data; \ ++ } while (0) ++#else ++#define SET_TIMING_GPIO(port, level) ++#endif + + void + decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, +@@ -182,6 +199,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, + free_mem_end_ptr = free_mem_ptr_end_p; + __machine_arch_type = arch_id; + ++ SET_TIMING_GPIO(4, 1); ++ + arch_decomp_setup(); + + putstr("Uncompressing Linux..."); +diff --git a/arch/arm/configs/fh8633_defconfig b/arch/arm/configs/fh8633_defconfig +new file mode 100755 +index 00000000..ad8b0adf +--- /dev/null ++++ b/arch/arm/configs/fh8633_defconfig +@@ -0,0 +1,1932 @@ ++# ++# Automatically generated make config: don't edit ++# Linux/arm 3.0.8 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_SCHED_CLOCK=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_KTIME_SCALAR=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++CONFIG_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_LOCALVERSION="" ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TREE_PREEMPT_RCU=y ++# CONFIG_TINY_RCU is not set ++# CONFIG_TINY_PREEMPT_RCU is not set ++CONFIG_PREEMPT_RCU=y ++# CONFIG_RCU_TRACE is not set ++CONFIG_RCU_FANOUT=32 ++# CONFIG_RCU_FANOUT_EXACT is not set ++# CONFIG_TREE_RCU_TRACE is not set ++# CONFIG_RCU_BOOST is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.gz" ++CONFIG_INITRAMFS_ROOT_UID=0 ++CONFIG_INITRAMFS_ROOT_GID=0 ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_INITRAMFS_COMPRESSION_NONE=y ++# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++CONFIG_PERF_EVENTS=y ++# CONFIG_PERF_COUNTERS is not set ++CONFIG_VM_EVENT_COUNTERS=y ++# CONFIG_SLUB_DEBUG is not set ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++CONFIG_HAVE_HW_BREAKPOINT=y ++ ++# ++# GCOV-based kernel profiling ++# ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_BLOCK=y ++# CONFIG_LBDAF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_DEFAULT_NOOP=y ++CONFIG_DEFAULT_IOSCHED="noop" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_SPIN_UNLOCK is not set ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_READ_UNLOCK is not set ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++# CONFIG_INLINE_READ_UNLOCK_IRQ is not set ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++# CONFIG_INLINE_WRITE_UNLOCK is not set ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++# CONFIG_MUTEX_SPIN_ON_OWNER is not set ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_NUC93X is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS4 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_TCC_926 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++CONFIG_ARCH_FULLHAN=y ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_KEYBOARD_GPIO_POLLED is not set ++CONFIG_CPU_FH8833=y ++ ++# ++# FullHan Implementations ++# ++ ++# ++# FullHan Core Type ++# ++# CONFIG_ARCH_FH8810 is not set ++CONFIG_ARCH_FH8833=y ++# CONFIG_ARCH_FH8830 is not set ++# CONFIG_ARCH_WUDANG is not set ++ ++# ++# FullHan Board Type ++# ++# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set ++# CONFIG_FH_SIMPLE_TIMER is not set ++CONFIG_MACH_FH8833=y ++CONFIG_MACH_FH8833_QFN56=y ++# CONFIG_MACH_FH_NAND is not set ++# CONFIG_JLINK_DEBUG is not set ++ ++# ++# System MMU ++# ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V6=y ++CONFIG_CPU_32v6=y ++CONFIG_CPU_ABRT_EV6=y ++CONFIG_CPU_PABRT_V6=y ++CONFIG_CPU_CACHE_V6=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V6=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_CPU_HAS_PMU=y ++CONFIG_ARM_ERRATA_411920=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_PREEMPT_NONE is not set ++# CONFIG_PREEMPT_VOLUNTARY is not set ++CONFIG_PREEMPT=y ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++# CONFIG_HIGHMEM is not set ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_SECCOMP is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_IP_NF_QUEUE is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_IP6_NF_QUEUE is not set ++# CONFIG_IP6_NF_IPTABLES is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++ ++# ++# Classification ++# ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++# CONFIG_DCB is not set ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_PRIV=y ++CONFIG_CFG80211=y ++CONFIG_NL80211_TESTMODE=y ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_REG_DEBUG is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_WEXT=y ++CONFIG_WIRELESS_EXT_SYSFS=y ++CONFIG_LIB80211=y ++# CONFIG_LIB80211_DEBUG is not set ++CONFIG_MAC80211=y ++CONFIG_MAC80211_HAS_RC=y ++# CONFIG_MAC80211_RC_PID is not set ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++# CONFIG_MAC80211_MESH is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++# CONFIG_WIMAX is not set ++CONFIG_RFKILL=y ++# CONFIG_RFKILL_INPUT is not set ++# CONFIG_RFKILL_GPIO is not set ++# CONFIG_NET_9P is not set ++# CONFIG_CAIF is not set ++# CONFIG_CEPH_LIB is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_SM_FTL is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_DATAFLASH is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=1 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_APDS9802ALS is not set ++# CONFIG_ISL29003 is not set ++# CONFIG_ISL29020 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_SENSORS_BH1780 is not set ++# CONFIG_SENSORS_BH1770 is not set ++# CONFIG_SENSORS_APDS990X is not set ++# CONFIG_HMC6352 is not set ++# CONFIG_FH_I2S is not set ++# CONFIG_FH_DW_I2S is not set ++# CONFIG_FH_ACW is not set ++# CONFIG_FH_PWM is not set ++CONFIG_FH_PWM_NUM=8 ++# CONFIG_FH_SADC is not set ++CONFIG_FH_FIRMWARE_LOADER=m ++CONFIG_FH_EFUSE=y ++CONFIG_FH_CLK_MISC=y ++# CONFIG_DS1682 is not set ++# CONFIG_TI_DAC7512 is not set ++# CONFIG_BMP085 is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_AT24=m ++# CONFIG_EEPROM_AT25 is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_IWMC3200TOP is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST is not set ++# CONFIG_SENSORS_LIS3_SPI is not set ++# CONFIG_SENSORS_LIS3_I2C is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++# CONFIG_SCSI_TGT is not set ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++# CONFIG_BLK_DEV_SD is not set ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++# CONFIG_SCSI_SCAN_ASYNC is not set ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++CONFIG_SCSI_LOWLEVEL=y ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_ISCSI_BOOT_SYSFS is not set ++# CONFIG_LIBFC is not set ++# CONFIG_LIBFCOE is not set ++# CONFIG_SCSI_DEBUG is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_SCSI_OSD_INITIATOR is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++# CONFIG_TARGET_CORE is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++CONFIG_MII=y ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++# CONFIG_AX88796 is not set ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++CONFIG_FH_GMAC=y ++CONFIG_FH_GMAC_DA=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_ETHOC is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_DNET is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set ++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set ++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set ++# CONFIG_B44 is not set ++# CONFIG_KS8842 is not set ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_FTMAC100 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++CONFIG_WLAN=y ++# CONFIG_LIBERTAS_THINFIRM is not set ++# CONFIG_AT76C50X_USB is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_USB_NET_RNDIS_WLAN is not set ++# CONFIG_RTL8187 is not set ++CONFIG_BCMDHD=m ++CONFIG_BCMDHD_FW_PATH="/bcmdhd/fw_bcmdhd.bin" ++CONFIG_BCMDHD_NVRAM_PATH="/bcmdhd/nvram_ap6181.txt" ++CONFIG_BCMDHD_CONFIG_PATH="/bcmdhd/config.txt" ++CONFIG_BCMDHD_OOB=y ++# CONFIG_BCMDHD_SDIO_IRQ is not set ++# CONFIG_RTL8189FS_SD is not set ++# CONFIG_MRVL8801 is not set ++# CONFIG_MAC80211_HWSIM is not set ++# CONFIG_ATH_COMMON is not set ++# CONFIG_B43 is not set ++# CONFIG_B43LEGACY is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_IWM is not set ++# CONFIG_LIBERTAS is not set ++# CONFIG_P54_COMMON is not set ++# CONFIG_RT2X00 is not set ++# CONFIG_RTL8192SE is not set ++# CONFIG_RTL8192CU is not set ++# CONFIG_WL1251 is not set ++# CONFIG_WL12XX_MENU is not set ++# CONFIG_ZD1211RW is not set ++# CONFIG_MWIFIEX is not set ++# CONFIG_RTL8189ES is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_HSO is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WAN is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_PPP=m ++# CONFIG_PPP_MULTILINK is not set ++# CONFIG_PPP_FILTER is not set ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_PPP_DEFLATE=m ++# CONFIG_PPP_BSDCOMP is not set ++# CONFIG_PPP_MPPE is not set ++# CONFIG_PPPOE is not set ++# CONFIG_SLIP is not set ++CONFIG_SLHC=m ++CONFIG_NETCONSOLE=y ++CONFIG_NETPOLL=y ++CONFIG_NETPOLL_TRAP=y ++CONFIG_NET_POLL_CONTROLLER=y ++# CONFIG_ISDN is not set ++# CONFIG_PHONE is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ADP5588 is not set ++# CONFIG_KEYBOARD_ADP5589 is not set ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_QT1070 is not set ++# CONFIG_KEYBOARD_QT2160 is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_GPIO is not set ++# CONFIG_KEYBOARD_TCA6416 is not set ++# CONFIG_KEYBOARD_MATRIX is not set ++# CONFIG_KEYBOARD_MAX7359 is not set ++# CONFIG_KEYBOARD_MCS is not set ++# CONFIG_KEYBOARD_MPR121 is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_OPENCORES is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_SERIO_ALTERA_PS2 is not set ++# CONFIG_SERIO_PS2MULT is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++# CONFIG_VT_CONSOLE is not set ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++CONFIG_SERIAL_FH=y ++CONFIG_SERIAL_FH_CONSOLE=y ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_RAMOOPS is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++# CONFIG_I2C_HELPER_AUTO is not set ++# CONFIG_I2C_SMBUS is not set ++ ++# ++# I2C Algorithms ++# ++# CONFIG_I2C_ALGOBIT is not set ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_FH_INTERRUPT=y ++# CONFIG_I2C_DESIGNWARE is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++CONFIG_SPI_FH=y ++CONFIG_SPI_FH_SLAVE=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_BASIC_MMIO is not set ++# CONFIG_GPIO_IT8761E is not set ++CONFIG_GPIO_FH=y ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++ ++# ++# Native drivers ++# ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7411 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7475 is not set ++# CONFIG_SENSORS_ASC7621 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS620 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_G760A is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_GPIO_FAN is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_JC42 is not set ++# CONFIG_SENSORS_LINEAGE is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++# CONFIG_SENSORS_LM73 is not set ++# CONFIG_SENSORS_LM75 is not set ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++# CONFIG_SENSORS_LTC4151 is not set ++# CONFIG_SENSORS_LTC4215 is not set ++# CONFIG_SENSORS_LTC4245 is not set ++# CONFIG_SENSORS_LTC4261 is not set ++# CONFIG_SENSORS_LM95241 is not set ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX16065 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX6639 is not set ++# CONFIG_SENSORS_MAX6642 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_PMBUS is not set ++# CONFIG_SENSORS_SHT15 is not set ++# CONFIG_SENSORS_SHT21 is not set ++# CONFIG_SENSORS_SMM665 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_EMC1403 is not set ++# CONFIG_SENSORS_EMC2103 is not set ++# CONFIG_SENSORS_EMC6W201 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_SCH5627 is not set ++# CONFIG_SENSORS_ADS1015 is not set ++# CONFIG_SENSORS_ADS7828 is not set ++# CONFIG_SENSORS_ADS7871 is not set ++# CONFIG_SENSORS_AMC6821 is not set ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_TMP102 is not set ++# CONFIG_SENSORS_TMP401 is not set ++# CONFIG_SENSORS_TMP421 is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83795 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++# CONFIG_THERMAL is not set ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++CONFIG_FH_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++CONFIG_BCMA_POSSIBLE=y ++ ++# ++# Broadcom specific AMBA ++# ++# CONFIG_BCMA is not set ++CONFIG_MFD_SUPPORT=y ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_88PM860X is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_HTC_I2CPLD is not set ++# CONFIG_TPS6105X is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_TPS6507X is not set ++# CONFIG_MFD_TPS6586X is not set ++# CONFIG_TWL4030_CORE is not set ++# CONFIG_MFD_STMPE is not set ++# CONFIG_MFD_TC3589X is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_T7L66XB is not set ++# CONFIG_MFD_TC6387XB is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_PMIC_ADP5520 is not set ++# CONFIG_MFD_MAX8925 is not set ++# CONFIG_MFD_MAX8997 is not set ++# CONFIG_MFD_MAX8998 is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM831X_I2C is not set ++# CONFIG_MFD_WM831X_SPI is not set ++# CONFIG_MFD_WM8350_I2C is not set ++# CONFIG_MFD_WM8994 is not set ++# CONFIG_MFD_PCF50633 is not set ++# CONFIG_MFD_MC13XXX is not set ++# CONFIG_ABX500_CORE is not set ++# CONFIG_EZX_PCAP is not set ++# CONFIG_MFD_WL1273_CORE is not set ++# CONFIG_MFD_TPS65910 is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_DRM is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB=y ++CONFIG_USB_DEBUG=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_OHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++CONFIG_CONFIG_USB_FH_OTG=y ++# CONFIG_USB_S3C_OTG_HOST is not set ++# CONFIG_USB_MUSB_HDRC is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ++# ++ ++# ++# also be needed; see USB_STORAGE Help for more info ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_REALTEK is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_STORAGE_ENE_UB6250 is not set ++# CONFIG_USB_UAS is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USB_DWC2 is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_DW is not set ++CONFIG_MMC_FH=y ++CONFIG_MMC_FH_IDMAC=y ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MEMSTICK is not set ++CONFIG_NEW_LEDS=y ++# CONFIG_LEDS_CLASS is not set ++ ++# ++# LED drivers ++# ++ ++# ++# LED Triggers ++# ++# CONFIG_NFC_DEVICES is not set ++# CONFIG_ACCESSIBILITY is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_ISL12022 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_BQ32K is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set ++# CONFIG_RTC_DRV_EM3027 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T93 is not set ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++# CONFIG_RTC_DRV_PCF2123 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_MSM6242 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_RP5C01 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++CONFIG_RTC_DRV_FH=y ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++# CONFIG_DW_DMAC is not set ++CONFIG_FH_DMAC=y ++CONFIG_FH_DMAC_MISC=y ++# CONFIG_TIMB_DMA is not set ++CONFIG_DMA_ENGINE=y ++ ++# ++# DMA Clients ++# ++# CONFIG_NET_DMA is not set ++# CONFIG_ASYNC_TX_DMA is not set ++# CONFIG_DMATEST is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_PWM=y ++CONFIG_PWM_FULLHAN=y ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# CONFIG_SQUASHFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_ROOT_NFS is not set ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# CONFIG_CEPH_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=m ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=m ++ ++# ++# Kernel hacking ++# ++# CONFIG_TEST_BOOT_TIME is not set ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_MEMORY_INIT is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++CONFIG_RCU_CPU_STALL_VERBOSE=y ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++CONFIG_FTRACE=y ++# CONFIG_FUNCTION_TRACER is not set ++# CONFIG_IRQSOFF_TRACER is not set ++# CONFIG_PREEMPT_TRACER is not set ++# CONFIG_SCHED_TRACER is not set ++# CONFIG_ENABLE_DEFAULT_TRACERS is not set ++# CONFIG_FTRACE_SYSCALLS is not set ++CONFIG_BRANCH_PROFILE_NONE=y ++# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set ++# CONFIG_PROFILE_ALL_BRANCHES is not set ++# CONFIG_STACK_TRACER is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_OC_ETM is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=y ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++CONFIG_CRYPTO_ECB=y ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_ANUBIS is not set ++CONFIG_CRYPTO_ARC4=y ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++CONFIG_CRYPTO_USER_API=y ++# CONFIG_CRYPTO_USER_API_HASH is not set ++CONFIG_CRYPTO_USER_API_SKCIPHER=y ++CONFIG_CRYPTO_HW=y ++CONFIG_FH_AES=y ++# CONFIG_FH_AES_SELF_TEST is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_CRC_CCITT=m ++# CONFIG_CRC16 is not set ++CONFIG_CRC_T10DIF=m ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_DECOMPRESS_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_NLATTR=y ++CONFIG_GENERIC_ATOMIC64=y ++CONFIG_AVERAGE=y +diff --git a/arch/arm/configs/fh8852_defconfig b/arch/arm/configs/fh8852_defconfig +new file mode 100644 +index 00000000..d1bae5f8 +--- /dev/null ++++ b/arch/arm/configs/fh8852_defconfig +@@ -0,0 +1,1703 @@ ++# ++# Automatically generated make config: don't edit ++# Linux/arm 3.0.8 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_SCHED_CLOCK=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_KTIME_SCALAR=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_LOCALVERSION="" ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TINY_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.gz" ++CONFIG_INITRAMFS_ROOT_UID=0 ++CONFIG_INITRAMFS_ROOT_GID=0 ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_INITRAMFS_COMPRESSION_NONE=y ++# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++# CONFIG_PERF_EVENTS is not set ++# CONFIG_PERF_COUNTERS is not set ++CONFIG_VM_EVENT_COUNTERS=y ++# CONFIG_SLUB_DEBUG is not set ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_BLOCK=y ++# CONFIG_LBDAF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_DEFAULT_NOOP=y ++CONFIG_DEFAULT_IOSCHED="noop" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++# CONFIG_MUTEX_SPIN_ON_OWNER is not set ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_NUC93X is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS4 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_TCC_926 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++CONFIG_ARCH_FULLHAN=y ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_GPIO_PCA953X is not set ++CONFIG_CPU_FH8856=y ++ ++# ++# FullHan Implementations ++# ++ ++# ++# FullHan Core Type ++# ++# CONFIG_ARCH_FH8810 is not set ++# CONFIG_ARCH_FH8833 is not set ++# CONFIG_ARCH_FH8830 is not set ++CONFIG_ARCH_FH8856=y ++# CONFIG_ARCH_WUDANG is not set ++ ++# ++# FullHan Board Type ++# ++# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set ++# CONFIG_FH_SIMPLE_TIMER is not set ++# CONFIG_MACH_FH8856 is not set ++CONFIG_MACH_FH8852=y ++# CONFIG_MACH_FH_NAND is not set ++# CONFIG_JLINK_DEBUG is not set ++ ++# ++# System MMU ++# ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V6=y ++CONFIG_CPU_32v6=y ++CONFIG_CPU_ABRT_EV6=y ++CONFIG_CPU_PABRT_V6=y ++CONFIG_CPU_CACHE_V6=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V6=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_CPU_HAS_PMU=y ++CONFIG_ARM_ERRATA_411920=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++# CONFIG_HIGHMEM is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_SECCOMP is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_IP_NF_QUEUE is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_IP6_NF_QUEUE is not set ++# CONFIG_IP6_NF_IPTABLES is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++ ++# ++# Classification ++# ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++# CONFIG_DCB is not set ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_PRIV=y ++CONFIG_CFG80211=y ++CONFIG_NL80211_TESTMODE=y ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_REG_DEBUG is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_WEXT=y ++CONFIG_WIRELESS_EXT_SYSFS=y ++CONFIG_LIB80211=y ++# CONFIG_LIB80211_DEBUG is not set ++CONFIG_MAC80211=y ++CONFIG_MAC80211_HAS_RC=y ++# CONFIG_MAC80211_RC_PID is not set ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++# CONFIG_MAC80211_MESH is not set ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++# CONFIG_WIMAX is not set ++CONFIG_RFKILL=y ++# CONFIG_RFKILL_INPUT is not set ++# CONFIG_RFKILL_GPIO is not set ++# CONFIG_NET_9P is not set ++# CONFIG_CAIF is not set ++# CONFIG_CEPH_LIB is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_SM_FTL is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_DATAFLASH is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=1 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_APDS9802ALS is not set ++# CONFIG_ISL29003 is not set ++# CONFIG_ISL29020 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_SENSORS_BH1780 is not set ++# CONFIG_SENSORS_BH1770 is not set ++# CONFIG_SENSORS_APDS990X is not set ++# CONFIG_HMC6352 is not set ++# CONFIG_FH_DW_I2S is not set ++# CONFIG_FH_ACW is not set ++# CONFIG_FH_PWM is not set ++CONFIG_FH_PWM_NUM=8 ++CONFIG_FH_PINCTRL=y ++CONFIG_FH_SADC_V1=y ++CONFIG_FH_SADC_V11=y ++CONFIG_FH_EFUSE=y ++CONFIG_FH_CLK_MISC=y ++# CONFIG_DS1682 is not set ++# CONFIG_TI_DAC7512 is not set ++# CONFIG_BMP085 is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_AT24=m ++# CONFIG_EEPROM_AT25 is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_IWMC3200TOP is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST is not set ++# CONFIG_SENSORS_LIS3_SPI is not set ++# CONFIG_SENSORS_LIS3_I2C is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++# CONFIG_SCSI is not set ++# CONFIG_SCSI_DMA is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++CONFIG_MII=y ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++# CONFIG_AX88796 is not set ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++CONFIG_FH_GMAC=y ++CONFIG_FH_GMAC_DA=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_ETHOC is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_DNET is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set ++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set ++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set ++# CONFIG_B44 is not set ++# CONFIG_KS8842 is not set ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_FTMAC100 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++CONFIG_WLAN=y ++# CONFIG_LIBERTAS_THINFIRM is not set ++# CONFIG_AT76C50X_USB is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_USB_NET_RNDIS_WLAN is not set ++# CONFIG_RTL8187 is not set ++# CONFIG_MAC80211_HWSIM is not set ++# CONFIG_ATH_COMMON is not set ++# CONFIG_B43 is not set ++# CONFIG_B43LEGACY is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_IWM is not set ++# CONFIG_LIBERTAS is not set ++# CONFIG_P54_COMMON is not set ++# CONFIG_RT2X00 is not set ++# CONFIG_RTL8192SE is not set ++# CONFIG_RTL8192CU is not set ++# CONFIG_WL1251 is not set ++# CONFIG_WL12XX_MENU is not set ++# CONFIG_ZD1211RW is not set ++# CONFIG_MWIFIEX is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_HSO is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WAN is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_PPP=m ++# CONFIG_PPP_MULTILINK is not set ++# CONFIG_PPP_FILTER is not set ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_PPP_DEFLATE=m ++# CONFIG_PPP_BSDCOMP is not set ++# CONFIG_PPP_MPPE is not set ++# CONFIG_PPPOE is not set ++# CONFIG_SLIP is not set ++CONFIG_SLHC=m ++CONFIG_NETCONSOLE=y ++CONFIG_NETPOLL=y ++CONFIG_NETPOLL_TRAP=y ++CONFIG_NET_POLL_CONTROLLER=y ++# CONFIG_ISDN is not set ++# CONFIG_PHONE is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++# CONFIG_VT_CONSOLE is not set ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++CONFIG_SERIAL_FH=y ++CONFIG_SERIAL_FH_CONSOLE=y ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_RAMOOPS is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++# CONFIG_I2C_HELPER_AUTO is not set ++# CONFIG_I2C_SMBUS is not set ++ ++# ++# I2C Algorithms ++# ++# CONFIG_I2C_ALGOBIT is not set ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_FH_INTERRUPT=y ++# CONFIG_I2C_DESIGNWARE is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++CONFIG_SPI_FH=y ++CONFIG_SPI_FH_SLAVE=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_BASIC_MMIO is not set ++# CONFIG_GPIO_IT8761E is not set ++CONFIG_GPIO_FH=y ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++CONFIG_FH_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++CONFIG_BCMA_POSSIBLE=y ++ ++# ++# Broadcom specific AMBA ++# ++# CONFIG_BCMA is not set ++# CONFIG_MFD_SUPPORT is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_DRM is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB=y ++CONFIG_USB_DEBUG=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_OHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++CONFIG_USB_FH_OTG=y ++CONFIG_FH_HOST_ONLY=y ++# CONFIG_FH_DEVICE_ONLY is not set ++# CONFIG_USB_S3C_OTG_HOST is not set ++# CONFIG_USB_MUSB_HDRC is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ++# ++ ++# ++# also be needed; see USB_STORAGE Help for more info ++# ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_DW is not set ++CONFIG_MMC_FH=y ++CONFIG_MMC_FH_IDMAC=y ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_NFC_DEVICES is not set ++# CONFIG_ACCESSIBILITY is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_ISL12022 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_BQ32K is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set ++# CONFIG_RTC_DRV_EM3027 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T93 is not set ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++# CONFIG_RTC_DRV_PCF2123 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_MSM6242 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_RP5C01 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++CONFIG_RTC_DRV_FH_V2=y ++CONFIG_USE_TSENSOR=y ++# CONFIG_USE_TSENSOR_OFFSET is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++# CONFIG_DW_DMAC is not set ++CONFIG_FH_DMAC=y ++CONFIG_FH_DMAC_MISC=y ++# CONFIG_TIMB_DMA is not set ++CONFIG_DMA_ENGINE=y ++ ++# ++# DMA Clients ++# ++# CONFIG_NET_DMA is not set ++# CONFIG_ASYNC_TX_DMA is not set ++# CONFIG_DMATEST is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_PWM=y ++CONFIG_PWM_FULLHAN=y ++CONFIG_PWM_FULLHAN_V20=y ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# CONFIG_SQUASHFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_ROOT_NFS is not set ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# CONFIG_CEPH_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=m ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=m ++ ++# ++# Kernel hacking ++# ++# CONFIG_TEST_BOOT_TIME is not set ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_MEMORY_INIT is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_LKDTM is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_OC_ETM is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=y ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++CONFIG_CRYPTO_ECB=y ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_ANUBIS is not set ++CONFIG_CRYPTO_ARC4=y ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++CONFIG_CRYPTO_USER_API=y ++# CONFIG_CRYPTO_USER_API_HASH is not set ++CONFIG_CRYPTO_USER_API_SKCIPHER=y ++CONFIG_CRYPTO_HW=y ++CONFIG_FH_AES=y ++# CONFIG_FH_AES_SELF_TEST is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_CRC_CCITT=m ++# CONFIG_CRC16 is not set ++CONFIG_CRC_T10DIF=m ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_DECOMPRESS_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_NLATTR=y ++CONFIG_GENERIC_ATOMIC64=y ++CONFIG_AVERAGE=y +diff --git a/arch/arm/configs/fh8856_defconfig b/arch/arm/configs/fh8856_defconfig +new file mode 100644 +index 00000000..f5f61f9d +--- /dev/null ++++ b/arch/arm/configs/fh8856_defconfig +@@ -0,0 +1,1705 @@ ++# ++# Automatically generated make config: don't edit ++# Linux/arm 3.0.8 Kernel Configuration ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_HAVE_SCHED_CLOCK=y ++CONFIG_GENERIC_GPIO=y ++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_KTIME_SCALAR=y ++CONFIG_HAVE_PROC_CPU=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_VECTORS_BASE=0xffff0000 ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_HAVE_IRQ_WORK=y ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="" ++CONFIG_LOCALVERSION="" ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_HAVE_KERNEL_GZIP=y ++CONFIG_HAVE_KERNEL_LZMA=y ++CONFIG_HAVE_KERNEL_LZO=y ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_LZMA is not set ++# CONFIG_KERNEL_LZO is not set ++CONFIG_DEFAULT_HOSTNAME="(none)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_FHANDLE is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_HAVE_GENERIC_HARDIRQS=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_HAVE_SPARSE_IRQ=y ++CONFIG_GENERIC_IRQ_SHOW=y ++# CONFIG_SPARSE_IRQ is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_TINY_RCU=y ++# CONFIG_PREEMPT_RCU is not set ++# CONFIG_RCU_TRACE is not set ++# CONFIG_TREE_RCU_TRACE is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_NAMESPACES is not set ++# CONFIG_SCHED_AUTOGROUP is not set ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.gz" ++CONFIG_INITRAMFS_ROOT_UID=0 ++CONFIG_INITRAMFS_ROOT_GID=0 ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++CONFIG_INITRAMFS_COMPRESSION_NONE=y ++# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set ++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_EXPERT=y ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_EMBEDDED=y ++CONFIG_HAVE_PERF_EVENTS=y ++CONFIG_PERF_USE_VMALLOC=y ++ ++# ++# Kernel Performance Events And Counters ++# ++# CONFIG_PERF_EVENTS is not set ++# CONFIG_PERF_COUNTERS is not set ++CONFIG_VM_EVENT_COUNTERS=y ++# CONFIG_SLUB_DEBUG is not set ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y ++CONFIG_HAVE_CLK=y ++CONFIG_HAVE_DMA_API_DEBUG=y ++ ++# ++# GCOV-based kernel profiling ++# ++# CONFIG_GCOV_KERNEL is not set ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_RT_MUTEXES=y ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_BLOCK=y ++# CONFIG_LBDAF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_DEFAULT_NOOP=y ++CONFIG_DEFAULT_IOSCHED="noop" ++# CONFIG_INLINE_SPIN_TRYLOCK is not set ++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK is not set ++# CONFIG_INLINE_SPIN_LOCK_BH is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set ++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set ++CONFIG_INLINE_SPIN_UNLOCK=y ++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set ++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y ++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_READ_TRYLOCK is not set ++# CONFIG_INLINE_READ_LOCK is not set ++# CONFIG_INLINE_READ_LOCK_BH is not set ++# CONFIG_INLINE_READ_LOCK_IRQ is not set ++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set ++CONFIG_INLINE_READ_UNLOCK=y ++# CONFIG_INLINE_READ_UNLOCK_BH is not set ++CONFIG_INLINE_READ_UNLOCK_IRQ=y ++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set ++# CONFIG_INLINE_WRITE_TRYLOCK is not set ++# CONFIG_INLINE_WRITE_LOCK is not set ++# CONFIG_INLINE_WRITE_LOCK_BH is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set ++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set ++CONFIG_INLINE_WRITE_UNLOCK=y ++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set ++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y ++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set ++# CONFIG_MUTEX_SPIN_ON_OWNER is not set ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_MMU=y ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_VEXPRESS is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_BCMRING is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CNS3XXX is not set ++# CONFIG_ARCH_GEMINI is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_MXS is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_DOVE is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_LPC32XX is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_MMP is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_W90X900 is not set ++# CONFIG_ARCH_NUC93X is not set ++# CONFIG_ARCH_TEGRA is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_MSM is not set ++# CONFIG_ARCH_SHMOBILE is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_S3C64XX is not set ++# CONFIG_ARCH_S5P64X0 is not set ++# CONFIG_ARCH_S5PC100 is not set ++# CONFIG_ARCH_S5PV210 is not set ++# CONFIG_ARCH_EXYNOS4 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_TCC_926 is not set ++# CONFIG_ARCH_U300 is not set ++# CONFIG_ARCH_U8500 is not set ++# CONFIG_ARCH_NOMADIK is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++CONFIG_ARCH_FULLHAN=y ++# CONFIG_PLAT_SPEAR is not set ++# CONFIG_ARCH_VT8500 is not set ++# CONFIG_GPIO_PCA953X is not set ++CONFIG_CPU_FH8856=y ++ ++# ++# FullHan Implementations ++# ++ ++# ++# FullHan Core Type ++# ++# CONFIG_ARCH_FH8810 is not set ++# CONFIG_ARCH_FH8833 is not set ++# CONFIG_ARCH_FH8830 is not set ++CONFIG_ARCH_FH8856=y ++# CONFIG_ARCH_FHZY2 is not set ++# CONFIG_ARCH_WUDANG is not set ++ ++# ++# FullHan Board Type ++# ++# CONFIG_USE_PTS_AS_CLOCKSOURCE is not set ++# CONFIG_FH_SIMPLE_TIMER is not set ++CONFIG_MACH_FH8856=y ++# CONFIG_MACH_FH8852 is not set ++# CONFIG_MACH_FH_NAND is not set ++# CONFIG_JLINK_DEBUG is not set ++ ++# ++# System MMU ++# ++ ++# ++# Processor Type ++# ++CONFIG_CPU_V6=y ++CONFIG_CPU_32v6=y ++CONFIG_CPU_ABRT_EV6=y ++CONFIG_CPU_PABRT_V6=y ++CONFIG_CPU_CACHE_V6=y ++CONFIG_CPU_CACHE_VIPT=y ++CONFIG_CPU_COPY_V6=y ++CONFIG_CPU_TLB_V6=y ++CONFIG_CPU_HAS_ASID=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++CONFIG_CPU_USE_DOMAINS=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_BPREDICT_DISABLE is not set ++CONFIG_ARM_L1_CACHE_SHIFT=5 ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_CPU_HAS_PMU=y ++CONFIG_ARM_ERRATA_411920=y ++ ++# ++# Bus support ++# ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++CONFIG_PREEMPT_NONE=y ++# CONFIG_PREEMPT_VOLUNTARY is not set ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_HAVE_ARCH_PFN_VALID=y ++# CONFIG_HIGHMEM is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_HAVE_MEMBLOCK=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++# CONFIG_COMPACTION is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++# CONFIG_KSM is not set ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_NEED_PER_CPU_KM=y ++# CONFIG_CLEANCACHE is not set ++CONFIG_FORCE_MAX_ZONEORDER=11 ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++# CONFIG_UACCESS_WITH_MEMCPY is not set ++# CONFIG_SECCOMP is not set ++# CONFIG_CC_STACKPROTECTOR is not set ++# CONFIG_DEPRECATED_PARAM_STRUCT is not set ++ ++# ++# Boot options ++# ++# CONFIG_USE_OF is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++# CONFIG_CRASH_DUMP is not set ++# CONFIG_AUTO_ZRELADDR is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y ++CONFIG_HAVE_AOUT=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++CONFIG_PM_SLEEP=y ++# CONFIG_PM_RUNTIME is not set ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE_DEMUX is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++# CONFIG_IPV6_SIT_6RD is not set ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set ++CONFIG_NETFILTER=y ++# CONFIG_NETFILTER_DEBUG is not set ++CONFIG_NETFILTER_ADVANCED=y ++ ++# ++# Core Netfilter Configuration ++# ++# CONFIG_NETFILTER_NETLINK_QUEUE is not set ++# CONFIG_NETFILTER_NETLINK_LOG is not set ++# CONFIG_NF_CONNTRACK is not set ++# CONFIG_NETFILTER_XTABLES is not set ++# CONFIG_IP_VS is not set ++ ++# ++# IP: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV4 is not set ++# CONFIG_IP_NF_QUEUE is not set ++# CONFIG_IP_NF_IPTABLES is not set ++# CONFIG_IP_NF_ARPTABLES is not set ++ ++# ++# IPv6: Netfilter Configuration ++# ++# CONFIG_NF_DEFRAG_IPV6 is not set ++# CONFIG_IP6_NF_QUEUE is not set ++# CONFIG_IP6_NF_IPTABLES is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_RDS is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_L2TP is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++# CONFIG_VLAN_8021Q is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_PHONET is not set ++# CONFIG_IEEE802154 is not set ++CONFIG_NET_SCHED=y ++ ++# ++# Queueing/Scheduling ++# ++# CONFIG_NET_SCH_CBQ is not set ++# CONFIG_NET_SCH_HTB is not set ++# CONFIG_NET_SCH_HFSC is not set ++# CONFIG_NET_SCH_PRIO is not set ++# CONFIG_NET_SCH_MULTIQ is not set ++# CONFIG_NET_SCH_RED is not set ++# CONFIG_NET_SCH_SFB is not set ++# CONFIG_NET_SCH_SFQ is not set ++# CONFIG_NET_SCH_TEQL is not set ++# CONFIG_NET_SCH_TBF is not set ++# CONFIG_NET_SCH_GRED is not set ++# CONFIG_NET_SCH_DSMARK is not set ++# CONFIG_NET_SCH_NETEM is not set ++# CONFIG_NET_SCH_DRR is not set ++# CONFIG_NET_SCH_MQPRIO is not set ++# CONFIG_NET_SCH_CHOKE is not set ++# CONFIG_NET_SCH_QFQ is not set ++ ++# ++# Classification ++# ++# CONFIG_NET_CLS_BASIC is not set ++# CONFIG_NET_CLS_TCINDEX is not set ++# CONFIG_NET_CLS_ROUTE4 is not set ++# CONFIG_NET_CLS_FW is not set ++# CONFIG_NET_CLS_U32 is not set ++# CONFIG_NET_CLS_RSVP is not set ++# CONFIG_NET_CLS_RSVP6 is not set ++# CONFIG_NET_CLS_FLOW is not set ++# CONFIG_NET_EMATCH is not set ++# CONFIG_NET_CLS_ACT is not set ++CONFIG_NET_SCH_FIFO=y ++# CONFIG_DCB is not set ++CONFIG_DNS_RESOLVER=y ++# CONFIG_BATMAN_ADV is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_PRIV=y ++CONFIG_CFG80211=y ++CONFIG_NL80211_TESTMODE=y ++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set ++# CONFIG_CFG80211_REG_DEBUG is not set ++CONFIG_CFG80211_DEFAULT_PS=y ++# CONFIG_CFG80211_DEBUGFS is not set ++# CONFIG_CFG80211_INTERNAL_REGDB is not set ++CONFIG_CFG80211_WEXT=y ++CONFIG_WIRELESS_EXT_SYSFS=y ++CONFIG_LIB80211=y ++# CONFIG_LIB80211_DEBUG is not set ++CONFIG_MAC80211=y ++CONFIG_MAC80211_HAS_RC=y ++# CONFIG_MAC80211_RC_PID is not set ++CONFIG_MAC80211_RC_MINSTREL=y ++CONFIG_MAC80211_RC_MINSTREL_HT=y ++CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y ++CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" ++# CONFIG_MAC80211_MESH is not set ++# CONFIG_MAC80211_DEBUGFS is not set ++# CONFIG_MAC80211_DEBUG_MENU is not set ++# CONFIG_WIMAX is not set ++CONFIG_RFKILL=y ++# CONFIG_RFKILL_INPUT is not set ++# CONFIG_RFKILL_GPIO is not set ++# CONFIG_NET_9P is not set ++# CONFIG_CAIF is not set ++# CONFIG_CEPH_LIB is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/mdev" ++CONFIG_DEVTMPFS=y ++# CONFIG_DEVTMPFS_MOUNT is not set ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++# CONFIG_CONNECTOR is not set ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++# CONFIG_MTD_TESTS is not set ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_SM_FTL is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_DATAFLASH is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SST25L is not set ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# LPDDR flash memory drivers ++# ++# CONFIG_MTD_LPDDR is not set ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++# CONFIG_BLK_DEV_LOOP is not set ++ ++# ++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected ++# ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=1 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++# CONFIG_MG_DISK is not set ++# CONFIG_BLK_DEV_RBD is not set ++# CONFIG_SENSORS_LIS3LV02D is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_AD525X_DPOT is not set ++# CONFIG_INTEL_MID_PTI is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_APDS9802ALS is not set ++# CONFIG_ISL29003 is not set ++# CONFIG_ISL29020 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_SENSORS_BH1780 is not set ++# CONFIG_SENSORS_BH1770 is not set ++# CONFIG_SENSORS_APDS990X is not set ++# CONFIG_HMC6352 is not set ++# CONFIG_FH_DW_I2S is not set ++# CONFIG_FH_ACW is not set ++# CONFIG_FH_PWM is not set ++CONFIG_FH_PWM_NUM=8 ++CONFIG_FH_PINCTRL=y ++CONFIG_FH_SADC_V1=y ++CONFIG_FH_SADC_V11=y ++CONFIG_FH_EFUSE=y ++CONFIG_FH_CLK_MISC=y ++# CONFIG_DS1682 is not set ++# CONFIG_TI_DAC7512 is not set ++# CONFIG_BMP085 is not set ++# CONFIG_C2PORT is not set ++ ++# ++# EEPROM support ++# ++CONFIG_EEPROM_AT24=m ++# CONFIG_EEPROM_AT25 is not set ++# CONFIG_EEPROM_LEGACY is not set ++# CONFIG_EEPROM_MAX6875 is not set ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_IWMC3200TOP is not set ++ ++# ++# Texas Instruments shared transport line discipline ++# ++# CONFIG_TI_ST is not set ++# CONFIG_SENSORS_LIS3_SPI is not set ++# CONFIG_SENSORS_LIS3_I2C is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI_MOD=y ++# CONFIG_RAID_ATTRS is not set ++# CONFIG_SCSI is not set ++# CONFIG_SCSI_DMA is not set ++# CONFIG_SCSI_NETLINK is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++CONFIG_MII=y ++CONFIG_PHYLIB=y ++ ++# ++# MII PHY device drivers ++# ++# CONFIG_MARVELL_PHY is not set ++# CONFIG_DAVICOM_PHY is not set ++# CONFIG_QSEMI_PHY is not set ++# CONFIG_LXT_PHY is not set ++# CONFIG_CICADA_PHY is not set ++# CONFIG_VITESSE_PHY is not set ++# CONFIG_SMSC_PHY is not set ++# CONFIG_BROADCOM_PHY is not set ++# CONFIG_ICPLUS_PHY is not set ++# CONFIG_REALTEK_PHY is not set ++# CONFIG_NATIONAL_PHY is not set ++# CONFIG_STE10XP is not set ++# CONFIG_LSI_ET1011C_PHY is not set ++# CONFIG_MICREL_PHY is not set ++# CONFIG_FIXED_PHY is not set ++# CONFIG_MDIO_BITBANG is not set ++CONFIG_NET_ETHERNET=y ++# CONFIG_AX88796 is not set ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++CONFIG_FH_GMAC=y ++CONFIG_FH_GMAC_DA=y ++# CONFIG_ENC28J60 is not set ++# CONFIG_ETHOC is not set ++# CONFIG_SMC911X is not set ++# CONFIG_SMSC911X is not set ++# CONFIG_DNET is not set ++# CONFIG_IBM_NEW_EMAC_ZMII is not set ++# CONFIG_IBM_NEW_EMAC_RGMII is not set ++# CONFIG_IBM_NEW_EMAC_TAH is not set ++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set ++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set ++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set ++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set ++# CONFIG_B44 is not set ++# CONFIG_KS8842 is not set ++# CONFIG_KS8851 is not set ++# CONFIG_KS8851_MLL is not set ++# CONFIG_FTMAC100 is not set ++# CONFIG_NETDEV_1000 is not set ++# CONFIG_NETDEV_10000 is not set ++CONFIG_WLAN=y ++# CONFIG_LIBERTAS_THINFIRM is not set ++# CONFIG_AT76C50X_USB is not set ++# CONFIG_USB_ZD1201 is not set ++# CONFIG_USB_NET_RNDIS_WLAN is not set ++# CONFIG_RTL8187 is not set ++# CONFIG_MAC80211_HWSIM is not set ++# CONFIG_ATH_COMMON is not set ++# CONFIG_B43 is not set ++# CONFIG_B43LEGACY is not set ++# CONFIG_HOSTAP is not set ++# CONFIG_IWM is not set ++# CONFIG_LIBERTAS is not set ++# CONFIG_P54_COMMON is not set ++# CONFIG_RT2X00 is not set ++# CONFIG_RTL8192SE is not set ++# CONFIG_RTL8192CU is not set ++# CONFIG_WL1251 is not set ++# CONFIG_WL12XX_MENU is not set ++# CONFIG_ZD1211RW is not set ++# CONFIG_MWIFIEX is not set ++ ++# ++# Enable WiMAX (Networking options) to see the WiMAX drivers ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_HSO is not set ++# CONFIG_USB_IPHETH is not set ++# CONFIG_WAN is not set ++ ++# ++# CAIF transport drivers ++# ++CONFIG_PPP=m ++# CONFIG_PPP_MULTILINK is not set ++# CONFIG_PPP_FILTER is not set ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_PPP_DEFLATE=m ++# CONFIG_PPP_BSDCOMP is not set ++# CONFIG_PPP_MPPE is not set ++# CONFIG_PPPOE is not set ++# CONFIG_SLIP is not set ++CONFIG_SLHC=m ++CONFIG_NETCONSOLE=y ++CONFIG_NETPOLL=y ++CONFIG_NETPOLL_TRAP=y ++CONFIG_NET_POLL_CONTROLLER=y ++# CONFIG_ISDN is not set ++# CONFIG_PHONE is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++# CONFIG_INPUT_SPARSEKMAP is not set ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++# CONFIG_VT_CONSOLE is not set ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_UNIX98_PTYS=y ++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_SERIAL_NONSTANDARD is not set ++# CONFIG_N_GSM is not set ++# CONFIG_TRACE_SINK is not set ++CONFIG_DEVKMEM=y ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_MAX3100 is not set ++# CONFIG_SERIAL_MAX3107 is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++# CONFIG_SERIAL_TIMBERDALE is not set ++# CONFIG_SERIAL_ALTERA_JTAGUART is not set ++# CONFIG_SERIAL_ALTERA_UART is not set ++# CONFIG_SERIAL_IFX6X60 is not set ++# CONFIG_SERIAL_XILINX_PS_UART is not set ++CONFIG_SERIAL_FH=y ++CONFIG_SERIAL_FH_CONSOLE=y ++# CONFIG_TTY_PRINTK is not set ++# CONFIG_HVC_DCC is not set ++# CONFIG_IPMI_HANDLER is not set ++# CONFIG_HW_RANDOM is not set ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++# CONFIG_RAMOOPS is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_COMPAT=y ++CONFIG_I2C_CHARDEV=y ++# CONFIG_I2C_MUX is not set ++# CONFIG_I2C_HELPER_AUTO is not set ++# CONFIG_I2C_SMBUS is not set ++ ++# ++# I2C Algorithms ++# ++# CONFIG_I2C_ALGOBIT is not set ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++CONFIG_I2C_FH_INTERRUPT=y ++# CONFIG_I2C_DESIGNWARE is not set ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_PXA_PCI is not set ++# CONFIG_I2C_SIMTEC is not set ++# CONFIG_I2C_XILINX is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_DIOLAN_U2C is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++# CONFIG_SPI_ALTERA is not set ++# CONFIG_SPI_BITBANG is not set ++# CONFIG_SPI_GPIO is not set ++# CONFIG_SPI_OC_TINY is not set ++# CONFIG_SPI_PXA2XX_PCI is not set ++# CONFIG_SPI_XILINX is not set ++# CONFIG_SPI_DESIGNWARE is not set ++CONFIG_SPI_FH=y ++CONFIG_SPI_FH_SLAVE=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_SPIDEV=y ++# CONFIG_SPI_TLE62X0 is not set ++ ++# ++# PPS support ++# ++# CONFIG_PPS is not set ++ ++# ++# PPS generators support ++# ++ ++# ++# PTP clock support ++# ++ ++# ++# Enable Device Drivers -> PPS to see the PTP clock options. ++# ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO drivers: ++# ++# CONFIG_GPIO_BASIC_MMIO is not set ++# CONFIG_GPIO_IT8761E is not set ++CONFIG_GPIO_FH=y ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX7300 is not set ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCF857X is not set ++# CONFIG_GPIO_SX150X is not set ++# CONFIG_GPIO_ADP5588 is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_GPIO_MC33880 is not set ++# CONFIG_GPIO_74X164 is not set ++ ++# ++# AC97 GPIO expanders: ++# ++ ++# ++# MODULbus GPIO expanders: ++# ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++# CONFIG_HWMON is not set ++# CONFIG_THERMAL is not set ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++# CONFIG_MAX63XX_WATCHDOG is not set ++CONFIG_FH_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++CONFIG_BCMA_POSSIBLE=y ++ ++# ++# Broadcom specific AMBA ++# ++# CONFIG_BCMA is not set ++# CONFIG_MFD_SUPPORT is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_MEDIA_SUPPORT is not set ++ ++# ++# Graphics support ++# ++# CONFIG_DRM is not set ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++# CONFIG_USB_ARCH_HAS_EHCI is not set ++CONFIG_USB=y ++CONFIG_USB_DEBUG=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG_WHITELIST is not set ++# CONFIG_USB_OTG_BLACKLIST_HUB is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_OXU210HP_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_ISP1760_HCD is not set ++# CONFIG_USB_ISP1362_HCD is not set ++# CONFIG_USB_OHCI_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++CONFIG_USB_FH_OTG=y ++# CONFIG_FH_OTG is not set ++CONFIG_FH_HOST_ONLY=y ++# CONFIG_FH_DEVICE_ONLY is not set ++# CONFIG_USB_S3C_OTG_HOST is not set ++# CONFIG_USB_MUSB_HDRC is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may ++# ++ ++# ++# also be needed; see USB_STORAGE Help for more info ++# ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_YUREX is not set ++# CONFIG_USB_GADGET is not set ++ ++# ++# OTG and related infrastructure ++# ++# CONFIG_USB_GPIO_VBUS is not set ++# CONFIG_USB_ULPI is not set ++# CONFIG_NOP_USB_XCEIV is not set ++CONFIG_MMC=y ++# CONFIG_MMC_DEBUG is not set ++# CONFIG_MMC_UNSAFE_RESUME is not set ++# CONFIG_MMC_CLKGATE is not set ++ ++# ++# MMC/SD/SDIO Card Drivers ++# ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMC_BLOCK_BOUNCE=y ++# CONFIG_SDIO_UART is not set ++# CONFIG_MMC_TEST is not set ++ ++# ++# MMC/SD/SDIO Host Controller Drivers ++# ++# CONFIG_MMC_SDHCI is not set ++# CONFIG_MMC_SPI is not set ++# CONFIG_MMC_DW is not set ++CONFIG_MMC_FH=y ++CONFIG_MMC_FH_IDMAC=y ++# CONFIG_MMC_VUB300 is not set ++# CONFIG_MMC_USHC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_NEW_LEDS is not set ++# CONFIG_NFC_DEVICES is not set ++# CONFIG_ACCESSIBILITY is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_DS3232 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_ISL12022 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_BQ32K is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++# CONFIG_RTC_DRV_RX8025 is not set ++# CONFIG_RTC_DRV_EM3027 is not set ++# CONFIG_RTC_DRV_RV3029C2 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T93 is not set ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++# CONFIG_RTC_DRV_PCF2123 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_MSM6242 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_RP5C01 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++CONFIG_RTC_DRV_FH_V2=y ++CONFIG_USE_TSENSOR=y ++# CONFIG_USE_TSENSOR_OFFSET is not set ++CONFIG_DMADEVICES=y ++# CONFIG_DMADEVICES_DEBUG is not set ++ ++# ++# DMA Devices ++# ++# CONFIG_DW_DMAC is not set ++CONFIG_FH_DMAC=y ++CONFIG_FH_DMAC_MISC=y ++# CONFIG_TIMB_DMA is not set ++CONFIG_DMA_ENGINE=y ++ ++# ++# DMA Clients ++# ++# CONFIG_NET_DMA is not set ++# CONFIG_ASYNC_TX_DMA is not set ++# CONFIG_DMATEST is not set ++# CONFIG_AUXDISPLAY is not set ++# CONFIG_UIO is not set ++# CONFIG_STAGING is not set ++CONFIG_CLKDEV_LOOKUP=y ++CONFIG_PWM=y ++CONFIG_PWM_FULLHAN=y ++CONFIG_PWM_FULLHAN_V20=y ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_BTRFS_FS is not set ++# CONFIG_NILFS2_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++CONFIG_FILE_LOCKING=y ++CONFIG_FSNOTIFY=y ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_FANOTIFY is not set ++# CONFIG_QUOTA is not set ++# CONFIG_QUOTACTL is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++ ++# ++# Caches ++# ++# CONFIG_FSCACHE is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_POSIX_ACL is not set ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++# CONFIG_CONFIGFS_FS is not set ++CONFIG_MISC_FILESYSTEMS=y ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_ECRYPT_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++# CONFIG_YAFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_LOGFS is not set ++CONFIG_CRAMFS=y ++# CONFIG_SQUASHFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_PSTORE is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_V4_1 is not set ++# CONFIG_ROOT_NFS is not set ++# CONFIG_NFS_USE_LEGACY_DNS is not set ++CONFIG_NFS_USE_KERNEL_DNS=y ++# CONFIG_NFS_USE_NEW_IDMAPPER is not set ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++# CONFIG_CEPH_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_KARMA_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++# CONFIG_SYSV68_PARTITION is not set ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++# CONFIG_NLS_CODEPAGE_936 is not set ++# CONFIG_NLS_CODEPAGE_950 is not set ++# CONFIG_NLS_CODEPAGE_932 is not set ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=m ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=m ++ ++# ++# Kernel hacking ++# ++# CONFIG_TEST_BOOT_TIME is not set ++CONFIG_PRINTK_TIME=y ++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_STRIP_ASM_SYMS is not set ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_SECTION_MISMATCH is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_HARDLOCKUP_DETECTOR is not set ++# CONFIG_SLUB_STATS is not set ++# CONFIG_SPARSE_RCU_POINTER is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_MEMORY_INIT is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_LKDTM is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y ++CONFIG_HAVE_DYNAMIC_FTRACE=y ++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y ++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y ++CONFIG_HAVE_C_RECORDMCOUNT=y ++CONFIG_TRACING_SUPPORT=y ++# CONFIG_FTRACE is not set ++# CONFIG_DYNAMIC_DEBUG is not set ++# CONFIG_DMA_API_DEBUG is not set ++# CONFIG_ATOMIC64_SELFTEST is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_TEST_KSTRTOX is not set ++# CONFIG_STRICT_DEVMEM is not set ++# CONFIG_ARM_UNWIND is not set ++# CONFIG_DEBUG_USER is not set ++# CONFIG_OC_ETM is not set ++ ++# ++# Security options ++# ++CONFIG_KEYS=y ++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set ++# CONFIG_SECURITY_DMESG_RESTRICT is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_PCOMP2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++# CONFIG_CRYPTO_GF128MUL is not set ++# CONFIG_CRYPTO_NULL is not set ++CONFIG_CRYPTO_WORKQUEUE=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=y ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++CONFIG_CRYPTO_SEQIV=y ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++CONFIG_CRYPTO_ECB=y ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_XCBC is not set ++# CONFIG_CRYPTO_VMAC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_GHASH is not set ++# CONFIG_CRYPTO_MD4 is not set ++# CONFIG_CRYPTO_MD5 is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++CONFIG_CRYPTO_AES=y ++# CONFIG_CRYPTO_ANUBIS is not set ++CONFIG_CRYPTO_ARC4=y ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_ZLIB is not set ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++CONFIG_CRYPTO_USER_API=y ++# CONFIG_CRYPTO_USER_API_HASH is not set ++CONFIG_CRYPTO_USER_API_SKCIPHER=y ++CONFIG_CRYPTO_HW=y ++CONFIG_FH_AES=y ++# CONFIG_FH_AES_SELF_TEST is not set ++# CONFIG_BINARY_PRINTF is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++CONFIG_CRC_CCITT=m ++# CONFIG_CRC16 is not set ++CONFIG_CRC_T10DIF=m ++# CONFIG_CRC_ITU_T is not set ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++# CONFIG_XZ_DEC is not set ++# CONFIG_XZ_DEC_BCJ is not set ++CONFIG_DECOMPRESS_GZIP=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++CONFIG_NLATTR=y ++CONFIG_GENERIC_ATOMIC64=y ++CONFIG_AVERAGE=y +diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h +index ee2ad8ae..3aefe527 100644 +--- a/arch/arm/include/asm/setup.h ++++ b/arch/arm/include/asm/setup.h +@@ -143,6 +143,12 @@ struct tag_memclk { + __u32 fmemclk; + }; + ++#define ATAG_PHYMODE 0x41000601 ++ ++struct tag_phymode { ++ u32 phymode; ++}; ++ + struct tag { + struct tag_header hdr; + union { +@@ -165,6 +171,11 @@ struct tag { + * DC21285 specific + */ + struct tag_memclk memclk; ++ ++ /* ++ * Fullhan specific ++ */ ++ struct tag_phymode phymode; + } u; + }; + +diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S +index 6b1e0ad9..aece734b 100644 +--- a/arch/arm/kernel/head-nommu.S ++++ b/arch/arm/kernel/head-nommu.S +@@ -61,7 +61,11 @@ __after_proc_init: + * the CPU init function. + */ + #ifdef CONFIG_ALIGNMENT_TRAP ++#if (__GNUC__ >= 5 && __LINUX_ARM_ARCH__ >= 6) ++ bic r0, r0, #CR_A ++#else + orr r0, r0, #CR_A ++#endif + #else + bic r0, r0, #CR_A + #endif +diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S +index 278c1b0e..d2da8a78 100644 +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -226,6 +226,7 @@ __create_page_tables: + * This allows debug messages to be output + * via a serial console before paging_init. + */ ++#ifndef CONFIG_JLINK_DEBUG + addruart r7, r3 + + mov r3, r3, lsr #20 +@@ -243,6 +244,7 @@ __create_page_tables: + add r3, r3, #1 << 20 + teq r0, r6 + bne 1b ++#endif + + #else /* CONFIG_DEBUG_ICEDCC */ + /* we don't need any serial debugging mappings for ICEDCC */ +@@ -349,7 +351,11 @@ __secondary_data: + */ + __enable_mmu: + #ifdef CONFIG_ALIGNMENT_TRAP ++#if (__GNUC__ >= 5 && __LINUX_ARM_ARCH__ >= 6) ++ bic r0, r0, #CR_A ++#else + orr r0, r0, #CR_A ++#endif + #else + bic r0, r0, #CR_A + #endif +@@ -362,6 +368,13 @@ __enable_mmu: + #ifdef CONFIG_CPU_ICACHE_DISABLE + bic r0, r0, #CR_I + #endif ++ /* ++ * add by fullhan ++ */ ++#ifdef CONFIG_JLINK_DEBUG ++ mov r4, #0x10000000 ++#endif ++ + mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ +diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c +old mode 100644 +new mode 100755 +diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h +old mode 100644 +new mode 100755 +diff --git a/arch/arm/mach-fh/Kconfig b/arch/arm/mach-fh/Kconfig +new file mode 100644 +index 00000000..1861aa25 +--- /dev/null ++++ b/arch/arm/mach-fh/Kconfig +@@ -0,0 +1,202 @@ ++if ARCH_FULLHAN ++ ++config CPU_FH8810 ++ select CPU_V6 ++ bool ++ ++config CPU_WUDANG ++ select CPU_V6 ++ bool ++ ++config CPU_FH8830 ++ select CPU_V6 ++ bool ++ ++config CPU_FH8833 ++ select CPU_V6 ++ bool ++ ++config CPU_FH8856 ++ select CPU_V6 ++ bool ++ ++config CPU_FH8626V100 ++ select CPU_V6 ++ bool ++ ++config CPU_ZY2 ++ select CPU_V6 ++ bool ++ ++menu "FullHan Implementations" ++ ++comment "FullHan Core Type" ++ ++choice ++ prompt "Select Fullhan Chip:" ++ default ARCH_FH8833 ++ ++config ARCH_FH8810 ++ bool "FullHan FH8810 based system" ++ select CPU_FH8810 ++ select USE_PTS_AS_CLOCKSOURCE ++ ++config ARCH_FH8833 ++ bool "FullHan FH8833 based system" ++ select CPU_FH8833 ++ ++config ARCH_FH8830 ++ bool "FullHan FH8830 based system" ++ select CPU_FH8830 ++ ++config ARCH_FH8856 ++ bool "FullHan FH8856 based system" ++ select CPU_FH8856 ++ ++config ARCH_FH8626V100 ++ bool "FullHan FH8626V100 based system" ++ select CPU_FH8626V100 ++ ++ ++config ARCH_WUDANG ++ bool "FullHan Wudang based system" ++ select CPU_WUDANG ++ ++config ARCH_ZY2 ++ bool "FullHan ZY2 based system" ++ select CPU_ZY2 ++ ++ ++endchoice ++ ++comment "FullHan Board Type" ++ ++config USE_PTS_AS_CLOCKSOURCE ++ bool "use pts as clock source" ++ default n ++ ++config FH_SIMPLE_TIMER ++ bool "use fh self-defined simple timer" ++ default n ++ ++config MACH_FH8810 ++ bool "FullHan FH8810 board" ++ default n ++ depends on ARCH_FH8810 ++ ++config MACH_FH8830_FPGA ++ bool "FullHan fh8830 fpga board" ++ default n ++ depends on ARCH_FH8830 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is a FH8830 fpga ++ ++config MACH_FH8833 ++ bool "FullHan FH8833 board" ++ default y ++ depends on ARCH_FH8833 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is FH8833 ++ ++ ++config MACH_FH8830 ++ bool "FullHan FH8830 board" ++ default y ++ depends on ARCH_FH8830 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is FH8830 ++ ++config MACH_FH8856 ++ bool "FullHan FH8856 board" ++ default y ++ depends on ARCH_FH8856 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is FH8856 ++ ++config MACH_FH8852 ++ bool "FullHan FH8852 board" ++ default n ++ depends on ARCH_FH8856 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is FH8852 ++config MACH_FH8626V100 ++ bool "FullHan FH8626V100 board" ++ default y ++ depends on ARCH_FH8626V100 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is FH8626V100 ++ ++config MACH_WUDANG ++ bool "FullHan Wudang board" ++ default n ++ depends on ARCH_WUDANG ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is a Wudang EVM ++ ++config MACH_HIK ++ bool "HIK FH8810 board" ++ default n ++ depends on ARCH_FH8810 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is a HIK EVM ++ ++config MACH_FH8830_QFN ++ bool "FH8830 QFN" ++ default n ++ depends on ARCH_FH8830 ++ help ++ FH8830 QFN ++ ++config MACH_FH8833_QFN56 ++ bool "FH8633 QFN56" ++ default n ++ depends on ARCH_FH8833 ++ help ++ FH8633 QFN56 ++ ++config MACH_ZY2 ++ bool "FullHan ZY2 board" ++ default y ++ depends on ARCH_ZY2 ++ select MISC_DEVICES ++ select I2C ++ help ++ Configure this option to specify the whether the board used ++ for development is ZY2 ++ ++config MACH_FH_NAND ++ bool "USE NAND FLASH" ++ default n ++ help ++ use NAND FLASH ++ ++config JLINK_DEBUG ++ bool "Use jlink to debug kernel." ++ ++endmenu ++ ++endif +diff --git a/arch/arm/mach-fh/Makefile b/arch/arm/mach-fh/Makefile +new file mode 100644 +index 00000000..7354c1a4 +--- /dev/null ++++ b/arch/arm/mach-fh/Makefile +@@ -0,0 +1,20 @@ ++# ++# Makefile for the linux kernel. ++# ++# ++ ++# Common objects ++obj-y := time.o \ ++ sram.o irq.o pmu.o pm.o sram.o fh_common.o fh_chipid.o ++# clk config ++obj-$(CONFIG_ARCH_FH8856) += clock.o ++# Chip specific ++obj-$(CONFIG_ARCH_FH8856) += fh8856.o ++# Board specific ++obj-$(CONFIG_ARCH_FH8856) += board-fh8856.o pinctrl.o ++obj-$(CONFIG_FH_SIMPLE_TIMER) += fh_simple_timer.o ++ ++# Power Management ++obj-$(CONFIG_CPU_FREQ) += cpufreq.o ++obj-$(CONFIG_CPU_IDLE) += cpuidle.o ++obj-$(CONFIG_SUSPEND) += pm.o sleep.o +diff --git a/arch/arm/mach-fh/Makefile.boot b/arch/arm/mach-fh/Makefile.boot +new file mode 100644 +index 00000000..f05489f0 +--- /dev/null ++++ b/arch/arm/mach-fh/Makefile.boot +@@ -0,0 +1,4 @@ ++ zreladdr-y := 0xA0008000 ++params_phys-y := 0xA0000100 ++initrd_phys-y := 0xA0800000 ++ +diff --git a/arch/arm/mach-fh/board-fh8856.c b/arch/arm/mach-fh/board-fh8856.c +new file mode 100644 +index 00000000..fabbf378 +--- /dev/null ++++ b/arch/arm/mach-fh/board-fh8856.c +@@ -0,0 +1,1258 @@ ++/* ++ * Fullhan FH8810 board support ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/err.h> ++#include <linux/i2c.h> ++#include <linux/io.h> ++#include <linux/mmc/dw_mmc.h> ++#include <linux/clk.h> ++#include <linux/i2c/at24.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/slab.h> ++#include <linux/input.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++#include <linux/phy.h> ++#include <linux/dma-mapping.h> ++#include <linux/spi/eeprom.h> ++#include <linux/delay.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++#include <asm/pmu.h> ++ ++#include <mach/system.h> ++#include <mach/chip.h> ++#include <mach/iomux.h> ++#include <mach/irqs.h> ++#include <mach/pmu.h> ++#include <mach/fh_dmac.h> ++#include <mach/fh_gmac.h> ++#include <mach/gpio.h> ++#include <mach/spi.h> ++#include <mach/clock.h> ++#include <mach/fh_rtc_v2.h> ++#include <mach/pinctrl.h> ++#include <mach/fh_wdt.h> ++#include <mach/fhmci.h> ++#include <mach/board_config.h> ++#include <mach/fh_efuse_plat.h> ++#include <crypto/if_alg.h> ++#include <mach/pmu.h> ++#include <mach/fh_usb.h> ++#include <mach/fh_i2s.h> ++ ++ ++static struct map_desc fh8856_io_desc[] = { ++ { ++ .virtual = VA_RAM_REG_BASE, ++ .pfn = __phys_to_pfn(RAM_BASE), ++ .length = SZ_16K, ++ .type = MT_MEMORY, ++ }, ++ { ++ .virtual = VA_DDRC_REG_BASE, ++ .pfn = __phys_to_pfn(DDRC_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = VA_INTC_REG_BASE, ++ .pfn = __phys_to_pfn(INTC_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = VA_TIMER_REG_BASE, ++ .pfn = __phys_to_pfn(TIMER_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = VA_PMU_REG_BASE, ++ .pfn = __phys_to_pfn(PMU_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = VA_UART0_REG_BASE, ++ .pfn = __phys_to_pfn(UART0_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = VA_UART1_REG_BASE, ++ .pfn = __phys_to_pfn(UART1_REG_BASE), ++ .length = SZ_16K, ++ .type = MT_DEVICE, ++ }, ++}; ++ ++ ++static struct resource fh_gpio0_resources[] = { ++ { ++ .start = GPIO0_REG_BASE, ++ .end = GPIO0_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = GPIO0_IRQ, ++ .end = GPIO0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_gpio1_resources[] = { ++ { ++ .start = GPIO1_REG_BASE, ++ .end = GPIO1_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = GPIO1_IRQ, ++ .end = GPIO1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++ ++static struct resource fh_uart0_resources[] = { ++ { ++ .start = (UART0_REG_BASE), ++ .end = (UART0_REG_BASE) + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = UART0_IRQ, ++ .end = UART0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_uart1_resources[] = { ++ { ++ .start = (UART1_REG_BASE), ++ .end = (UART1_REG_BASE) + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = UART1_IRQ, ++ .end = UART1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_dma_resources[] = { ++ { ++ .start = (DMAC_REG_BASE), ++ .end = (DMAC_REG_BASE) + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = DMAC0_IRQ, ++ .end = DMAC0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static struct resource fh_i2c_resources_0[] = { ++ { ++ .start = I2C0_REG_BASE, ++ .end = I2C0_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = I2C0_IRQ, ++ .end = I2C0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static struct resource fh_i2c_resources_1[] = { ++ { ++ .start = I2C1_REG_BASE, ++ .end = I2C1_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = I2C1_IRQ, ++ .end = I2C1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_sdc0_resources[] = { ++ { ++ .start = SDC0_REG_BASE, ++ .end = SDC0_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = SDC0_IRQ, ++ .end = SDC0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static struct resource fh_sdc1_resources[] = { ++ { ++ .start = SDC1_REG_BASE, ++ .end = SDC1_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = SDC1_IRQ, ++ .end = SDC1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++static struct resource fh_wdt_resources[] = { ++ { ++ .start = WDT_REG_BASE, ++ .end = WDT_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = WDT_IRQ, ++ .end = WDT_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_spi0_resources[] = { ++ { ++ .start = SPI0_REG_BASE, ++ .end = SPI0_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "fh spi0 mem", ++ }, ++ { ++ .start = SPI0_IRQ, ++ .end = SPI0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ .name = "fh spi0 irq", ++ }, ++}; ++ ++static struct resource fh_spi1_resources[] = { ++ { ++ .start = SPI1_REG_BASE, ++ .end = SPI1_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "fh spi1 mem", ++ }, ++ { ++ .start = SPI1_IRQ, ++ .end = SPI1_IRQ, ++ .flags = IORESOURCE_IRQ, ++ .name = "fh spi1 irq", ++ }, ++}; ++ ++static struct resource fh_spi2_resources[] = { ++ { ++ .start = SPI2_REG_BASE, ++ .end = SPI2_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "fh spi2 mem", ++ }, ++ { ++ .start = SPI2_IRQ, ++ .end = SPI2_IRQ, ++ .flags = IORESOURCE_IRQ, ++ .name = "fh spi2 irq", ++ }, ++}; ++ ++ ++ ++static struct resource fh_gmac_resources[] = { ++ { ++ .start = GMAC_REG_BASE, ++ .end = GMAC_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++ { ++ .start = GMAC_IRQ, ++ .end = GMAC_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_pwm_resources[] = { ++ { ++ .start = PWM_REG_BASE, ++ .end = PWM_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = PWM_IRQ, ++ .end = PWM_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource fh_sadc_resources[] = { ++ { ++ .start = SADC_REG_BASE, ++ .end = SADC_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "fh sadc mem", ++ }, ++ { ++ .start = SADC_IRQ, ++ .end = SADC_IRQ, ++ .flags = IORESOURCE_IRQ, ++ .name = "fh sadc irq", ++ }, ++}; ++ ++static struct resource fh_aes_resources[] = { ++ { ++ .start = AES_REG_BASE, ++ .end = AES_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ .name = "fh aes mem", ++ }, ++ { ++ .start = AES_IRQ, ++ .end = AES_IRQ, ++ .flags = IORESOURCE_IRQ, ++ .name = "fh aes irq", ++ }, ++}; ++ ++static struct resource fh_rtc_resources[] = { ++ { ++ .start = RTC_REG_BASE, ++ .end = RTC_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = RTC_IRQ, ++ .end = RTC_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++ ++static struct resource fh_efuse_resources[] = { ++ { ++ .start = EFUSE_REG_BASE, ++ .end = EFUSE_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ ++}; ++ ++static void fh_gmac_early_init(struct fh_gmac_platform_data *plat_data) ++{ ++} ++ ++static void fh_gmac_plat_init(struct fh_gmac_platform_data *plat_data) ++{ ++ u32 reg; ++ ++ if (plat_data->interface == PHY_INTERFACE_MODE_RMII) { ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg |= 0x7000000; ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++ ++ fh_pmu_set_reg(REG_PMU_SWRST_AHB_CTRL, 0xfffdffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_AHB_CTRL) != 0xffffffff) ++ ; ++ ++ } else if (plat_data->interface == PHY_INTERFACE_MODE_MII) { ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg &= ~(0x7000000); ++ reg |= 0x1000000; ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++ ++ fh_pmu_set_reg(REG_PMU_SWRST_AHB_CTRL, 0xfffdffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_AHB_CTRL) != 0xffffffff) ++ ; ++ } ++} ++ ++static void fh_set_rmii_speed(int speed) ++{ ++ u32 reg; ++ ++ if (speed == gmac_speed_10m) { ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg &= ~(0x1000000); ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++ } else { ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg |= 0x1000000; ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++ } ++} ++ ++static void fh_phy_reset(void) ++{ ++ /* ++ * RXDV must be low during phy reset ++ */ ++ ++ fh_pmu_set_reg(0xe8, 0x01101030); ++ ++ gpio_request(CONFIG_GPIO_EMACPHY_RESET, "phy_reset"); ++ gpio_request(CONFIG_GPIO_EMACPHY_RXDV, "phy_rxdv"); ++ ++ gpio_direction_output(CONFIG_GPIO_EMACPHY_RESET, 0); ++ mdelay(10); ++ gpio_direction_output(CONFIG_GPIO_EMACPHY_RESET, 1); ++ msleep(150); ++ ++ gpio_free(CONFIG_GPIO_EMACPHY_RESET); ++ gpio_free(CONFIG_GPIO_EMACPHY_RXDV); ++ ++ fh_pmu_set_reg(0xe8, 0x00101030); ++ ++} ++ ++static struct fh_gmac_platform_data fh_gmac_data = { ++ .early_init = fh_gmac_early_init, ++ .plat_init = fh_gmac_plat_init, ++ .set_rmii_speed = fh_set_rmii_speed, ++ .phy_reset = fh_phy_reset, ++ .phyid = -1, ++}; ++ ++static const char *const fh_gpio0_names[] = { ++ "GPIO0", "GPIO1", "GPIO2", "GPIO3", ++ "GPIO4", "GPIO5", "GPIO6", "GPIO7", ++ "GPIO8", "GPIO9", "GPIO10", "GPIO11", ++ "GPIO12", "GPIO13", "GPIO14", "GPIO15", ++ "GPIO16", "GPIO17", "GPIO18", "GPIO19", ++ "GPIO20", "GPIO21", "GPIO22", "GPIO23", ++ "GPIO24", "GPIO25", "GPIO26", "GPIO27", ++ "GPIO28", "GPIO29", "GPIO30", "GPIO31", ++}; ++ ++static const char *const fh_gpio1_names[] = { ++ "GPIO32", "GPIO33", "GPIO34", "GPIO35", ++ "GPIO36", "GPIO37", "GPIO38", "GPIO39", ++ "GPIO40", "GPIO41", "GPIO42", "GPIO43", ++ "GPIO44", "GPIO45", "GPIO46", "GPIO47", ++ "GPIO48", "GPIO49", "GPIO50", "GPIO51", ++ "GPIO52", "GPIO53", "GPIO54", "GPIO55", ++ "GPIO56", "GPIO57", "GPIO58", "GPIO59", ++ "GPIO60", "GPIO61", "GPIO62", "GPIO63", ++}; ++ ++static struct fh_gpio_chip fh_gpio0_chip = { ++ .chip = { ++ .owner = THIS_MODULE, ++ .label = "FH_GPIO0", ++ .base = 0, ++ .ngpio = 32, ++ .names = fh_gpio0_names, ++ }, ++}; ++ ++static struct fh_gpio_chip fh_gpio1_chip = { ++ .chip = { ++ .owner = THIS_MODULE, ++ .label = "FH_GPIO1", ++ .base = 32, ++ .ngpio = 32, ++ .names = fh_gpio1_names, ++ }, ++}; ++ ++ ++static void fh_wdt_pause(void) ++{ ++ unsigned int reg; ++ ++ reg = fh_pmu_get_reg(REG_PMU_WDT_CTRL); ++ reg |= 0x100; ++ fh_pmu_set_reg(REG_PMU_WDT_CTRL, reg); ++ ++ printk(KERN_INFO "wdt pause\n"); ++} ++ ++static void fh_wdt_resume(void) ++{ ++ unsigned int reg; ++ ++ reg = fh_pmu_get_reg(REG_PMU_WDT_CTRL); ++ reg &= ~(0x100); ++ fh_pmu_set_reg(REG_PMU_WDT_CTRL, reg); ++} ++ ++static irqreturn_t fh_wdt_intr(void *pri) ++{ ++ struct fh_wdt_t *fh_wdt = (struct fh_wdt_t *)pri; ++ struct fh_wdt_platform_data *plat_data = ++ (struct fh_wdt_platform_data *)fh_wdt->plat_data; ++ struct fh_wdt_platform_reset *priv = ++ (struct fh_wdt_platform_reset *)plat_data->plat_info; ++ unsigned int spi0_cs_pin = priv->spi0_cs_pin; ++ unsigned int spi0_rst_bit = priv->spi0_rst_bit; ++ unsigned int sd0_rst_bit = priv->sd0_rst_bit; ++ unsigned int uart0_rst_bit = priv->uart0_rst_bit; ++ ++ gpio_request(spi0_cs_pin, "spi0_cs0"); ++ gpio_direction_output(spi0_cs_pin, 1); ++ ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, ~BIT(spi0_rst_bit)); ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, ~BIT(uart0_rst_bit)); ++ fh_pmu_set_reg(REG_PMU_SWRST_AHB_CTRL, ~BIT(sd0_rst_bit)); ++ ++ fh_pmu_stop(); ++ ++ /* Dead Loop! Prevent Other IRQ's Reentrancy!*/ ++ while (1) ++ ; ++ return IRQ_HANDLED; ++} ++ ++static int fh_buswd(u32 slot_id) ++{ ++ return 4; ++} ++ ++static int sd_init(unsigned int slot_id, void *data, void *v) ++{ ++ u32 reg; ++ ++ reg = slot_id ? 0xfffffffd : 0xfffffffb; ++ fh_pmu_set_reg(REG_PMU_SWRST_AHB_CTRL, reg); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_AHB_CTRL) != 0xffffffff) ++ ; ++ return 0; ++} ++ ++static unsigned int __maybe_unused ++fh_mci_sys_card_detect_fixed(struct fhmci_host *host) ++{ ++ return 0; ++} ++ ++static unsigned int __maybe_unused ++fh_mci_sys_read_only_fixed(struct fhmci_host *host) ++{ ++ return 0; ++} ++ ++struct fh_mci_board fh_mci = { ++ .init = sd_init, ++#ifdef CONFIG_SD_CD_FIXED ++ .get_cd = fh_mci_sys_card_detect_fixed, ++#endif ++ .num_slots = 1, ++ .bus_hz = 50000000, ++ .detect_delay_ms = 200, ++ .get_bus_wd = fh_buswd, ++ .caps = MMC_CAP_4_BIT_DATA ++ | MMC_CAP_SD_HIGHSPEED ++ | MMC_CAP_MMC_HIGHSPEED ++ | MMC_CAP_NEEDS_POLL ++ /* | MMC_CAP_SDIO_IRQ */, ++}; ++ ++struct fh_mci_board fh_mci_sd = { ++ .init = sd_init, ++ .num_slots = 1, ++ .bus_hz = 50000000, ++ .detect_delay_ms = 200, ++ .get_bus_wd = fh_buswd, ++ .caps = MMC_CAP_4_BIT_DATA ++ | MMC_CAP_SD_HIGHSPEED ++ | MMC_CAP_MMC_HIGHSPEED ++ | MMC_CAP_NEEDS_POLL ++ /* | MMC_CAP_SDIO_IRQ */, ++}; ++ ++static struct fh_dma_platform_data fh_dma_data = { ++ .chan_priority = CHAN_PRIORITY_ASCENDING, ++ .nr_channels = 8, ++}; ++ ++static struct at24_platform_data at24c02 = { ++ .byte_len = SZ_2K / 8, ++ .page_size = 8, ++ .flags = AT24_FLAG_TAKE8ADDR, ++}; ++ ++static struct platform_device fh_gmac_device = { ++ .name = "fh_gmac", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_gmac_resources), ++ .resource = fh_gmac_resources, ++ .dev = { ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &fh_gmac_data, ++ }, ++}; ++ ++static struct platform_device fh_gpio0_device = { ++ .name = GPIO_NAME, ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_gpio0_resources), ++ .resource = fh_gpio0_resources, ++ .dev = { ++ .platform_data = &fh_gpio0_chip, ++ }, ++}; ++ ++static struct platform_device fh_gpio1_device = { ++ .name = GPIO_NAME, ++ .id = 1, ++ .num_resources = ARRAY_SIZE(fh_gpio1_resources), ++ .resource = fh_gpio1_resources, ++ .dev = { ++ .platform_data = &fh_gpio1_chip, ++ }, ++}; ++ ++struct platform_device fh_sd0_device = { ++ .name = "fh_mci", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_sdc0_resources), ++ .resource = fh_sdc0_resources, ++ .dev = { ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &fh_mci_sd, ++ } ++}; ++ ++struct platform_device fh_sd1_device = { ++ .name = "fh_mci", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(fh_sdc1_resources), ++ .resource = fh_sdc1_resources, ++ .dev = { ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &fh_mci, ++ } ++}; ++ ++static struct platform_device fh_uart0_device = { ++ .name = "ttyS", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_uart0_resources), ++ .resource = fh_uart0_resources, ++}; ++ ++static struct platform_device fh_uart1_device = { ++ .name = "ttyS", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(fh_uart1_resources), ++ .resource = fh_uart1_resources, ++}; ++ ++static struct platform_device fh_dma_device = { ++ .name = "fh_dmac", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_dma_resources), ++ .resource = fh_dma_resources, ++ .dev.platform_data = &fh_dma_data, ++}; ++ ++static struct platform_device fh_i2c0_device = { ++ .name = "fh_i2c", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_i2c_resources_0), ++ .resource = fh_i2c_resources_0, ++}; ++ ++static struct platform_device fh_i2c1_device = { ++ .name = "fh_i2c", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(fh_i2c_resources_1), ++ .resource = fh_i2c_resources_1, ++}; ++ ++static struct i2c_board_info __initdata fh_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("24c02", 0x50), ++ .platform_data = &at24c02, ++ }, ++ { ++ I2C_BOARD_INFO("pcf8563", 0x51) ++ } ++}; ++ ++static struct resource fh_i2s_resources[] = { ++ { ++ .start = I2S_REG_BASE, ++ .end = I2S_REG_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = I2S0_IRQ, ++ .end = I2S0_IRQ, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static int i2s_clk_config(int div_val) ++{ ++ int reg; ++ ++ if (div_val & 0xffff0000) ++ return -EINVAL; ++ ++ reg = fh_pmu_get_reg(REG_PMU_CLK_DIV6); /*config I2S clk div*/ ++ reg &= ~0x3fff; ++ reg |= div_val; ++ fh_pmu_set_reg(REG_PMU_CLK_DIV6, reg); ++ ++ /* i2s_clk switch to PLLVCO */ ++ reg = fh_pmu_get_reg(REG_PAD_PWR_SEL); ++ reg |= 1<<6; ++ fh_pmu_set_reg(REG_PAD_PWR_SEL, reg); ++ ++ return 0; ++} ++ ++static struct fh_i2s_platform_data fh_i2s_data = { ++ .dma_capture_channel = 2, ++ .dma_playback_channel = 3, ++ .dma_master = 0, ++ .clk_config = i2s_clk_config, ++}; ++ ++static struct platform_device fh_i2s_device = { ++ .name = "fh_audio", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_i2s_resources), ++ .resource = fh_i2s_resources, ++ .dev = { ++ .platform_data = &fh_i2s_data, ++ }, ++}; ++ ++ ++#define FH_SPI0_CS0 (54) ++#define FH_SPI0_CS1 (55) ++ ++#define FH_SPI1_CS0 (56) ++#define FH_SPI1_CS1 (57) ++ ++#define SPI0_FIFO_DEPTH (128) ++#define SPI0_CLK_IN (100000000) ++#define SPI0_MAX_SLAVE_NO (2) ++#define SPI0_DMA_RX_CHANNEL (0) ++#define SPI0_DMA_TX_CHANNEL (1) ++ ++#define SPI1_FIFO_DEPTH (64) ++#define SPI1_CLK_IN (100000000) ++#define SPI1_MAX_SLAVE_NO (2) ++#define SPI1_DMA_RX_CHANNEL (2) ++#define SPI1_DMA_TX_CHANNEL (3) ++ ++#define SPI2_FIFO_DEPTH (64) ++#define SPI2_CLK_IN (100000000) ++/* SPI_TRANSFER_USE_DMA */ ++ ++static struct fh_spi_platform_data fh_spi0_data = { ++ .apb_clock_in = SPI0_CLK_IN, ++ .fifo_len = SPI0_FIFO_DEPTH, ++ .slave_max_num = SPI0_MAX_SLAVE_NO, ++ .cs_data[0].GPIO_Pin = FH_SPI0_CS0, ++ .cs_data[0].name = "spi0_cs0", ++ .cs_data[1].GPIO_Pin = FH_SPI0_CS1, ++ .cs_data[1].name = "spi0_cs1", ++ .dma_transfer_enable = 0, ++ .rx_handshake_num = 2, ++ .tx_handshake_num = 3, ++ .rx_dma_channel = SPI0_DMA_RX_CHANNEL, ++ .tx_dma_channel = SPI0_DMA_TX_CHANNEL, ++ .clk_name = "spi0_clk", ++ .max_speed_support = 50000000, ++ .spidma_xfer_mode = TX_RX_MODE, ++ .data_reg_offset = 0, ++ /*dma use inc mode could move data by burst mode... ++ or move data use single mode with low efficient*/ ++ .data_increase_support = 0, ++ .data_field_size = 0, ++ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |\ ++ MULTI_WIRE_SUPPORT, ++ .swap_support = SWAP_SUPPORT, ++ ++}; ++ ++static struct fh_spi_platform_data fh_spi1_data = { ++ .apb_clock_in = SPI1_CLK_IN, ++ .fifo_len = SPI1_FIFO_DEPTH, ++ .slave_max_num = SPI1_MAX_SLAVE_NO, ++ .cs_data[0].GPIO_Pin = FH_SPI1_CS0, ++ .cs_data[0].name = "spi1_cs0", ++ .cs_data[1].GPIO_Pin = FH_SPI1_CS1, ++ .cs_data[1].name = "spi1_cs1", ++ .dma_transfer_enable = 0, ++ .rx_handshake_num = 4, ++ .tx_handshake_num = 5, ++ .rx_dma_channel = SPI1_DMA_RX_CHANNEL, ++ .tx_dma_channel = SPI1_DMA_TX_CHANNEL, ++ .clk_name = "spi1_clk", ++ .max_speed_support = 25000000, ++ .data_reg_offset = 0x60, ++ .data_increase_support = 0, ++}; ++ ++static struct fh_spi_platform_data fh_spi2_data = { ++ .apb_clock_in = SPI2_CLK_IN, ++ .fifo_len = SPI2_FIFO_DEPTH, ++ .dma_transfer_enable = 0, ++ .rx_handshake_num = 12, ++ .tx_handshake_num = 13, ++ .clk_name = "spi2_clk", ++}; ++ ++static struct fh_rtc_platform_data fh_rtc_data = { ++ .clock_in = 32768, ++ .dev_name = "rtc", ++ .clk_name = "rtc_clk", ++ .base_year = 2000, ++ .base_month = 1, ++ .base_day = 1, ++ .sadc_channel = -1, ++}; ++ ++ ++static struct fh_wdt_platform_reset fh_plat_rst_info = { ++ .spi0_cs_pin = FH_SPI0_CS0, ++ .spi0_rst_bit = SPI0_RSTN_BIT, ++ .sd0_rst_bit = SDC0_HRSTN_BIT, ++ .uart0_rst_bit = UART0_RSTN_BIT, ++}; ++ ++static struct fh_wdt_platform_data fh_wdt_data = { ++ .pause = fh_wdt_pause, ++ .resume = fh_wdt_resume, ++ .intr = fh_wdt_intr, ++ .plat_info = &fh_plat_rst_info, ++}; ++ ++ ++struct platform_device fh_wdt_device = { ++ .name = "fh_wdt", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_wdt_resources), ++ .resource = fh_wdt_resources, ++ .dev = { ++ .platform_data = &fh_wdt_data, ++ } ++}; ++ ++ ++static struct platform_device fh_spi0_device = { ++ .name = "fh_spi", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_spi0_resources), ++ .resource = fh_spi0_resources, ++ .dev = { ++ .platform_data = &fh_spi0_data, ++ }, ++}; ++ ++static struct platform_device fh_spi1_device = { ++ .name = "fh_spi", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(fh_spi1_resources), ++ .resource = fh_spi1_resources, ++ .dev = { ++ .platform_data = &fh_spi1_data, ++ }, ++}; ++ ++ ++static struct platform_device fh_spi2_device = { ++ .name = "fh_spi_slave", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_spi2_resources), ++ .resource = fh_spi2_resources, ++ .dev = { ++ .platform_data = &fh_spi2_data, ++ }, ++}; ++ ++static struct platform_device fh_pwm_device = { ++ .name = "fh_pwm", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_pwm_resources), ++ .resource = fh_pwm_resources, ++ ++}; ++ ++static struct platform_device fh_pinctrl_device = { ++ .name = "fh_pinctrl", ++ .id = 0, ++}; ++ ++static struct platform_device fh_sadc_device = { ++ .name = "fh_sadc", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_sadc_resources), ++ .resource = fh_sadc_resources, ++ .dev = { ++ .platform_data = NULL, ++ }, ++}; ++ ++static struct platform_device fh_aes_device = { ++ .name = "fh_aes", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_aes_resources), ++ .resource = fh_aes_resources, ++ .dev = { ++ .platform_data = NULL, ++ }, ++}; ++ ++static struct platform_device fh_rtc_device = { ++ .name = "fh_rtc", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_rtc_resources), ++ .resource = fh_rtc_resources, ++ .dev = { ++ .platform_data = &fh_rtc_data, ++ }, ++}; ++ ++struct fh_efuse_platform_data fh_efuse_plat_data = { ++ .efuse_support_flag = CRYPTO_CPU_SET_KEY | ++ CRYPTO_EX_MEM_SET_KEY | ++ CRYPTO_EX_MEM_SWITCH_KEY | ++ CRYPTO_EX_MEM_4_ENTRY_1_KEY | ++ CRYPTO_EX_MEM_INDEP_POWER, ++}; ++static struct platform_device fh_efuse_device = { ++ .name = "fh_efuse", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(fh_efuse_resources), ++ .resource = fh_efuse_resources, ++ .dev = { ++ .platform_data = &fh_efuse_plat_data, ++ }, ++}; ++ ++ ++/* ++ * fh8856 usb board config ++ * add 2016/12/20 ++ * ++ */ ++#define S3C64XX_PA_USBHOST USBC_REG_BASE ++#define IRQ_UHOST USBC_IRQ ++#define S3C_PA_OTG S3C64XX_PA_USBHOST ++#define IRQ_OTG IRQ_UHOST ++#define S3C64XX_SZ_USBHOST SZ_1M ++#define S3C_SZ_OTG SZ_1M ++ ++static void fh_usb_utmi_rst(void) ++{ ++ uint32_t pmu_reg = 0; ++ ++ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL); ++ pmu_reg &= ~(0x2); ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, pmu_reg); ++ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL); ++ mdelay(1); ++ ++ pmu_reg |= 0x2; ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, pmu_reg); ++ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL); ++ msleep(20); ++} ++ ++static void fh_usb_phy_rst(void) ++{ ++ uint32_t pmu_reg = 0; ++ ++ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS); ++ pmu_reg |= (0x11); ++ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg); ++ mdelay(1); ++ ++ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS); ++ pmu_reg &= (~0x11); ++ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg); ++} ++ ++/*1:normal mode 0:sleep mode*/ ++ ++static void fh_usb_resume(void) ++{ ++ uint32_t pmu_reg = 0; ++ ++ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS); ++ pmu_reg |= (0x1<<24); ++ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg); ++ mdelay(1); ++} ++ ++/*usb vbus power on*/ ++static void fh_usb_pwr_on(void) ++{ ++ uint32_t pwron_gpio = 0; ++ uint32_t pmu_reg = 0; ++ ++ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS1); ++ pmu_reg &= (~(1<<10)); ++ fh_pmu_set_reg(REG_PMU_USB_SYS1, pmu_reg); ++ pwron_gpio = 2; ++ ++#if defined(CONFIG_FH_HOST_ONLY) ++ gpio_request(pwron_gpio, "usb_pwren"); ++ gpio_direction_output(pwron_gpio, 1); ++ mdelay(1); ++ gpio_free(pwron_gpio); ++#endif ++ ++#if defined(CONFIG_FH_DEVICE_ONLY) ++ gpio_request(pwron_gpio, "usb_pwren"); ++ gpio_direction_output(pwron_gpio, 0); ++ mdelay(1); ++ gpio_free(pwron_gpio); ++#endif ++} ++ ++struct fh_usb_platform_data fh_usb_plat_data = { ++ .utmi_rst = fh_usb_utmi_rst, ++ .phy_rst = fh_usb_phy_rst, ++ .power_on = fh_usb_pwr_on, ++ .hcd_resume = fh_usb_resume, ++ .grxfsiz_pwron_val = 0xA00, ++ .gnptxfsiz_pwron_val = 0xA000A00, ++}; ++ ++ ++static struct resource s3c_usb_otghcd_resource[] = { ++ { ++ .start = S3C_PA_OTG, ++ .end = S3C_PA_OTG + S3C_SZ_OTG - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = IRQ_OTG, ++ .end = IRQ_OTG, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static u64 fh_usb_otghcd_dmamask = 0xffffffffUL; ++struct platform_device fh_device_usb_otghcd = { ++ .name = "fh_otg", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(s3c_usb_otghcd_resource), ++ .resource = s3c_usb_otghcd_resource, ++ .dev = { ++ .dma_mask = &fh_usb_otghcd_dmamask, ++ .coherent_dma_mask = 0xffffffffUL, ++ .platform_data = &fh_usb_plat_data, ++ } ++}; ++ ++static struct platform_device *fh8856_devices[] __initdata = { ++ &fh_gmac_device, ++ &fh_uart0_device, ++ &fh_uart1_device, ++ &fh_dma_device, ++ &fh_i2c0_device, ++ &fh_i2c1_device, ++ &fh_sd0_device, ++ &fh_sd1_device, ++ &fh_spi0_device, ++ &fh_spi1_device, ++ &fh_spi2_device, ++ &fh_gpio0_device, ++ &fh_gpio1_device, ++ &fh_wdt_device, ++ &fh_pwm_device, ++ &fh_pinctrl_device, ++ &fh_sadc_device, ++ &fh_aes_device, ++ &fh_rtc_device, ++ &fh_device_usb_otghcd, ++ &fh_efuse_device, ++ &fh_i2s_device, ++}; ++ ++static struct mtd_partition fh_sf_parts[] = { ++ { ++ /* head & Ramboot */ ++ .name = "bootstrap", ++ .offset = 0, ++ .size = SZ_256K, ++ .mask_flags = MTD_WRITEABLE, /* force read-only */ ++ }, { ++ /* Ramboot & U-Boot environment */ ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_64K, ++ .mask_flags = MTD_WRITEABLE, /* force read-only */ ++ }, { ++ /* U-Boot */ ++ .name = "uboot", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_256K, ++ .mask_flags = MTD_WRITEABLE, /* force read-only */ ++ }, { ++ .name = "kernel", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_4M, ++ .mask_flags = 0, ++ }, { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_8M, ++ .mask_flags = 0, ++ }, { ++ .name = "app", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ .mask_flags = 0, ++ } ++ /* mtdparts= ++ * spi_flash:256k(bootstrap), ++ * 64k(u-boot-env), ++ * 192k(u-boot),4M(kernel), ++ * 8M(rootfs), ++ * -(app) */ ++ /* two blocks with bad block table (and mirror) at the end */ ++}; ++#ifdef CONFIG_MACH_FH_NAND ++static struct mtd_partition fh_sf_nand_parts[] = { ++ { ++ /* head & Ramboot */ ++ .name = "bootstrap", ++ .offset = 0, ++ .size = SZ_256K, ++ .mask_flags = MTD_WRITEABLE, /* force read-only */ ++ }, { ++ .name = "uboot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_256K, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "uboot", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_256K, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_4M, ++ .mask_flags = 0, ++ }, { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_APPEND, ++ .size = SZ_8M, ++ .mask_flags = 0, ++ }, { ++ .name = "app", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ .mask_flags = 0, ++ } ++ /* mtdparts= ++ * spi0.0:64k(bootstrap), ++ * 64k(u-boot-env), ++ * 192k(u-boot), ++ * 4M(kernel), ++ * 8M(rootfs), ++ * -(app) */ ++ /* two blocks with bad block table (and mirror) at the end */ ++}; ++#endif ++ ++static struct flash_platform_data fh_flash_platform_data = { ++ .name = "spi_flash", ++ .parts = fh_sf_parts, ++ .nr_parts = ARRAY_SIZE(fh_sf_parts), ++}; ++ ++#ifdef CONFIG_MACH_FH_NAND ++static struct flash_platform_data fh_nandflash_platform_data = { ++ .name = "spi_nandflash", ++ .parts = fh_sf_nand_parts, ++ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts), ++}; ++#endif ++ ++static struct spi_board_info fh_spi_devices[] = { ++#ifdef CONFIG_MACH_FH_NAND ++ { ++ .modalias = "spi-nand", ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 50000000, ++ .mode = SPI_MODE_3, ++ .platform_data = &fh_nandflash_platform_data, ++ }, ++#endif ++ { ++ .modalias = "m25p80", ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_3, ++ .max_speed_hz = 50000000, ++ .platform_data = &fh_flash_platform_data, ++ }, ++ ++}; ++static void __init fh8856_map_io(void) ++{ ++ iotable_init(fh8856_io_desc, ARRAY_SIZE(fh8856_io_desc)); ++} ++ ++ ++static __init void fh8856_board_init(void) ++{ ++ printk(KERN_INFO "%s board init\n", fh_get_chipname()); ++ platform_add_devices(fh8856_devices, ARRAY_SIZE(fh8856_devices)); ++ i2c_register_board_info(1, fh_i2c_devices, ARRAY_SIZE(fh_i2c_devices)); ++ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices)); ++ fh_clk_procfs_init(); ++ fh_pmu_init(); ++} ++ ++static void __init fh8856_init_early(void) ++{ ++ fh_clk_init(); ++ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80); ++} ++ ++MACHINE_START(FH8856, "FH8856") ++ .boot_params = DDR_BASE + 0x100, ++ .map_io = fh8856_map_io, ++ .init_irq = fh_intc_init, ++ .timer = &fh_timer, ++ .init_machine = fh8856_board_init, ++ .init_early = fh8856_init_early, ++MACHINE_END ++ ++MACHINE_START(FH8852, "FH8852") ++ .boot_params = DDR_BASE + 0x100, ++ .map_io = fh8856_map_io, ++ .init_irq = fh_intc_init, ++ .timer = &fh_timer, ++ .init_machine = fh8856_board_init, ++ .init_early = fh8856_init_early, ++MACHINE_END +diff --git a/arch/arm/mach-fh/clock.c b/arch/arm/mach-fh/clock.c +new file mode 100644 +index 00000000..2e8a162b +--- /dev/null ++++ b/arch/arm/mach-fh/clock.c +@@ -0,0 +1,790 @@ ++/* ++ * Clock and PLL control for FH devices ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/mutex.h> ++#include <linux/io.h> ++#include <asm/bitops.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++#include <mach/hardware.h> ++#include <asm/uaccess.h> ++#include <linux/miscdevice.h> ++#include <mach/clock.h> ++#include <mach/clock.h> ++#include <linux/platform_device.h> ++#include <mach/pmu.h> ++ ++#define PROC_FILE "driver/clock" ++ ++static LIST_HEAD(clocks); ++static DEFINE_MUTEX(clocks_mutex); ++static DEFINE_SPINLOCK(clocks_lock); ++ ++struct proc_dir_entry *proc_file; ++ ++ ++#define DIVVCO_ONE_DEVISION 0x0 ++#define DIVVCO_TWO_DEVISION 0x8 ++#define DIVVCO_FOUR_DEVISION 0xc ++#define DIVVCO_EIGHT_DEVISION 0xd ++#define DIVVCO_SIXTEEN_DEVISION 0xe ++#define DIVVCO_THIRTYTWO_DEVISION 0xf ++ ++ ++/*#define FH_CLK_DEBUG*/ ++ ++#if defined(FH_CLK_DEBUG) ++ #define PRINT_CLK_DBG(fmt, args...) \ ++ do { \ ++ printk("FH_CLK_DEBUG: "); \ ++ printk(fmt, ##args); \ ++ } while (0) ++#else ++ #define PRINT_CLK_DBG(fmt, args...) \ ++ do { \ ++ } while (0) ++#endif ++ ++ ++void clk_set_clk_sel(unsigned int reg) ++{ ++ fh_pmu_set_reg(REG_PMU_CLK_SEL, reg); ++} ++EXPORT_SYMBOL(clk_set_clk_sel); ++ ++unsigned int clk_get_clk_sel(void) ++{ ++ return fh_pmu_get_reg(REG_PMU_CLK_SEL); ++} ++EXPORT_SYMBOL(clk_get_clk_sel); ++ ++#ifdef FH_CLOCK_DEBUG ++static void __clk_sel_ddr_clk(int source) ++{ ++ unsigned int clk_sel; ++ int shift = 24; ++ clk_sel = clk_get_clk_sel(); ++ clk_sel &= ~(0x1 << shift); ++ clk_sel |= (source & 0x1) << shift; ++ clk_set_clk_sel(clk_sel); ++} ++ ++static void __clk_sel_pix_clk(int source) ++{ ++ unsigned int clk_sel; ++ int shift = 4; ++ clk_sel = clk_get_clk_sel(); ++ clk_sel &= ~(0x3 << shift); ++ clk_sel |= (source & 0x3) << shift; ++ clk_set_clk_sel(clk_sel); ++} ++ ++static void __clk_sel_ac_clk(int source) ++{ ++ unsigned int clk_sel; ++ int shift = 0; ++ clk_sel = clk_get_clk_sel(); ++ clk_sel &= ~(0x1 << shift); ++ clk_sel |= (source & 0x1) << shift; ++ clk_set_clk_sel(clk_sel); ++} ++#endif ++ ++ ++static void fh_clk_enable(struct clk *clk) ++{ ++ unsigned int reg; ++ ++ if (clk->flag & CLOCK_NOGATE) { ++ PRINT_CLK_DBG("%s, %s has no gate register\n", __func__, clk->name); ++ return; ++ } ++ ++ reg = fh_pmu_get_reg(clk->en_reg_offset); ++ PRINT_CLK_DBG("%s, clk: %s, reg: 0x%x\n", __func__, clk->name, reg); ++ reg &= ~(clk->en_reg_mask); ++ fh_pmu_set_reg(clk->en_reg_offset, reg); ++ PRINT_CLK_DBG("%s, clk: %s, after mask: 0x%x\n", __func__, clk->name, reg); ++} ++ ++static void fh_clk_disable(struct clk *clk) ++{ ++ unsigned int reg; ++ ++ if (clk->flag & CLOCK_NOGATE) { ++ PRINT_CLK_DBG("%s, %s has no gate register\n", __func__, clk->name); ++ return; ++ } ++ ++ reg = fh_pmu_get_reg(clk->en_reg_offset); ++ reg |= clk->en_reg_mask; ++ fh_pmu_set_reg(clk->en_reg_offset, reg); ++ ++ PRINT_CLK_DBG("%s, clk: %s, reg: 0x%x\n", __func__, clk->name, reg); ++} ++ ++static int fh_clk_get_sel(struct clk *clk) ++{ ++ unsigned int reg, shift; ++ int ret; ++ ++ if (!(clk->flag & CLOCK_MULTI_PARENT)) ++ return 0; ++ ++ shift = ffs(clk->sel_reg_mask) - 1; ++ reg = fh_pmu_get_reg(clk->sel_reg_offset); ++ reg &= clk->sel_reg_mask; ++ ret = reg >> shift; ++ PRINT_CLK_DBG("%s, clk: %s, sel: %d\n", __func__, clk->name, ret); ++ ++ return ret; ++} ++ ++static void fh_clk_set_sel(struct clk *clk, int sel) ++{ ++ unsigned int reg, shift; ++ ++ if (!(clk->flag & CLOCK_MULTI_PARENT)) { ++ PRINT_CLK_DBG("%s, clk: %s has only one parent\n", __func__, clk->name); ++ return; ++ } ++ ++ clk->select = sel; ++ shift = ffs(clk->sel_reg_mask) - 1; ++ reg = fh_pmu_get_reg(clk->sel_reg_offset); ++ reg &= ~(clk->sel_reg_mask); ++ reg |= (sel << shift); ++ fh_pmu_set_reg(clk->sel_reg_offset, reg); ++ PRINT_CLK_DBG("%s, clk: %s, select: %d, reg: 0x%x\n", __func__, clk->name, sel, ++ reg); ++} ++ ++static unsigned long fh_clk_get_pll_rate(struct clk *clk) ++{ ++ unsigned int reg, m, n, od, no = 1, i; ++ ++ reg = fh_pmu_get_reg(clk->div_reg_offset); ++ m = reg & 0xff; ++ n = (reg >> 8) & 0xf; ++ od = (reg >> 16) & 0x3; ++ ++ for(i=0; i<od; i++) ++ no *= 2; ++ ++ clk->frequency = OSC_FREQUENCY * m / n / no; ++ ++ return clk->frequency; ++} ++ ++static unsigned long fh_clk_get_pll_p_rate(struct clk *clk) ++{ ++ unsigned int reg, m, n, p, r = 1; ++ unsigned int clk_vco, divvcop = 1, shift; ++ ++ reg = fh_pmu_get_reg(clk->div_reg_offset); ++ ++ m = reg & 0x7f; ++ n = (reg >> 8) & 0x1f; ++ p = (reg >> 16) & 0x3f; ++ r = (reg >> 24) & 0x3f; ++ ++ /*pll databook*/ ++ if (m<4) ++ m=128+m; ++ ++ if (m==0xb) ++ m=0xa; ++ ++ shift = ffs(clk->en_reg_mask)-1; ++ reg = fh_pmu_get_reg(clk->en_reg_offset); ++ ++ switch ((reg&clk->en_reg_mask)>>shift){ ++ case DIVVCO_ONE_DEVISION: ++ divvcop=1; ++ break; ++ ++ case DIVVCO_TWO_DEVISION: ++ divvcop=2; ++ break; ++ ++ case DIVVCO_FOUR_DEVISION: ++ divvcop=4; ++ break; ++ ++ case DIVVCO_EIGHT_DEVISION: ++ divvcop=8; ++ break; ++ ++ case DIVVCO_SIXTEEN_DEVISION: ++ divvcop=16; ++ break; ++ ++ case DIVVCO_THIRTYTWO_DEVISION: ++ divvcop=32; ++ break; ++ default: ++ printk("divvcop error:%x\n",divvcop); ++ } ++ ++ clk_vco = OSC_FREQUENCY * m / (n+1); ++ clk->frequency = clk_vco/ (p+1)/divvcop; ++ return clk->frequency; ++} ++ ++static unsigned long fh_clk_get_pll_r_rate(struct clk *clk) ++{ ++ unsigned int reg, m, n, p, r = 1; ++ unsigned int clk_vco,divvcor=1,shift; ++ ++ reg = fh_pmu_get_reg(clk->div_reg_offset); ++ ++ m = reg & 0x7f; ++ n = (reg >> 8) & 0x1f; ++ p = (reg >> 16) & 0x3f; ++ r = (reg >> 24) & 0x3f; ++ ++ /*pll databook*/ ++ if(m<4) ++ m=128+m; ++ ++ if(m==0xb) ++ m=0xa; ++ ++ shift = ffs(clk->en_reg_mask)-1; ++ reg = fh_pmu_get_reg(clk->en_reg_offset); ++ ++ switch ((reg&clk->en_reg_mask)>>shift){ ++ case DIVVCO_ONE_DEVISION: ++ divvcor=1; ++ break; ++ ++ case DIVVCO_TWO_DEVISION: ++ divvcor=2; ++ break; ++ ++ case DIVVCO_FOUR_DEVISION: ++ divvcor=4; ++ break; ++ ++ case DIVVCO_EIGHT_DEVISION: ++ divvcor=8; ++ break; ++ ++ case DIVVCO_SIXTEEN_DEVISION: ++ divvcor=16; ++ break; ++ ++ case DIVVCO_THIRTYTWO_DEVISION: ++ divvcor=32; ++ break; ++ default: ++ printk("divvcop error:%x\n", divvcor); ++ } ++ ++ ++ clk_vco = OSC_FREQUENCY * m / (n+1); ++ clk->frequency = clk_vco/ (r+1)/divvcor; ++ return clk->frequency; ++} ++ ++static int fh_clk_get_div(struct clk *clk) ++{ ++ unsigned int reg, shift; ++ int ret; ++ ++ if (clk->flag & (CLOCK_NODIV | CLOCK_FIXED)) ++ return 0; ++ ++ shift = ffs(clk->div_reg_mask) - 1; ++ reg = fh_pmu_get_reg(clk->div_reg_offset); ++ PRINT_CLK_DBG("%s, clk: %s, reg: 0x%x\n", __func__, clk->name, reg); ++ reg &= clk->div_reg_mask; ++ PRINT_CLK_DBG("%s, clk: %s, shift: %d, after mask: 0x%x\n", __func__, clk->name, ++ shift, reg); ++ ret = reg >> shift; ++ PRINT_CLK_DBG("%s, clk: %s, div: %d\n", __func__, clk->name, ret); ++ PRINT_CLK_DBG("%s, clk: %s, div_mask: 0x%x, div_offset: 0x%x\n", ++ __func__, clk->name, clk->div_reg_mask, clk->div_reg_offset); ++ ++ return ret; ++} ++ ++static void fh_clk_set_div(struct clk *clk, int div) ++{ ++ unsigned int reg, shift; ++ ++ if (clk->flag & CLOCK_NODIV) { ++ PRINT_CLK_DBG("%s, clk: %s has no divide\n", __func__, clk->name); ++ return; ++ } ++ ++ shift = ffs(clk->div_reg_mask) - 1; ++ ++ if(div > clk->div_reg_mask >> shift) { ++ pr_err("%s, clk: %s, curr div %d is too big, max is %d\n", ++ __func__, clk->name, div, clk->div_reg_mask >> shift); ++ return; ++ } ++ ++ clk->divide = div; ++ ++ reg = fh_pmu_get_reg(clk->div_reg_offset); ++ PRINT_CLK_DBG("%s, clk: %s, reg: 0x%x\n", __func__, clk->name, reg); ++ reg &= ~(clk->div_reg_mask); ++ reg |= (div << shift); ++ PRINT_CLK_DBG("%s, clk: %s, shift: %d, after mask: 0x%x\n", __func__, clk->name, ++ shift, reg); ++ fh_pmu_set_reg(clk->div_reg_offset, reg); ++ PRINT_CLK_DBG("%s, clk: %s, div: %d, reg: 0x%x\n", __func__, clk->name, div, ++ reg); ++ PRINT_CLK_DBG("%s, clk: %s, div_mask: 0x%x, div_offset: 0x%x\n", ++ __func__, clk->name, clk->div_reg_mask, clk->div_reg_offset); ++ ++} ++ ++unsigned long fh_clk_get_rate(struct clk *clk) ++{ ++ if (clk->flag & CLOCK_FIXED) { ++ PRINT_CLK_DBG("%s, clk: %s is fixed clock, rate: %lu\n", __func__, clk->name, ++ clk->frequency); ++ return clk->frequency; ++ } ++ ++ if (clk->flag & CLOCK_PLL) { ++ PRINT_CLK_DBG("%s, clk: %s is a PLL clock\n", __func__, clk->name); ++ return fh_clk_get_pll_rate(clk); ++ } ++ ++ if (clk->flag & CLOCK_PLL_P) { ++ PRINT_CLK_DBG("%s, clk: %s is a PLL clock\n", __func__, clk->name); ++ return fh_clk_get_pll_p_rate(clk); ++ } ++ ++ if (clk->flag & CLOCK_PLL_R) { ++ PRINT_CLK_DBG("%s, clk: %s is a PLL clock\n", __func__, clk->name); ++ return fh_clk_get_pll_r_rate(clk); ++ } ++ ++ if (clk->flag & CLOCK_CIS && (0 == fh_clk_get_sel(clk))) { ++ clk->frequency = OSC_FREQUENCY; ++ return clk->frequency; ++ } ++ ++ clk->select = fh_clk_get_sel(clk); ++ clk->divide = fh_clk_get_div(clk) + 1; ++ ++ if (clk->select > CLOCK_MAX_PARENT) { ++ pr_err("ERROR, %s, clk: %s, select is not correct, clk->select: %d\n", __func__, ++ clk->name, clk->select); ++ return 0; ++ } ++ ++ if (!clk->parent[clk->select]) { ++ pr_err("ERROR, %s, clk: %s has no parent and is not a fixed clock\n", __func__, ++ clk->name); ++ return 0; ++ } ++ ++ clk->frequency = clk->parent[clk->select]->frequency / clk->prediv; ++ clk->frequency /= clk->divide; ++ ++ PRINT_CLK_DBG("%s, clk: %s, rate: %lu\n", __func__, clk->name, clk->frequency); ++ ++ return clk->frequency; ++} ++ ++void fh_clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ if (clk->flag & CLOCK_FIXED) { ++ pr_err("%s, clk: %s is fixed clock, rate: %lu\n", __func__, clk->name, ++ clk->frequency); ++ return; ++ } ++ ++ if (clk->flag & (CLOCK_PLL | CLOCK_PLL_R | CLOCK_PLL_P)) { ++ pr_err("%s, clk: %s is a PLL clock, changing frequency is not recommended\n", ++ __func__, clk->name); ++ return; ++ } ++ if (clk->select > CLOCK_MAX_PARENT) { ++ pr_err("ERROR, %s, clk: %s, select is not correct, clk->select: %d\n", __func__, ++ clk->name, clk->select); ++ return; ++ } ++ ++ if (!clk->parent[clk->select]) { ++ pr_err("ERROR, %s, clk: %s has no parent and is not a fixed clock\n", __func__, ++ clk->name); ++ return; ++ } ++ if (clk->flag & CLOCK_CIS) { ++ ++ if (rate == OSC_FREQUENCY) { ++ fh_clk_set_sel(clk, 0); ++ clk->frequency = rate; ++ return; ++ } else ++ fh_clk_set_sel(clk, 1); ++ } ++ ++ clk->frequency = clk->parent[clk->select]->frequency / clk->prediv; ++ clk->divide = clk->frequency / rate; ++ PRINT_CLK_DBG("%s, clk: %s, set rate: %lu, divide: %d\n", __func__, clk->name, ++ rate, clk->divide); ++ fh_clk_set_div(clk, clk->divide - 1); ++ ++ clk->frequency = rate; ++ ++ PRINT_CLK_DBG("%s, clk: %s, rate: %lu\n", __func__, clk->name, clk->frequency); ++} ++ ++void fh_clk_reset(struct clk *clk) ++{ ++ unsigned int reg; ++ ++ if (clk->flag & CLOCK_NORESET) { ++ pr_err("%s, clk: %s has no reset\n", __func__, clk->name); ++ return; ++ } ++ ++ reg = 0xffffffff & ~(clk->rst_reg_mask); ++ ++ fh_pmu_set_reg(clk->rst_reg_offset, reg); ++ while (fh_pmu_get_reg(clk->rst_reg_offset) != 0xffffffff) { ++ ++ } ++ PRINT_CLK_DBG("%s, clk: %s has been reset\n", __func__, clk->name); ++} ++ ++int clk_enable(struct clk *clk) ++{ ++ unsigned long flags; ++ ++ if (clk == NULL || IS_ERR(clk)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ if(clk->flag & (CLOCK_PLL_R | CLOCK_PLL_P)) ++ fh_clk_disable(clk); ++ else ++ fh_clk_enable(clk); ++ spin_unlock_irqrestore(&clocks_lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL(clk_enable); ++ ++void clk_disable(struct clk *clk) ++{ ++ unsigned long flags; ++ ++ if (clk == NULL || IS_ERR(clk)) ++ return; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ if (clk->flag & (CLOCK_PLL_R | CLOCK_PLL_P)) ++ fh_clk_enable(clk); ++ else ++ fh_clk_disable(clk); ++ spin_unlock_irqrestore(&clocks_lock, flags); ++} ++EXPORT_SYMBOL(clk_disable); ++ ++ ++unsigned long clk_get_rate(struct clk *clk) ++{ ++ unsigned long flags, rate; ++ if (clk == NULL || IS_ERR(clk)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ ++ rate = fh_clk_get_rate(clk); ++ ++ spin_unlock_irqrestore(&clocks_lock, flags); ++ ++ return rate; ++} ++EXPORT_SYMBOL(clk_get_rate); ++ ++ ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ unsigned long flags, real_rate; ++ int ret = -EINVAL; ++ ++ if (clk == NULL || IS_ERR(clk)) ++ return ret; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ fh_clk_set_rate(clk, rate); ++ real_rate = clk_get_rate(clk); ++ if (rate != real_rate) ++ printk("WARN: set clk %s to %ld, but get %ld\n", clk->name, rate, real_rate); ++ ++ spin_unlock_irqrestore(&clocks_lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL(clk_set_rate); ++ ++void clk_reset(struct clk *clk) ++{ ++ unsigned long flags; ++ ++ if (clk == NULL || IS_ERR(clk)) ++ return; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ fh_clk_reset(clk); ++ spin_unlock_irqrestore(&clocks_lock, flags); ++} ++EXPORT_SYMBOL(clk_reset); ++ ++void clk_change_parent(struct clk *clk, int select) ++{ ++ unsigned long flags; ++ ++ if (clk == NULL || IS_ERR(clk)) ++ return; ++ ++ spin_lock_irqsave(&clocks_lock, flags); ++ fh_clk_set_sel(clk, select); ++ spin_unlock_irqrestore(&clocks_lock, flags); ++} ++EXPORT_SYMBOL(clk_change_parent); ++ ++int clk_register(struct clk *clk) ++{ ++ if (clk == NULL || IS_ERR(clk)) ++ return -EINVAL; ++ ++ if (WARN(clk->parent[clk->select] && !clk->parent[clk->select]->frequency, ++ "CLK: %s parent %s has no rate!\n", ++ clk->name, clk->parent[clk->select]->name)) ++ return -EINVAL; ++ ++ clk_get_rate(clk); ++ ++ PRINT_CLK_DBG("clk: %s has been registered, div: %d, sel: %d\n", ++ clk->name, clk->divide, clk->select); ++ ++ mutex_lock(&clocks_mutex); ++ list_add_tail(&clk->list, &clocks); ++ mutex_unlock(&clocks_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL(clk_register); ++ ++void clk_unregister(struct clk *clk) ++{ ++ if (clk == NULL || IS_ERR(clk)) ++ return; ++ ++ mutex_lock(&clocks_mutex); ++ list_del(&clk->list); ++ mutex_unlock(&clocks_mutex); ++} ++EXPORT_SYMBOL(clk_unregister); ++ ++ ++static void del_char(char* str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) { ++ *p++ = *q; ++ } ++ q++; ++ } ++ *p = '\0'; ++} ++ ++static ssize_t fh_clk_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off) ++{ ++ int i, ret; ++ char message[64] = {0}; ++ char * const delim = ","; ++ char *cur = message; ++ char *param_str[4]; ++ unsigned int param[4]; ++ struct clk *clk; ++ ++ len = (len > 64) ? 64 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ for (i = 0; i < 3; i++) { ++ param_str[i] = strsep(&cur, delim); ++ if (!param_str[i]) { ++ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i); ++ pr_err("[clk name], [enable/disable], [clk rate]\n"); ++ return -EINVAL; ++ } else { ++ del_char(param_str[i], ' '); ++ del_char(param_str[i], '\n'); ++ } ++ } ++ ++ clk = clk_get(NULL, param_str[0]); ++ if (!clk) { ++ pr_err("%s: ERROR: clk %s is not found\n", __func__, param_str[0]); ++ pr_err("[clk name], [enable/disable], [clk rate]\n"); ++ return -EINVAL; ++ } ++ ++ param[2] = (u32)simple_strtoul(param_str[2], NULL, 10); ++ if (param[2] < 0) { ++ pr_err("ERROR: parameter[2] is incorrect\n"); ++ return -EINVAL; ++ } ++ ++ ret = clk_set_rate(clk, param[2]); ++ if (ret) { ++ pr_err("set clk rate failed\n, ret=%d\n", ret); ++ } ++ ++ if (!strcmp(param_str[1], "enable")) { ++ clk_enable(clk); ++ printk("clk %s enabled\n", param_str[0]); ++ } ++ else if (!strcmp(param_str[1], "disable")) { ++ clk_disable(clk); ++ printk(KERN_ERR "clk %s disabled\n", param_str[0]); ++ } else { ++ pr_err("%s: ERROR: parameter[1]:%s is incorrect\n", ++ __func__, param_str[1]); ++ pr_err("[clk name], [enable/disable], [clk rate]\n"); ++ return -EINVAL; ++ } ++ ++ return len; ++} ++ ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ ++ struct clk_lookup *clock_lookup; ++ struct clk *clk; ++ unsigned long rate; ++ unsigned int reg; ++ char gate[10] = {0}; ++ seq_printf(sfile, "\nPLL Information: \n"); ++ for (clock_lookup = fh_clks; clock_lookup->clk; clock_lookup++) { ++ clk = clock_lookup->clk; ++ ++ if (clk->flag & CLOCK_HIDE) ++ continue; ++ ++ rate = clk_get_rate(clk); ++ if (!(clk->flag & CLOCK_NOGATE)) { ++ reg = fh_pmu_get_reg(clk->en_reg_offset); ++ reg &= clk->en_reg_mask; ++ if (reg) { ++ if (clk->flag & (CLOCK_PLL_P|CLOCK_PLL_R)) ++ strncpy(gate, "enable", sizeof(gate)); ++ else ++ strncpy(gate, "disable", sizeof(gate)); ++ } else { ++ if (clk->flag & (CLOCK_PLL_P|CLOCK_PLL_R)) ++ strncpy(gate, "disable", sizeof(gate)); ++ else ++ strncpy(gate, "enable", sizeof(gate)); ++ } ++ } else { ++ strncpy(gate, "nogate", sizeof(gate)); ++ } ++ seq_printf(sfile, "\t%-20s \t%9luHZ \t%-10s\n", ++ clk->name, rate, gate); ++} ++ return 0; ++} ++ ++static const struct seq_operations fh_clk_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_clk_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &fh_clk_seq_ops); ++} ++ ++ ++static struct file_operations fh_clk_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_clk_proc_open, ++ .read = seq_read, ++ .write = fh_clk_proc_write, ++ .release = seq_release, ++}; ++ ++int __init fh_clk_procfs_init(void) ++{ ++ proc_file = create_proc_entry(PROC_FILE, 0644, NULL); ++ if (proc_file) ++ proc_file->proc_fops = &fh_clk_proc_ops; ++ else ++ pr_err("clock, create proc fs failed\n"); ++ ++ return 0; ++} ++ ++int __init fh_clk_init(void) ++{ ++ struct clk_lookup *clock_lookup; ++ struct clk *clk; ++ size_t num_clocks = 0; ++ ++ for (clock_lookup = fh_clks; clock_lookup->clk; clock_lookup++) { ++ clk = clock_lookup->clk; ++ num_clocks++; ++ clk_register(clk); ++ if (clk->def_rate) ++ clk_set_rate(clk, clk->def_rate); ++ } ++ clkdev_add_table(fh_clks, num_clocks); ++ return 0; ++} +diff --git a/arch/arm/mach-fh/fh8856.c b/arch/arm/mach-fh/fh8856.c +new file mode 100644 +index 00000000..a6ac7c92 +--- /dev/null ++++ b/arch/arm/mach-fh/fh8856.c +@@ -0,0 +1,597 @@ ++/* ++ * Fullhan FH8833 board support ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include <linux/init.h> ++#include <linux/clk.h> ++#include <linux/serial_8250.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <linux/gpio.h> ++#include <linux/spi/spi.h> ++ ++#include <asm/mach/map.h> ++ ++#include <mach/chip.h> ++#include <mach/irqs.h> ++#include <mach/timex.h> ++#include <mach/pmu.h> ++#include <mach/clock.h> ++#include <mach/board_config.h> ++ ++/* ++ * external oscillator ++ * fixed to 24M ++ */ ++static struct clk osc_clk = { ++ .name = "osc_clk", ++ .frequency = OSC_FREQUENCY, ++ .flag = CLOCK_FIXED, ++}; ++ ++/* ++ * phase-locked-loop device, ++ * generates a higher frequency clock ++ * from the external oscillator reference ++ */ ++static struct clk pll0p_clk = { ++ .name = "pll0p_clk", ++ .flag = CLOCK_PLL_P, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL0, ++ .en_reg_offset = REG_PMU_PLL_CTRL, ++ .en_reg_mask = 0xf00, ++}; ++ ++static struct clk pll0r_clk = { ++ .name = "pll0r_clk", ++ .flag = CLOCK_PLL_R, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL0, ++ .en_reg_offset = REG_PMU_PLL_CTRL, ++ .en_reg_mask = 0xf000, ++}; ++ ++#if 0 ++static struct clk pll1p_clk = { ++ .name = "pll1p_clk", ++ .flag = CLOCK_PLL_P, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL1, ++ .en_reg_offset = REG_PMU_PLL_CTRL, ++ .en_reg_mask = 0xf000000, ++}; ++#endif ++ ++static struct clk pll1r_clk = { ++ .name = "pll1r_clk", ++ .flag = CLOCK_PLL_R, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL1, ++ .en_reg_offset = REG_PMU_PLL_CTRL, ++ .en_reg_mask = 0xf0000000, ++}; ++ ++static struct clk pll2p_clk = { ++ .name = "pll2p_clk", ++ .flag = CLOCK_PLL_P, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL2, ++ .en_reg_offset = REG_PMU_PLL2_CTRL, ++ .en_reg_mask = 0xf00, ++}; ++ ++#if 0 ++static struct clk pll2r_clk = { ++ .name = "pll2r_clk", ++ .flag = CLOCK_PLL_R, ++ .parent = {&osc_clk}, ++ .div_reg_offset = REG_PMU_PLL2, ++ .en_reg_offset = REG_PMU_PLL2_CTRL, ++ .en_reg_mask = 0xf000, ++}; ++#endif ++/* ++ * pll0r ++ */ ++static struct clk arm_clk = { ++ .name = "arm_clk", ++ .flag = CLOCK_NOGATE, ++ .parent = {&pll0r_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x1, ++}; ++ ++static struct clk ahb_clk = { ++ .name = "ahb_clk", ++ .flag = CLOCK_NORESET|CLOCK_NOGATE, ++ .parent = {&pll0r_clk}, ++ .prediv = 2, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf0000, ++}; ++static struct clk arc_clk = { ++ .name = "arc_clk", ++ .flag = 0, ++ .parent = {&pll0r_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x4, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x400000, ++}; ++ ++static struct clk pae_arc_clk = { ++ .name = "pae_arc_clk", ++ .flag = 0, ++ .parent = {&pll0r_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x8, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x400000, ++}; ++ ++static struct clk cis_clk_out = { ++ .name = "cis_clk_out", ++ .flag = CLOCK_NORESET, ++ .parent = {&pll0r_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV1, ++ .div_reg_mask = 0xff0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x800000, ++}; ++ ++/* ++ * pll1r ++ */ ++static struct clk ddr_clk = { ++ .name = "ddr_clk", ++ .parent = {&pll1r_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV1, ++ .div_reg_mask = 0xf, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x40, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x8, ++}; ++/* ++ * pll0p ++ */ ++ ++static struct clk isp_aclk = { ++ .name = "isp_aclk", ++ .flag = CLOCK_NORESET, ++ .parent = {&pll0p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf00, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x1, ++ .def_rate = CONFIG_ISP_CLK_RATE, ++}; ++ ++static struct clk jpeg_clk = { ++ .name = "jpeg_clk", ++ .flag = CLOCK_NORESET|CLOCK_NODIV, ++ .parent = {&isp_aclk}, ++ .prediv = 1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x1, ++}; ++ ++static struct clk vpu_clk = { ++ .name = "vpu_clk", ++ .flag = CLOCK_NORESET|CLOCK_NODIV, ++ .parent = {&isp_aclk}, ++ .prediv = 1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x1, ++}; ++ ++static struct clk bgm_clk = { ++ .name = "bgm_clk", ++ .flag = CLOCK_NORESET, ++ .parent = {&pll0p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0xf00, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x40000, ++}; ++ ++static struct clk mipi_dphy_clk = { ++ .name = "mipi_dphy_clk", ++ .flag = CLOCK_NORESET|CLOCK_NODIV, ++ .parent = {&osc_clk}, ++ .prediv = 1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x100000, ++}; ++ ++static struct clk pix_clk = { ++ .name = "pix_clk", ++ .flag = CLOCK_NORESET, ++ .parent = {&pll0p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV2, ++ .div_reg_mask = 0xf000000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x400000, ++}; ++ ++static struct clk pae_clk = { ++ .name = "pae_clk", ++ .flag = CLOCK_NORESET|CLOCK_MULTI_PARENT|CLOCK_HIDE, ++ .parent = {&pll0p_clk, &pll2p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV0, ++ .div_reg_mask = 0x7000000, ++ .sel_reg_offset = REG_PMU_CLK_SEL, ++ .sel_reg_mask = 0x2, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x10, ++ .def_rate = CONFIG_PAE_CLK_RATE, ++}; ++ ++static struct clk ddrc_a1clk = { ++ .name = "ddrc_a1clk", ++ .flag = CLOCK_NORESET|CLOCK_NODIV, ++ .parent = {&pae_clk}, ++ .prediv = 1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x20, ++}; ++ ++/* ++ * pll2p ++ */ ++ ++static struct clk hevc_aclk = { ++ .name = "hevc_aclk", ++ .flag = CLOCK_MULTI_PARENT|CLOCK_HIDE, ++ .parent = {&pll0p_clk, &pll2p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV7, ++ .div_reg_mask = 0x700, ++ .sel_reg_offset = REG_PMU_CLK_SEL, ++ .sel_reg_mask = 0x1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x20000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x1000000, ++ .def_rate = CONFIG_HEVC_CLK_RATE, ++}; ++ ++static struct clk hevc_bclk = { ++ .name = "hevc_bclk", ++ .flag = CLOCK_MULTI_PARENT|CLOCK_HIDE, ++ .parent = {&pll0p_clk , &pll2p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV7, ++ .div_reg_mask = 0x70000, ++ .sel_reg_offset = REG_PMU_CLK_SEL, ++ .sel_reg_mask = 0x1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x40000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x2000000, ++ .def_rate = CONFIG_HEVC_CLK_RATE, ++}; ++ ++static struct clk hevc_cclk = { ++ .name = "hevc_cclk", ++ .flag = CLOCK_MULTI_PARENT|CLOCK_HIDE, ++ .parent = {&pll0p_clk, &pll2p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV7, ++ .div_reg_mask = 0x7000000, ++ .sel_reg_offset = REG_PMU_CLK_SEL, ++ .sel_reg_mask = 0x1, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x80000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x4000000, ++ .def_rate = CONFIG_HEVC_CLK_RATE, ++}; ++ ++ ++static struct clk pll0_div12_dw_clk = { ++ .name = "pll0_div12_dw_clk", ++ .flag = CLOCK_NORESET|CLOCK_NOGATE, ++ .parent = {&pll0p_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV5, ++ .div_reg_mask = 0xf000000, ++}; ++ ++static struct clk sdc0_clk = { ++ .name = "sdc0_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 2, ++ .div_reg_offset = REG_PMU_CLK_DIV3, ++ .div_reg_mask = 0xf00, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x200, ++ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL, ++ .rst_reg_mask = 0x4, ++}; ++ ++static struct clk sdc1_clk = { ++ .name = "sdc1_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 2, ++ .div_reg_offset = REG_PMU_CLK_DIV3, ++ .div_reg_mask = 0xf000000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x400, ++ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL, ++ .rst_reg_mask = 0x2, ++}; ++ ++static struct clk spi0_clk = { ++ .name = "spi0_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV3, ++ .div_reg_mask = 0xff, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x80, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x100, ++}; ++ ++static struct clk spi1_clk = { ++ .name = "spi1_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV3, ++ .div_reg_mask = 0xff0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x100, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x200, ++}; ++ ++static struct clk spi2_clk = { ++ .name = "spi2_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV3, ++ .div_reg_mask = 0xf000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x2, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x100000, ++}; ++ ++static struct clk eth_clk = { ++ .name = "eth_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV6, ++ .div_reg_mask = 0xf000000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x12000000, ++ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL, ++ .rst_reg_mask = 0x20000, ++}; ++ ++static struct clk i2c0_clk = { ++ .name = "i2c0_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV4, ++ .div_reg_mask = 0x3f0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x1000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x400, ++}; ++ ++static struct clk i2c1_clk = { ++ .name = "i2c1_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV4, ++ .div_reg_mask = 0x3f000000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x8000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x800, ++}; ++ ++static struct clk pwm_clk = { ++ .name = "pwm_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV5, ++ .div_reg_mask = 0xff, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x10000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x80, ++ .def_rate = 50000000, ++}; ++ ++static struct clk uart0_clk = { ++ .name = "uart0_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV4, ++ .div_reg_mask = 0x1f, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x2000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x4000, ++ .def_rate = 16666666, ++}; ++ ++static struct clk uart1_clk = { ++ .name = "uart1_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV4, ++ .div_reg_mask = 0x1f00, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x4000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x8000, ++ .def_rate = 16666666, ++}; ++ ++static struct clk pts_clk = { ++ .name = "pts_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV2, ++ .div_reg_mask = 0x1ff, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x80000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x20000, ++ .def_rate = 1000000, ++}; ++ ++static struct clk efuse_clk = { ++ .name = "efuse_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV1, ++ .div_reg_mask = 0x3f000000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x200000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x800000, ++}; ++ ++static struct clk tmr0_clk = { ++ .name = "tmr0_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV5, ++ .div_reg_mask = 0xff0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x20000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x40000, ++}; ++ ++static struct clk sadc_clk = { ++ .name = "sadc_clk", ++ .parent = {&pll0_div12_dw_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV6, ++ .div_reg_mask = 0x7f0000, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x4000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x10000, ++}; ++ ++static struct clk ac_clk = { ++ .name = "ac_clk", ++ .parent = {&osc_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV6, ++ .div_reg_mask = 0x3f, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x800, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x1000, ++}; ++ ++static struct clk i2s_clk = { ++ .name = "i2s_clk", ++ .parent = {&ac_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV6, ++ .div_reg_mask = 0x3f00, ++ .en_reg_offset = REG_PMU_CLK_GATE, ++ .en_reg_mask = 0x1000000, ++ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL, ++ .rst_reg_mask = 0x2000, ++}; ++ ++static struct clk wdt_clk = { ++ .name = "wdt_clk", ++ .flag = CLOCK_NOGATE, ++ .parent = {&ahb_clk}, ++ .prediv = 1, ++ .div_reg_offset = REG_PMU_CLK_DIV5, ++ .div_reg_mask = 0xff00, ++ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL, ++ .rst_reg_mask = 0x100000, ++ .def_rate = 1000000, ++}; ++ ++struct clk_lookup fh_clks[] = { ++ CLK(NULL, "osc_clk", &osc_clk), ++ CLK(NULL, "pll0p_clk", &pll0p_clk), ++ CLK(NULL, "pll0r_clk", &pll0r_clk), ++ CLK(NULL, "pll1r_clk", &pll1r_clk), ++ CLK(NULL, "pll2p_clk", &pll2p_clk), ++ ++ CLK(NULL, "arm_clk", &arm_clk), ++ CLK(NULL, "arc_clk", &arc_clk), ++ CLK(NULL, "pae_arc_clk", &pae_arc_clk), ++ CLK(NULL, "ahb_clk", &ahb_clk), ++ ++ CLK(NULL, "ddr_clk", &ddr_clk), ++ CLK(NULL, "isp_aclk", &isp_aclk), ++ CLK(NULL, "jpeg_clk", &jpeg_clk), ++ CLK(NULL, "vpu_clk", &vpu_clk), ++ CLK(NULL, "pae_clk", &pae_clk), ++ CLK(NULL, "bgm_clk", &bgm_clk), ++ CLK(NULL, "mipi_dphy_clk", &mipi_dphy_clk), ++ CLK(NULL, "ddrc_a1clk", &ddrc_a1clk), ++ ++ CLK(NULL, "hevc_aclk", &hevc_aclk), ++ CLK(NULL, "hevc_bclk", &hevc_bclk), ++ CLK(NULL, "hevc_cclk", &hevc_cclk), ++ CLK(NULL, "pll0_div12_dw_clk", &pll0_div12_dw_clk), ++ ++ CLK(NULL, "cis_clk_out", &cis_clk_out), ++ CLK(NULL, "pix_clk", &pix_clk), ++ CLK(NULL, "pts_clk", &pts_clk), ++ ++ CLK(NULL, "spi0_clk", &spi0_clk), ++ CLK(NULL, "spi1_clk", &spi1_clk), ++ CLK(NULL, "spi2_clk", &spi2_clk), ++ CLK(NULL, "sdc0_clk", &sdc0_clk), ++ CLK(NULL, "sdc1_clk", &sdc1_clk), ++ CLK(NULL, "uart0_clk", &uart0_clk), ++ CLK(NULL, "uart1_clk", &uart1_clk), ++ CLK(NULL, "i2c0_clk", &i2c0_clk), ++ CLK(NULL, "i2c1_clk", &i2c1_clk), ++ CLK(NULL, "pwm_clk", &pwm_clk), ++ CLK(NULL, "wdt_clk", &wdt_clk), ++ CLK(NULL, "tmr0_clk", &tmr0_clk), ++ CLK(NULL, "ac_clk", &ac_clk), ++ CLK(NULL, "i2s_clk", &i2s_clk), ++ CLK(NULL, "sadc_clk", &sadc_clk), ++ CLK(NULL, "eth_clk", ð_clk), ++ CLK(NULL, "efuse_clk", &efuse_clk), ++ ++ CLK(NULL, NULL, NULL), ++}; ++EXPORT_SYMBOL(fh_clks); +diff --git a/arch/arm/mach-fh/fh_chipid.c b/arch/arm/mach-fh/fh_chipid.c +new file mode 100644 +index 00000000..5f2693c2 +--- /dev/null ++++ b/arch/arm/mach-fh/fh_chipid.c +@@ -0,0 +1,216 @@ ++/** ++ * Copyright (c) 2015-2019 Shanghai Fullhan Microelectronics Co., Ltd. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * ++ * Change Logs: ++ * Date Author Notes ++ * 2019-08-20 wangyl add license Apache-2.0 ++ */ ++ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++#include <mach/pmu.h> ++#include <mach/fh_chipid.h> ++ ++#define CHIP_INFO(__plat_id, __chip_id, __chip_mask, chip, size) \ ++ { \ ++ ._plat_id = __plat_id, \ ++ ._chip_id = __chip_id, \ ++ ._chip_mask = __chip_mask, \ ++ .chip_id = FH_CHIP_##chip, \ ++ .ddr_size = size, \ ++ .chip_name = #chip, \ ++ }, ++ ++static struct fh_chip_info chip_infos[] = { ++ CHIP_INFO(0x46488302, 0x37, 0x3F, FH8632, 512) ++ CHIP_INFO(0x46488302, 0x07, 0x3F, FH8632v2, 512) ++ CHIP_INFO(0x17092901, 0xC, 0xF, FH8852, 512) ++ CHIP_INFO(0x17092901, 0xD, 0xF, FH8856, 1024) ++ CHIP_INFO(0x18112301, 0x3, 0x3, FH8626V100, 512) ++}; ++ ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ++#endif ++ ++ ++void fh_get_chipid(unsigned int *plat_id, unsigned int *chip_id) ++{ ++ unsigned int _plat_id = 0; ++ ++ _plat_id = fh_pmu_get_reg(REG_PMU_CHIP_ID); ++ if (plat_id != NULL) ++ *plat_id = _plat_id; ++ ++ if (chip_id != NULL) ++ { ++ switch (_plat_id) ++ { ++ case 0x46488302: ++ *chip_id = fh_pmu_get_reg(REG_PMU_SPC_IO_STATUS); ++ break; ++ default: ++ *chip_id = fh_pmu_get_reg(REG_PMU_IP_VER); ++ break; ++ } ++ } ++} ++EXPORT_SYMBOL(fh_get_chipid); ++ ++#define FH_GET_CHIP_ID(plat_id, chip_id) \ ++ int plat_id = 0;\ ++ int chip_id = 0;\ ++ fh_get_chipid(&plat_id, &chip_id) ++ ++ ++struct fh_chip_info *fh_get_chip_info(void) ++{ ++ static struct fh_chip_info *chip_info = NULL; ++ struct fh_chip_info *info = NULL; ++ int plat_id = 0; ++ int chip_id = 0; ++ int i = 0; ++ ++ if (chip_info != NULL) ++ return chip_info; ++ ++ fh_get_chipid(&plat_id, &chip_id); ++ ++ for (i = 0; i < ARRAY_SIZE(chip_infos); i++) ++ { ++ info = &chip_infos[i]; ++ if (plat_id == info->_plat_id && (chip_id & info->_chip_mask) == info->_chip_id) ++ { ++ chip_info = info; ++ return info; ++ } ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(fh_get_chip_info); ++ ++unsigned int fh_get_ddrsize_mbit(void) ++{ ++ struct fh_chip_info *info = fh_get_chip_info(); ++ ++ if (info) ++ return info->ddr_size; ++ return 0; ++} ++EXPORT_SYMBOL(fh_get_ddrsize_mbit); ++ ++char *fh_get_chipname(void) ++{ ++ struct fh_chip_info *info = fh_get_chip_info(); ++ ++ if (info) ++ return info->chip_name; ++ return "UNKNOWN"; ++} ++EXPORT_SYMBOL(fh_get_chipname); ++ ++#define DEFINE_FUNC_FH_IS(name, chip) \ ++unsigned int fh_is_##name(void) \ ++{ \ ++ struct fh_chip_info *info = fh_get_chip_info(); \ ++ \ ++ if (info) \ ++ return info->chip_id == FH_CHIP_##chip; \ ++ return 0; \ ++} \ ++EXPORT_SYMBOL(fh_is_##name) ++ ++unsigned int fh_is_8632(void) ++{ ++ struct fh_chip_info *info = fh_get_chip_info(); ++ ++ if (info) ++ return (info->chip_id == FH_CHIP_FH8632 || \ ++ info->chip_id == FH_CHIP_FH8632v2); ++ return 0; ++} ++EXPORT_SYMBOL(fh_is_8632); ++ ++DEFINE_FUNC_FH_IS(8830, FH8830); ++DEFINE_FUNC_FH_IS(8852, FH8852); ++DEFINE_FUNC_FH_IS(8856, FH8856); ++DEFINE_FUNC_FH_IS(8626v100, FH8626V100); ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ unsigned int plat_id = 0; ++ unsigned int chip_id = 0; ++ fh_get_chipid(&plat_id, &chip_id); ++ ++ seq_printf(sfile, "chip_name\t: %s\n", fh_get_chipname()); ++ seq_printf(sfile, "ddr_size\t: %dMbit\n", fh_get_ddrsize_mbit()); ++ seq_printf(sfile, "plat_id\t\t: 0x%x\npkg_id\t\t: 0x%x\n", ++ plat_id, chip_id); ++ return 0; ++} ++ ++static const struct seq_operations chipid_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_chipid_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &chipid_seq_ops); ++} ++ ++static const struct file_operations fh_chipid_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_chipid_proc_open, ++ .read = seq_read, ++}; ++ ++#define FH_CHIPID_PROC_FILE "driver/chip" ++static struct proc_dir_entry *chipid_proc_file; ++ ++int fh_chipid_init(void) ++{ ++ chipid_proc_file = proc_create(FH_CHIPID_PROC_FILE, 0644, NULL, ++ &fh_chipid_proc_ops); ++ ++ if (!chipid_proc_file) { ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, "CHIP ID"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ +diff --git a/arch/arm/mach-fh/fh_common.c b/arch/arm/mach-fh/fh_common.c +new file mode 100644 +index 00000000..c40d706a +--- /dev/null ++++ b/arch/arm/mach-fh/fh_common.c +@@ -0,0 +1,33 @@ ++/* ++ * fh_common.c ++ * ++ * Copyright (C) 2018 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/sched.h> ++#include <mach/system.h> ++ ++/** ++ * fh_setscheduler - change the scheduling policy and/or RT priority of `current` thread. ++ * @policy: new policy. egz. SCHED_RR ++ * @priority: new priority. egz MAX_USER_RT_PRIO-12 ++ * @param: structure containing the new RT priority. ++ * ++ * NOTE that the task may be already dead. ++ */ ++void fh_setscheduler(int policy, int priority) ++{ ++ struct sched_param param; ++ param.sched_priority = priority; ++ sched_setscheduler(current, policy, ¶m); ++} ++EXPORT_SYMBOL(fh_setscheduler); +diff --git a/arch/arm/mach-fh/fh_simple_timer.c b/arch/arm/mach-fh/fh_simple_timer.c +new file mode 100644 +index 00000000..ecd7a4d6 +--- /dev/null ++++ b/arch/arm/mach-fh/fh_simple_timer.c +@@ -0,0 +1,237 @@ ++#include <linux/module.h> ++#include <mach/fh_simple_timer.h> ++ ++//#define FH_TIMER_DEBUG ++#ifdef FH_TIMER_DEBUG ++#define PRINT_DBG(fmt,args...) printk(fmt,##args) ++#else ++#define PRINT_DBG(fmt,args...) do{} while(0) ++#endif ++ ++enum SIMPLE_TIMER_WORKMODE { ++ SIMPLE_TIMER_SEQ, ++ SIMPLE_TIMER_PERIOD ++}; ++ ++struct simple_time_base ++{ ++ struct timerqueue_head simple_timer_queue; ++ int state; ++ int workmode; ++}; ++struct fh_simple_timer periodic_timer; ++ ++ ++struct simple_time_base base; ++ ++static void fh_timer_enable(void) ++{ ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x3); ++} ++ ++static void fh_timer_disable(void) ++{ ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x0); ++} ++ ++static void fh_timer_clearirq(void) ++{ ++ GET_REG(VTIMER(REG_TIMER_EOI_REG(SIMPLE_TIMER_BASE))); ++} ++ ++void fh_simple_timer_set_next(long cycles) ++{ ++ long curr_val; ++ int sync_cnt = 0; ++ ++ ++ PRINT_DBG("cycles: %lu\n", cycles); ++ ++ if (cycles < 0) { ++ pr_err("ERROR: cycles is invaild: %lu\n", cycles); ++ fh_timer_clearirq(); ++ fh_timer_disable(); ++ base.state = SIMPLE_TIMER_ERROR; ++ return; ++ } ++ ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x00, 0x1); ++ /* zy/ticket/100 : update apb Timer LOADCNT */ ++ /* CURRENTVALE could,t be start from new LOADCOUNT */ ++ /* cause is timer clk 1M hz and apb is 150M hz */ ++ /* check current cnt for it is disabled */ ++ while (GET_REG(VTIMER(REG_TIMER_CUR_VAL(1))) != 0) { ++ sync_cnt++; ++ if (sync_cnt >= 50) { ++ /* typical cnt is 5 when in 1M timer clk */ ++ /* so here use 50 to check whether it is err */ ++ pr_err("timer problem,can't disable"); ++ } ++ } ++ SET_REG(VTIMER(REG_TIMER_LOADCNT(SIMPLE_TIMER_BASE)), cycles); ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x01, 0x1); ++#ifdef CONFIG_USE_PTS_AS_CLOCKSOURCE ++#if defined(CONFIG_ARCH_FH8632) || defined(CONFIG_ARCH_FH8833) || defined(CONFIG_ARCH_FH8810) ++ curr_val = GET_REG(VTIMER(REG_TIMER_CUR_VAL(SIMPLE_TIMER_BASE))) ; ++ if (curr_val > 0x80000000) { ///0xffff0000) ++ panic("timer curr %lu, want cycles %lu\n", curr_val, cycles); ++ ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x01, 0x1); ++ SET_REG(VTIMER(REG_TIMER_LOADCNT(SIMPLE_TIMER_BASE)), cycles); ++ ++ //pmu reset ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0xfffbffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL) != 0xffffffff) { ++ ++ } ++ } ++ ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0xfffbffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL) != 0xffffffff) { ++ ++ } ++#endif ++#endif ++ ++} ++ ++int fh_simple_timer_create(struct fh_simple_timer* new) ++{ ++ timerqueue_init(&new->node); ++ new->node.expires = new->it_value; ++ timerqueue_add(&base.simple_timer_queue, &new->node); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_simple_timer_create); ++ ++int fh_timer_start(void) ++{ ++ struct fh_simple_timer *timer = NULL; ++ struct timerqueue_node *node; ++ ++ if (base.state == SIMPLE_TIMER_START) ++ return 0; ++ ++ ++ node = timerqueue_getnext(&base.simple_timer_queue); ++ ++ if(node == NULL) ++ { ++ pr_err("ERROR: timequeue is empty\n"); ++ return -1; ++ } ++ base.workmode = SIMPLE_TIMER_SEQ; ++ timer = container_of(node, struct fh_simple_timer, node); ++ ++ base.state = SIMPLE_TIMER_START; ++ fh_timer_enable(); ++ fh_simple_timer_set_next(ktime_to_us(ktime_sub(timer->it_value, timer->it_delay))); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_timer_start); ++ ++int fh_simple_timer_interrupt_seq(void) ++{ ++ ktime_t diff; ++ struct fh_simple_timer *curr = NULL, *next = NULL; ++ struct timerqueue_node *node; ++ ++ node = timerqueue_getnext(&base.simple_timer_queue); ++ ++ if(node == NULL) ++ { ++ pr_err("ERROR: timequeue is empty\n"); ++ fh_timer_clearirq(); ++ fh_timer_disable(); ++ base.state = SIMPLE_TIMER_ERROR; ++ return -1; ++ } ++ ++ curr = container_of(node, struct fh_simple_timer, node); ++ ++ timerqueue_del(&base.simple_timer_queue, &curr->node); ++ ++ curr->function(curr->param); ++ ++ node = timerqueue_getnext(&base.simple_timer_queue); ++ ++ if(node == NULL) ++ { ++ PRINT_DBG("finished all timers, close device\n"); ++ fh_timer_clearirq(); ++ fh_timer_disable(); ++ base.state = SIMPLE_TIMER_STOP; ++ return 0; ++ } ++ ++ next = container_of(node, struct fh_simple_timer, node); ++ ++ PRINT_DBG("sec: %lu, nsec: %lu\n", ++ ktime_to_timespec(next->it_value).tv_sec, ++ ktime_to_timespec(next->it_value).tv_nsec); ++ ++ diff = ktime_sub(next->it_value, curr->it_value); ++ ++ fh_simple_timer_set_next(ktime_to_us(ktime_sub(diff, next->it_delay))); ++ fh_timer_clearirq(); ++ return 0; ++} ++int fh_simple_timer_interrupt_period(void) ++{ ++ ++ periodic_timer.function(periodic_timer.param); ++ fh_timer_clearirq(); ++ return 0; ++} ++ ++int fh_simple_timer_interrupt(void) ++{ ++ if (base.workmode == SIMPLE_TIMER_SEQ) ++ return fh_simple_timer_interrupt_seq(); ++ else ++ return fh_simple_timer_interrupt_period(); ++} ++ ++ ++int fh_simple_timer_init(void) ++{ ++ base.state = SIMPLE_TIMER_STOP; ++ timerqueue_init_head(&base.simple_timer_queue); ++ memset(&periodic_timer, 0, sizeof(periodic_timer)); ++ fh_timer_disable(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_simple_timer_init); ++ ++ ++int fh_simple_timer_periodic_start(struct fh_simple_timer *tim) ++{ ++ ++ if (base.state == SIMPLE_TIMER_START) ++ return 0; ++ ++ if (tim == NULL) ++ return 0; ++ ++ periodic_timer = *tim; ++ ++ ++ ++ base.state = SIMPLE_TIMER_START; ++ base.workmode = SIMPLE_TIMER_PERIOD; ++ fh_timer_enable(); ++ fh_simple_timer_set_next(ktime_to_us(ktime_sub(periodic_timer.it_value, ++ periodic_timer.it_delay))); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_simple_timer_periodic_start); ++int fh_simple_timer_periodic_stop(void) ++{ ++ fh_timer_disable(); ++ base.state = SIMPLE_TIMER_STOP; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_simple_timer_periodic_stop); ++ +diff --git a/arch/arm/mach-fh/include/mach/board_config.fh8852.appboard b/arch/arm/mach-fh/include/mach/board_config.fh8852.appboard +new file mode 100644 +index 00000000..d63cd9b2 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/board_config.fh8852.appboard +@@ -0,0 +1,45 @@ ++/* ++ * board_config.h ++ * ++ * Created on: Jan 9, 2017 ++ * Author: duobao ++ */ ++ ++#ifndef BOARD_CONFIG_H_ ++#define BOARD_CONFIG_H_ ++ ++/* ++ * GPIO0 -> IRCUT_ON ++ * GPIO1 -> IRCUT_OFF ++ * GPIO2 -> USB_PWREN ++ * GPIO3 -> SD1_PWREN/WIFI_REG_ON ++ * GPIO7 -> IR ++ * GPIO11 -> EMAC PHY Reset ++ * GPIO12 -> CIS_CLK ++ * GPIO13 -> CIS_RSTN ++ * GPIO14 -> CIS_PDN ++ */ ++ ++#define CONFIG_GPIO_EMACPHY_RESET 11 ++#define CONFIG_GPIO_EMACPHY_RXDV 41 ++ ++#define CONFIG_GPIO_USB_PWREN 2 ++ ++#define CONFIG_ISP_CLK_RATE 150000000 ++#define CONFIG_HEVC_CLK_RATE 200000000 ++#define CONFIG_PAE_CLK_RATE 240000000 ++ ++#define FH_BOARD_8852 ++#define CONFIG_PINCTRL_SELECT \ ++ "I2C0", "MIPI", "RMII", "SD0_NO_WP", "SSI0_4BIT",\ ++ "UART0", "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO7",\ ++ "GPIO11", "GPIO13", "GPIO14",\ ++ \ ++ /* 未引出的pad,默认配置为GPIO */ \ ++ "GPIO4", "GPIO5", "GPIO6", "GPIO8", "GPIO9", "GPIO10",\ ++ "GPIO19", "GPIO20", "GPIO21", "GPIO22", "GPIO23", "GPIO24",\ ++ "GPIO25", "GPIO26", "GPIO27", "GPIO28", "GPIO53",\ ++ "GPIO55" ++ ++ ++#endif /* BOARD_CONFIG_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/board_config.fh8856.testboard b/arch/arm/mach-fh/include/mach/board_config.fh8856.testboard +new file mode 100644 +index 00000000..1cd8c86c +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/board_config.fh8856.testboard +@@ -0,0 +1,47 @@ ++/* ++ * board_config.h ++ * ++ * Created on: Jan 9, 2017 ++ * Author: duobao ++ */ ++ ++#ifndef BOARD_CONFIG_H_ ++#define BOARD_CONFIG_H_ ++ ++/* ++ * GPIO0 -> IRCUT_ON ++ * GPIO1 -> IRCUT_OFF ++ * GPIO2 -> USB_PWREN ++ * GPIO11 -> EMAC PHY Reset ++ * GPIO12 -> CIS_CLK ++ * GPIO13 -> CIS_RSTN ++ * GPIO14 -> CIS_PDN ++ * GPIO19 -> SD1_PWREN/WIFI_REG_ON ++ * GPIO20 -> AK7755 Reset ++ * GPIO24 -> LED0 ++ * GPIO25 -> LED1 ++ * GPIO26 -> Reset Configs ++ * GPIO27 -> AK7755 PowerDown ++ * GPIO28 -> IR ++ * GPIO53 -> USB_PWREN/SD0_PWREN ++ * GPIO55 -> SD1 WIFI Interrupt ++ */ ++ ++#define CONFIG_GPIO_EMACPHY_RESET 11 ++#define CONFIG_GPIO_EMACPHY_RXDV 41 ++ ++#define CONFIG_GPIO_USB_PWREN 2 ++ ++#define CONFIG_ISP_CLK_RATE 200000000 ++#define CONFIG_HEVC_CLK_RATE 300000000 ++#define CONFIG_PAE_CLK_RATE 400000000 ++ ++#define FH_BOARD_8856 ++#define CONFIG_PINCTRL_SELECT \ ++ "I2C0", "I2C1", "MIPI", "RMII", "SD0_NO_WP", \ ++ "SD1_NO_WP", "SSI0_4BIT", "UART0", "GPIO0", "GPIO1", \ ++ "GPIO2", "GPIO3", "GPIO11", "GPIO13", "GPIO14", \ ++ "GPIO19", "GPIO20", "GPIO24", "GPIO25", "GPIO26", \ ++ "GPIO27", "GPIO28", "GPIO53", "GPIO55" ++ ++#endif /* BOARD_CONFIG_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/board_config.h b/arch/arm/mach-fh/include/mach/board_config.h +new file mode 100644 +index 00000000..1cd8c86c +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/board_config.h +@@ -0,0 +1,47 @@ ++/* ++ * board_config.h ++ * ++ * Created on: Jan 9, 2017 ++ * Author: duobao ++ */ ++ ++#ifndef BOARD_CONFIG_H_ ++#define BOARD_CONFIG_H_ ++ ++/* ++ * GPIO0 -> IRCUT_ON ++ * GPIO1 -> IRCUT_OFF ++ * GPIO2 -> USB_PWREN ++ * GPIO11 -> EMAC PHY Reset ++ * GPIO12 -> CIS_CLK ++ * GPIO13 -> CIS_RSTN ++ * GPIO14 -> CIS_PDN ++ * GPIO19 -> SD1_PWREN/WIFI_REG_ON ++ * GPIO20 -> AK7755 Reset ++ * GPIO24 -> LED0 ++ * GPIO25 -> LED1 ++ * GPIO26 -> Reset Configs ++ * GPIO27 -> AK7755 PowerDown ++ * GPIO28 -> IR ++ * GPIO53 -> USB_PWREN/SD0_PWREN ++ * GPIO55 -> SD1 WIFI Interrupt ++ */ ++ ++#define CONFIG_GPIO_EMACPHY_RESET 11 ++#define CONFIG_GPIO_EMACPHY_RXDV 41 ++ ++#define CONFIG_GPIO_USB_PWREN 2 ++ ++#define CONFIG_ISP_CLK_RATE 200000000 ++#define CONFIG_HEVC_CLK_RATE 300000000 ++#define CONFIG_PAE_CLK_RATE 400000000 ++ ++#define FH_BOARD_8856 ++#define CONFIG_PINCTRL_SELECT \ ++ "I2C0", "I2C1", "MIPI", "RMII", "SD0_NO_WP", \ ++ "SD1_NO_WP", "SSI0_4BIT", "UART0", "GPIO0", "GPIO1", \ ++ "GPIO2", "GPIO3", "GPIO11", "GPIO13", "GPIO14", \ ++ "GPIO19", "GPIO20", "GPIO24", "GPIO25", "GPIO26", \ ++ "GPIO27", "GPIO28", "GPIO53", "GPIO55" ++ ++#endif /* BOARD_CONFIG_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/chip.h b/arch/arm/mach-fh/include/mach/chip.h +new file mode 100644 +index 00000000..78198934 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/chip.h +@@ -0,0 +1,20 @@ ++/***************************************************************************** ++* ++* chip.h ++* ++* Copyright (c) 2010 Shanghai Fullhan Microelectronics Co., Ltd. ++* All Rights Reserved. Confidential. ++* ++* File Description: ++* Chip definition. Include the base address of each module, memory ++* address, memory size ++* ++* Modification History: ++* ++******************************************************************************/ ++#ifndef _CHIP_H_ ++#define _CHIP_H_ ++ ++#include <mach/fh8856.h> ++ ++#endif +diff --git a/arch/arm/mach-fh/include/mach/clkdev.h b/arch/arm/mach-fh/include/mach/clkdev.h +new file mode 100644 +index 00000000..14a50488 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/clkdev.h +@@ -0,0 +1,15 @@ ++#ifndef __MACH_CLKDEV_H ++#define __MACH_CLKDEV_H ++ ++struct clk; ++ ++static inline int __clk_get(struct clk *clk) ++{ ++ return 1; ++} ++ ++static inline void __clk_put(struct clk *clk) ++{ ++} ++ ++#endif +diff --git a/arch/arm/mach-fh/include/mach/clock.h b/arch/arm/mach-fh/include/mach/clock.h +new file mode 100644 +index 00000000..018b81c4 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/clock.h +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2010 Shanghai Fullhan Microelectronics Co., Ltd. ++ * All Rights Reserved. Confidential. ++ * ++ *This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ASM_ARCH_FH_CLOCK_H ++#define __ASM_ARCH_FH_CLOCK_H ++ ++#include <linux/list.h> ++#include <linux/clkdev.h> ++ ++#define CLOCK_MAX_PARENT 4 ++ ++#define OSC_FREQUENCY (24000000) ++ ++#define CLOCK_FIXED (1<<0) ++#define CLOCK_NOGATE (1<<1) ++#define CLOCK_NODIV (1<<2) ++#define CLOCK_NORESET (1<<3) ++#define CLOCK_MULTI_PARENT (1<<4) ++#define CLOCK_PLL (1<<5) ++#define CLOCK_PLL_P (1<<6) ++#define CLOCK_PLL_R (1<<7) ++#define CLOCK_HIDE (1<<8) ++#define CLOCK_CIS (1<<9) ++ ++ ++ ++#define CLK_IOCTL_MAGIC 'c' ++#define ENABLE_CLK _IOWR(CLK_IOCTL_MAGIC, 0, unsigned int) ++#define DISABLE_CLK _IOWR(CLK_IOCTL_MAGIC, 1, unsigned int) ++#define SET_CLK_RATE _IOWR(CLK_IOCTL_MAGIC, 2, unsigned int) ++#define GET_CLK_RATE _IOWR(CLK_IOCTL_MAGIC, 3, unsigned int) ++#define SET_PMU _IOWR(CLK_IOCTL_MAGIC, 4, unsigned int) ++#define GET_PMU _IOWR(CLK_IOCTL_MAGIC, 5, unsigned int) ++ ++#define CLK_IOCTL_MAXNR 8 ++ ++ ++#define CLK(dev, con, ck) \ ++ { \ ++ .dev_id = dev, \ ++ .con_id = con, \ ++ .clk = ck, \ ++ } ++ ++struct clk_usr { ++ char *name; ++ unsigned long frequency; ++}; ++ ++ ++struct clk { ++ struct list_head list; ++ const char *name; ++ unsigned long frequency; ++ unsigned int flag; ++ int select; ++ struct clk *parent[CLOCK_MAX_PARENT]; ++ int prediv; ++ int divide; ++ unsigned int div_reg_offset; ++ unsigned int div_reg_mask; ++ unsigned int en_reg_offset; ++ unsigned int en_reg_mask; ++ unsigned int rst_reg_offset; ++ unsigned int rst_reg_mask; ++ unsigned int sel_reg_offset; ++ unsigned int sel_reg_mask; ++ unsigned int def_rate; ++}; ++ ++extern int clk_register(struct clk *clk); ++extern void clk_unregister(struct clk *clk); ++ ++void clk_set_clk_sel(unsigned int reg); ++unsigned int clk_get_clk_sel(void); ++ ++int fh_clk_init(void); ++int fh_clk_procfs_init(void); ++int fh_clk_misc_init(void); ++ ++extern struct clk_lookup fh_clks[]; ++ ++#endif +diff --git a/arch/arm/mach-fh/include/mach/ddrc.h b/arch/arm/mach-fh/include/mach/ddrc.h +new file mode 100644 +index 00000000..b6cdb5b7 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/ddrc.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2010 Shanghai Fullhan Microelectronics Co., Ltd. ++ * All Rights Reserved. Confidential. ++ * ++ *This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef DDRC_H_ ++#define DDRC_H_ ++ ++#define OFFSET_DENAL_CTL_31 (0x007c) ++#define OFFSET_DENAL_CTL_57 (0x00e4) ++#define OFFSET_DENAL_CTL_97 (0x0184) ++ ++#define DDRC_CONTROLLER_BUSY (1 << 24) ++#define DDRC_CKE_STATUS (1 << 8) ++ ++#define DDRC_LP_CMD_SELFREFRESH (10 << 8) ++#define DDRC_LP_CMD_EXITLOWPOWER (1 << 8) ++ ++#define DDRC_LPI_SR_WAKEUP_TIME (3 << 24) ++#define DDRC_CKSRX_DELAY (1 << 0) ++ ++#endif /* DDRC_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/debug-macro.S b/arch/arm/mach-fh/include/mach/debug-macro.S +new file mode 100644 +index 00000000..3f542607 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/debug-macro.S +@@ -0,0 +1,50 @@ ++/* linux/arch/arm/mach-fh/include/mach/debug-macro.S ++ * ++ * ++ * ++ * 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. ++*/ ++ ++/* pull in the relevant register and map files. */ ++ ++ /* note, for the boot process to work we have to keep the UART ++ * virtual address aligned to an 1MiB boundary for the L1 ++ * mapping the head code makes. We keep the UART virtual address ++ * aligned and add in the offset when we load the value here. ++ */ ++ ++ ++#include <linux/serial_reg.h> ++#include <mach/hardware.h> ++#include <asm/memory.h> ++#include <mach/chip.h> ++ ++#include <mach/io.h> ++ ++ .macro addruart, rp, rv ++ ldr \rp, =CONSOLE_REG_BASE ++ ldr \rv, =VA_CONSOLE_REG_BASE ++ .endm ++ ++ .macro senduart,data,addr ++ strb \data, [\addr, #(0x00)] @ Write to Transmitter Holding Register ++ .endm ++ ++ .macro waituart,data,addr ++1001: ldr \data, [\addr, #(0x14)] @ Read Status Register ++ tst \data, #(0x40) @when TX FIFO Full, then wait ++ beq 1001b ++ .endm ++ ++ .macro busyuart,data,addr ++@ stmfd r13!, {r4} ++1002: ++ ldr \data, [\addr, #(0x14)] ++ tst \data, #(0x40) ++ beq 1002b ++ .endm ++ ++ ++ +diff --git a/arch/arm/mach-fh/include/mach/entry-macro.S b/arch/arm/mach-fh/include/mach/entry-macro.S +new file mode 100644 +index 00000000..6eea8639 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/entry-macro.S +@@ -0,0 +1,31 @@ ++#include <mach/io.h> ++#include <mach/irqs.h> ++ ++ .macro disable_fiq ++ .endm ++ ++ .macro get_irqnr_preamble, base, tmp ++ ldr \base, =VA_INTC_REG_BASE ++ .endm ++ ++ .macro arch_ret_to_user, tmp1, tmp2 ++ .endm ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ @ check low interrupts ++ ldr \irqstat, [\base, #0x30] ++ mov \irqnr, #31 ++ ands \irqstat, \irqstat, #0xffffffff ++ ++ @ if no low interrupts set, check high interrupts ++ ldreq \irqstat, [\base, #0x34] ++ moveq \irqnr, #63 ++ andeqs \irqstat, \irqstat, #0xffffffff ++ ++ @ find first active interrupt source ++ clzne \irqstat, \irqstat ++ subne \irqnr, \irqnr, \irqstat ++ .endm ++ ++ .macro irq_prio_table ++ .endm +diff --git a/arch/arm/mach-fh/include/mach/fh8852_iopad.h b/arch/arm/mach-fh/include/mach/fh8852_iopad.h +new file mode 100644 +index 00000000..9642e79f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh8852_iopad.h +@@ -0,0 +1,572 @@ ++#include "pinctrl.h" ++#include "pinctrl_osdep.h" ++#include "board_config.h" ++ ++/* PINCTRL_FUNC */ ++PINCTRL_FUNC(GPIO19, 0, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 0, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO20, 1, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 1, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO21, 2, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C1_SDA, 2, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO25, 3, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_TXD, 3, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_TXD, 3, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO26, 4, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_RXD, 4, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_RXD, 4, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO27, 5, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CLK, 5, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CLK, 5, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO28, 6, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 6, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CSN, 6, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(USB_DBG_CLK, 6, FUNC3, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI0_D2, 7, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO50, 7, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SDA, 7, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 7, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_D3, 8, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO51, 8, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SCL, 8, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 8, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO22, 9, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C1_SCL, 9, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO23, 10, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(AC_MCLK, 10, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO24, 11, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(USB_PWREN, 11, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(MAC_RMII_CLK, 15, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO15, 15, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CLK, 15, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 15, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CLK, 15, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CLK, 15, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_REF_CLK, 16, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(MAC_MDC, 17, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO34, 17, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_WP, 17, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(RTC_CLK, 17, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_MCLK, 17, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(USB_PWREN, 17, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_MDIO, 18, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO17, 18, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TDO, 18, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM7, 18, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXD_0, 22, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO16, 22, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_0, 22, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 22, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 22, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_RXD, 22, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXD_1, 23, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO38, 23, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_1, 23, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 23, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 23, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 23, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXDV, 26, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO41, 26, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CD, 26, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM3, 26, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXD_0, 28, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO42, 28, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_2, 28, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM4, 28, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXD_1, 29, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO43, 29, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_3, 29, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM5, 29, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 29, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 29, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXEN, 32, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO46, 32, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM6, 32, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 32, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_TXD, 32, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TRSTN, 35, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO0, 35, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 35, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_TXD, 35, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_DO, 35, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_DO, 35, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ACIP_ADDAT, 35, FUNC6, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TMS, 36, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO1, 36, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 36, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_RXD, 36, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_DI, 36, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_DI, 36, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TCK, 37, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO2, 37, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CLK, 37, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CLK, 37, FUNC3, PUPD_DOWN, 3); ++PINCTRL_FUNC(AC_I2S_CLK, 37, FUNC4, PUPD_DOWN, 3); ++PINCTRL_FUNC(DW_I2S_CLK, 37, FUNC5, PUPD_DOWN, 3); ++PINCTRL_FUNC(ACIP_BCLK, 37, FUNC6, PUPD_DOWN, 3); ++PINCTRL_FUNC(ARM_JTAG_TDI, 38, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO3, 38, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 38, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_WS, 38, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_WS, 38, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ACIP_ADLRC, 38, FUNC6, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO4, 39, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CLK, 39, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 39, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO5, 40, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_0, 40, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 40, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO6, 41, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_1, 41, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 41, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO7, 42, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CD, 42, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM3, 42, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO8, 43, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_2, 43, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM4, 43, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO9, 44, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_3, 44, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM5, 44, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO10, 45, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CMD_RSP, 45, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM6, 45, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO11, 46, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_WP, 46, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM7, 46, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 47, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO12, 47, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(CIS_CLK, 47, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 48, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO13, 48, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 49, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(UART0_RX, 50, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO48, 50, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(UART0_TX, 51, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO49, 51, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C0_SCL, 52, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO57, 52, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C0_SDA, 53, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO56, 53, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI0_CLK, 56, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI0_TXD, 57, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_CSN_0, 58, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO54, 58, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_CSN_1, 59, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO55, 59, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_RXD, 60, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_CD, 61, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO52, 61, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TRSTN, 61, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TRSTN, 61, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_WP, 62, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO53, 62, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_CLK, 63, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO63, 63, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(ARC_JTAG_TMS, 63, FUNC2, PUPD_NONE, 3); ++PINCTRL_FUNC(PAE_JTAG_TMS, 63, FUNC3, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI1_CLK, 63, FUNC4, PUPD_NONE, 3); ++PINCTRL_FUNC(SD0_CMD_RSP, 64, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO29, 64, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TCK, 64, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TCK, 64, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 64, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_0, 65, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO62, 65, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TDI, 65, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TDI, 65, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 65, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_1, 66, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO61, 66, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(USB_PWREN, 66, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(AC_MCLK, 66, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 66, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_2, 67, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO60, 67, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SDA, 67, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 67, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TDO, 67, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_3, 68, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO18, 68, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SCL, 68, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 68, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TDO, 68, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 68, FUNC5, PUPD_UP, 3); ++ ++ ++/* PINCTRL_MUX */ ++ ++PINCTRL_MUX(ACIP_ADDAT, 0, &PAD35_ACIP_ADDAT); ++PINCTRL_MUX(ACIP_ADLRC, 0, &PAD38_ACIP_ADLRC); ++PINCTRL_MUX(ACIP_BCLK, 0, &PAD37_ACIP_BCLK); ++ ++PINCTRL_MUX(AC_I2S_CLK, 0, &PAD37_AC_I2S_CLK); ++PINCTRL_MUX(AC_I2S_DI, 0, &PAD36_AC_I2S_DI); ++PINCTRL_MUX(AC_I2S_DO, 0, &PAD35_AC_I2S_DO); ++PINCTRL_MUX(AC_I2S_WS, 0, &PAD38_AC_I2S_WS); ++PINCTRL_MUX(AC_MCLK, 2, &PAD10_AC_MCLK, &PAD17_AC_MCLK, &PAD66_AC_MCLK); ++ ++PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD64_ARC_JTAG_TCK); ++PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD65_ARC_JTAG_TDI); ++PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD67_ARC_JTAG_TDO); ++PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD63_ARC_JTAG_TMS); ++PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD61_ARC_JTAG_TRSTN); ++ ++PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD37_ARM_JTAG_TCK); ++PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD38_ARM_JTAG_TDI); ++PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD18_ARM_JTAG_TDO); ++PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD36_ARM_JTAG_TMS); ++PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD35_ARM_JTAG_TRSTN); ++ ++PINCTRL_MUX(CIS_CLK, 0, &PAD47_CIS_CLK); ++ ++PINCTRL_MUX(DW_I2S_CLK, 0, &PAD37_DW_I2S_CLK); ++PINCTRL_MUX(DW_I2S_DI, 0, &PAD36_DW_I2S_DI); ++PINCTRL_MUX(DW_I2S_DO, 0, &PAD35_DW_I2S_DO); ++PINCTRL_MUX(DW_I2S_WS, 0, &PAD38_DW_I2S_WS); ++ ++PINCTRL_MUX(I2C0_SCL, 0, &PAD52_I2C0_SCL); ++PINCTRL_MUX(I2C0_SDA, 0, &PAD53_I2C0_SDA); ++ ++PINCTRL_MUX(I2C1_SCL, 2, &PAD8_I2C1_SCL, &PAD9_I2C1_SCL, &PAD68_I2C1_SCL); ++PINCTRL_MUX(I2C1_SDA, 2, &PAD2_I2C1_SDA, &PAD7_I2C1_SDA, &PAD67_I2C1_SDA); ++ ++PINCTRL_MUX(MAC_MDC, 0, &PAD17_MAC_MDC); ++PINCTRL_MUX(MAC_MDIO, 0, &PAD18_MAC_MDIO); ++PINCTRL_MUX(MAC_REF_CLK, 0, &PAD16_MAC_REF_CLK); ++PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD15_MAC_RMII_CLK); ++PINCTRL_MUX(MAC_RXDV, 0, &PAD26_MAC_RXDV); ++PINCTRL_MUX(MAC_RXD_0, 0, &PAD22_MAC_RXD_0); ++PINCTRL_MUX(MAC_RXD_1, 0, &PAD23_MAC_RXD_1); ++PINCTRL_MUX(MAC_TXD_0, 0, &PAD28_MAC_TXD_0); ++PINCTRL_MUX(MAC_TXD_1, 0, &PAD29_MAC_TXD_1); ++PINCTRL_MUX(MAC_TXEN, 0, &PAD32_MAC_TXEN); ++ ++PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD64_PAE_JTAG_TCK); ++PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD65_PAE_JTAG_TDI); ++PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD68_PAE_JTAG_TDO); ++PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD63_PAE_JTAG_TMS); ++PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD61_PAE_JTAG_TRSTN); ++ ++PINCTRL_MUX(PWM0, 0, &PAD15_PWM0, &PAD39_PWM0, &PAD47_PWM0); ++PINCTRL_MUX(PWM1, 0, &PAD22_PWM1, &PAD40_PWM1, &PAD48_PWM1); ++PINCTRL_MUX(PWM2, 0, &PAD23_PWM2, &PAD41_PWM2, &PAD49_PWM2); ++PINCTRL_MUX(PWM3, 0, &PAD26_PWM3, &PAD42_PWM3); ++PINCTRL_MUX(PWM4, 0, &PAD28_PWM4, &PAD43_PWM4); ++PINCTRL_MUX(PWM5, 0, &PAD29_PWM5, &PAD44_PWM5); ++PINCTRL_MUX(PWM6, 0, &PAD32_PWM6, &PAD45_PWM6); ++PINCTRL_MUX(PWM7, 0, &PAD18_PWM7, &PAD46_PWM7); ++ ++PINCTRL_MUX(RTC_CLK, 0, &PAD17_RTC_CLK); ++ ++PINCTRL_MUX(SD0_CD, 0, &PAD61_SD0_CD); ++PINCTRL_MUX(SD0_CLK, 0, &PAD63_SD0_CLK); ++PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD64_SD0_CMD_RSP); ++PINCTRL_MUX(SD0_DATA_0, 0, &PAD65_SD0_DATA_0); ++PINCTRL_MUX(SD0_DATA_1, 0, &PAD66_SD0_DATA_1); ++PINCTRL_MUX(SD0_DATA_2, 0, &PAD67_SD0_DATA_2); ++PINCTRL_MUX(SD0_DATA_3, 0, &PAD68_SD0_DATA_3); ++PINCTRL_MUX(SD0_WP, 0, &PAD62_SD0_WP); ++ ++PINCTRL_MUX(SD1_CD, 0, &PAD26_SD1_CD, &PAD42_SD1_CD); ++PINCTRL_MUX(SD1_CLK, 0, &PAD15_SD1_CLK, &PAD39_SD1_CLK); ++PINCTRL_MUX(SD1_CMD_RSP, 0, &PAD32_SD1_CMD_RSP, &PAD45_SD1_CMD_RSP); ++PINCTRL_MUX(SD1_DATA_0, 0, &PAD22_SD1_DATA_0, &PAD40_SD1_DATA_0); ++PINCTRL_MUX(SD1_DATA_1, 0, &PAD23_SD1_DATA_1, &PAD41_SD1_DATA_1); ++PINCTRL_MUX(SD1_DATA_2, 0, &PAD28_SD1_DATA_2, &PAD43_SD1_DATA_2); ++PINCTRL_MUX(SD1_DATA_3, 0, &PAD29_SD1_DATA_3, &PAD44_SD1_DATA_3); ++PINCTRL_MUX(SD1_WP, 0, &PAD17_SD1_WP, &PAD46_SD1_WP); ++ ++PINCTRL_MUX(SSI0_CLK, 0, &PAD56_SSI0_CLK); ++PINCTRL_MUX(SSI0_CSN_0, 0, &PAD58_SSI0_CSN_0); ++PINCTRL_MUX(SSI0_CSN_1, 0, &PAD59_SSI0_CSN_1); ++PINCTRL_MUX(SSI0_D2, 0, &PAD7_SSI0_D2); ++PINCTRL_MUX(SSI0_D3, 0, &PAD8_SSI0_D3); ++PINCTRL_MUX(SSI0_RXD, 0, &PAD60_SSI0_RXD); ++PINCTRL_MUX(SSI0_TXD, 0, &PAD57_SSI0_TXD); ++ ++PINCTRL_MUX(SSI1_CLK, 2, &PAD5_SSI1_CLK, &PAD15_SSI1_CLK, &PAD37_SSI1_CLK, ++ &PAD63_SSI1_CLK); ++PINCTRL_MUX(SSI1_CSN_0, 3, &PAD6_SSI1_CSN_0, &PAD23_SSI1_CSN_0, ++ &PAD29_SSI1_CSN_0, &PAD38_SSI1_CSN_0, &PAD66_SSI1_CSN_0, ++ &PAD68_SSI1_CSN_0); ++PINCTRL_MUX(SSI1_RXD, 2, &PAD4_SSI1_RXD, &PAD22_SSI1_RXD, &PAD36_SSI1_RXD, ++ &PAD65_SSI1_RXD); ++PINCTRL_MUX(SSI1_TXD, 2, &PAD3_SSI1_TXD, &PAD32_SSI1_TXD, &PAD35_SSI1_TXD, ++ &PAD64_SSI1_TXD); ++ ++PINCTRL_MUX(SSI2_CLK, 2, &PAD5_SSI2_CLK, &PAD15_SSI2_CLK, &PAD37_SSI2_CLK); ++PINCTRL_MUX(SSI2_CSN, 3, &PAD6_SSI2_CSN, &PAD23_SSI2_CSN, &PAD29_SSI2_CSN, ++ &PAD38_SSI2_CSN); ++PINCTRL_MUX(SSI2_RXD, 2, &PAD4_SSI2_RXD, &PAD22_SSI2_RXD, &PAD36_SSI2_RXD); ++PINCTRL_MUX(SSI2_TXD, 2, &PAD3_SSI2_TXD, &PAD32_SSI2_TXD, &PAD35_SSI2_TXD); ++ ++PINCTRL_MUX(UART0_RX, 0, &PAD50_UART0_RX); ++PINCTRL_MUX(UART0_TX, 0, &PAD51_UART0_TX); ++ ++PINCTRL_MUX(UART1_RX, 1, &PAD1_UART1_RX, &PAD8_UART1_RX, &PAD68_UART1_RX); ++PINCTRL_MUX(UART1_TX, 1, &PAD0_UART1_TX, &PAD7_UART1_TX, &PAD67_UART1_TX); ++ ++PINCTRL_MUX(USB_DBG_CLK, 0, &PAD6_USB_DBG_CLK); ++PINCTRL_MUX(USB_PWREN, 1, &PAD11_USB_PWREN, &PAD17_USB_PWREN, &PAD66_USB_PWREN); ++ ++PINCTRL_MUX(GPIO0, 0, &PAD35_GPIO0); ++PINCTRL_MUX(GPIO1, 0, &PAD36_GPIO1); ++PINCTRL_MUX(GPIO2, 0, &PAD37_GPIO2); ++PINCTRL_MUX(GPIO3, 0, &PAD38_GPIO3); ++PINCTRL_MUX(GPIO4, 0, &PAD39_GPIO4); ++PINCTRL_MUX(GPIO5, 0, &PAD40_GPIO5); ++PINCTRL_MUX(GPIO6, 0, &PAD41_GPIO6); ++PINCTRL_MUX(GPIO7, 0, &PAD42_GPIO7); ++PINCTRL_MUX(GPIO8, 0, &PAD43_GPIO8); ++PINCTRL_MUX(GPIO9, 0, &PAD44_GPIO9); ++PINCTRL_MUX(GPIO10, 0, &PAD45_GPIO10); ++PINCTRL_MUX(GPIO11, 0, &PAD46_GPIO11); ++PINCTRL_MUX(GPIO12, 0, &PAD47_GPIO12); ++PINCTRL_MUX(GPIO13, 0, &PAD48_GPIO13); ++PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14); ++PINCTRL_MUX(GPIO15, 0, &PAD15_GPIO15); ++PINCTRL_MUX(GPIO16, 0, &PAD22_GPIO16); ++PINCTRL_MUX(GPIO17, 0, &PAD18_GPIO17); ++PINCTRL_MUX(GPIO18, 0, &PAD68_GPIO18); ++PINCTRL_MUX(GPIO19, 0, &PAD0_GPIO19); ++PINCTRL_MUX(GPIO20, 0, &PAD1_GPIO20); ++PINCTRL_MUX(GPIO21, 0, &PAD2_GPIO21); ++PINCTRL_MUX(GPIO22, 0, &PAD9_GPIO22); ++PINCTRL_MUX(GPIO23, 0, &PAD10_GPIO23); ++PINCTRL_MUX(GPIO24, 0, &PAD11_GPIO24); ++PINCTRL_MUX(GPIO25, 0, &PAD3_GPIO25); ++PINCTRL_MUX(GPIO26, 0, &PAD4_GPIO26); ++PINCTRL_MUX(GPIO27, 0, &PAD5_GPIO27); ++PINCTRL_MUX(GPIO28, 0, &PAD6_GPIO28); ++PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29); ++PINCTRL_MUX(GPIO34, 0, &PAD17_GPIO34); ++PINCTRL_MUX(GPIO38, 0, &PAD23_GPIO38); ++PINCTRL_MUX(GPIO41, 0, &PAD26_GPIO41); ++PINCTRL_MUX(GPIO42, 0, &PAD28_GPIO42); ++PINCTRL_MUX(GPIO43, 0, &PAD29_GPIO43); ++PINCTRL_MUX(GPIO46, 0, &PAD32_GPIO46); ++PINCTRL_MUX(GPIO48, 0, &PAD50_GPIO48); ++PINCTRL_MUX(GPIO49, 0, &PAD51_GPIO49); ++PINCTRL_MUX(GPIO50, 0, &PAD7_GPIO50); ++PINCTRL_MUX(GPIO51, 0, &PAD8_GPIO51); ++PINCTRL_MUX(GPIO52, 0, &PAD61_GPIO52); ++PINCTRL_MUX(GPIO53, 0, &PAD62_GPIO53); ++PINCTRL_MUX(GPIO54, 0, &PAD58_GPIO54); ++PINCTRL_MUX(GPIO55, 0, &PAD59_GPIO55); ++PINCTRL_MUX(GPIO56, 0, &PAD53_GPIO56); ++PINCTRL_MUX(GPIO57, 0, &PAD52_GPIO57); ++PINCTRL_MUX(GPIO60, 0, &PAD67_GPIO60); ++PINCTRL_MUX(GPIO61, 0, &PAD66_GPIO61); ++PINCTRL_MUX(GPIO62, 0, &PAD65_GPIO62); ++PINCTRL_MUX(GPIO63, 0, &PAD63_GPIO63); ++ ++PINCTRL_MUX(SD1_CLK_RMII, 0, &PAD15_SD1_CLK, &PAD39_SD1_CLK); ++PINCTRL_MUX(SD1_CD_RMII, 0, &PAD26_SD1_CD, &PAD42_SD1_CD); ++PINCTRL_MUX(SD1_CMD_RSP_RMII, 0, &PAD32_SD1_CMD_RSP, &PAD45_SD1_CMD_RSP); ++PINCTRL_MUX(SD1_WP_RMII, 0, &PAD17_SD1_WP, &PAD46_SD1_WP); ++PINCTRL_MUX(SD1_DATA_0_RMII, 0, &PAD22_SD1_DATA_0, &PAD40_SD1_DATA_0); ++PINCTRL_MUX(SD1_DATA_1_RMII, 0, &PAD23_SD1_DATA_1, &PAD41_SD1_DATA_1); ++PINCTRL_MUX(SD1_DATA_2_RMII, 0, &PAD28_SD1_DATA_2, &PAD43_SD1_DATA_2); ++PINCTRL_MUX(SD1_DATA_3_RMII, 0, &PAD29_SD1_DATA_3, &PAD44_SD1_DATA_3); ++ ++/* PINCTRL_DEVICE */ ++PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO, ++ &MUX_AC_I2S_WS, &MUX_AC_MCLK); ++PINCTRL_DEVICE(ACIP, 3, &MUX_ACIP_ADDAT, &MUX_ACIP_ADLRC, &MUX_ACIP_BCLK); ++PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI, ++ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN); ++PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI, ++ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN); ++PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO, ++ &MUX_DW_I2S_WS); ++PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA); ++PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA); ++PINCTRL_DEVICE(MIPI, 1, &MUX_CIS_CLK); ++PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI, ++ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN); ++PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0); ++PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1); ++PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2); ++PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3); ++PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4); ++PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5); ++PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6); ++PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7); ++PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK, ++ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1, ++ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN); ++PINCTRL_DEVICE(SD0, 8, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3, ++ &MUX_SD0_WP); ++PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0); ++PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3); ++PINCTRL_DEVICE(SD1, 8, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, ++ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3, ++ &MUX_SD1_WP); ++PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, ++ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3); ++PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO54, &MUX_SSI0_CLK, &MUX_SSI0_RXD, ++ &MUX_SSI0_TXD); ++PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO54, &MUX_SSI0_CLK, &MUX_SSI0_D2, ++ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD); ++PINCTRL_DEVICE(SSI1, 4, &MUX_SSI1_CLK, &MUX_SSI1_CSN_0, &MUX_SSI1_RXD, ++ &MUX_SSI1_TXD); ++PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN, &MUX_SSI2_RXD, ++ &MUX_SSI2_TXD); ++PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX); ++PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX); ++PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN); ++PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0); ++PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1); ++PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2); ++PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3); ++PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4); ++PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5); ++PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6); ++PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7); ++PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8); ++PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9); ++PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10); ++PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11); ++PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12); ++PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13); ++PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14); ++PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15); ++PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16); ++PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17); ++PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18); ++PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19); ++PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20); ++PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21); ++PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22); ++PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23); ++PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24); ++PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25); ++PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26); ++PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27); ++PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28); ++PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29); ++PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34); ++PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38); ++PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41); ++PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42); ++PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43); ++PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46); ++PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48); ++PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49); ++PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50); ++PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51); ++PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52); ++PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53); ++PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54); ++PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55); ++PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56); ++PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57); ++PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60); ++PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61); ++PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62); ++PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63); ++ ++PINCTRL_DEVICE(SD1_WIFI_RMII, 7, &MUX_SD1_CLK_RMII, &MUX_SD1_CD_RMII, ++ &MUX_SD1_CMD_RSP_RMII, &MUX_SD1_DATA_0_RMII, &MUX_SD1_DATA_1_RMII, ++ &MUX_SD1_DATA_2_RMII, &MUX_SD1_DATA_3_RMII); ++ ++void fh_pinctrl_init_devicelist(OS_LIST *list) ++{ ++ OS_LIST_EMPTY(list); ++ ++ /*PINCTRL_ADD_DEVICE*/ ++ PINCTRL_ADD_DEVICE(ACI2S); ++ PINCTRL_ADD_DEVICE(ACIP); ++ PINCTRL_ADD_DEVICE(ARCJTAG); ++ PINCTRL_ADD_DEVICE(ARMJTAG); ++ PINCTRL_ADD_DEVICE(DWI2S); ++ PINCTRL_ADD_DEVICE(I2C0); ++ PINCTRL_ADD_DEVICE(I2C1); ++ PINCTRL_ADD_DEVICE(MIPI); ++ PINCTRL_ADD_DEVICE(PAEJTAG); ++ PINCTRL_ADD_DEVICE(PWM0); ++ PINCTRL_ADD_DEVICE(PWM1); ++ PINCTRL_ADD_DEVICE(PWM2); ++ PINCTRL_ADD_DEVICE(PWM3); ++ PINCTRL_ADD_DEVICE(PWM4); ++ PINCTRL_ADD_DEVICE(PWM5); ++ PINCTRL_ADD_DEVICE(PWM6); ++ PINCTRL_ADD_DEVICE(PWM7); ++ PINCTRL_ADD_DEVICE(RMII); ++ PINCTRL_ADD_DEVICE(SD0); ++ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP); ++ PINCTRL_ADD_DEVICE(SD0_NO_WP); ++ PINCTRL_ADD_DEVICE(SD1); ++ PINCTRL_ADD_DEVICE(SD1_NO_WP); ++ PINCTRL_ADD_DEVICE(SSI0); ++ PINCTRL_ADD_DEVICE(SSI0_4BIT); ++ PINCTRL_ADD_DEVICE(SSI1); ++ PINCTRL_ADD_DEVICE(SSI2); ++ PINCTRL_ADD_DEVICE(UART0); ++ PINCTRL_ADD_DEVICE(UART1); ++ PINCTRL_ADD_DEVICE(USB); ++ PINCTRL_ADD_DEVICE(GPIO0); ++ PINCTRL_ADD_DEVICE(GPIO1); ++ PINCTRL_ADD_DEVICE(GPIO2); ++ PINCTRL_ADD_DEVICE(GPIO3); ++ PINCTRL_ADD_DEVICE(GPIO4); ++ PINCTRL_ADD_DEVICE(GPIO5); ++ PINCTRL_ADD_DEVICE(GPIO6); ++ PINCTRL_ADD_DEVICE(GPIO7); ++ PINCTRL_ADD_DEVICE(GPIO8); ++ PINCTRL_ADD_DEVICE(GPIO9); ++ PINCTRL_ADD_DEVICE(GPIO10); ++ PINCTRL_ADD_DEVICE(GPIO11); ++ PINCTRL_ADD_DEVICE(GPIO12); ++ PINCTRL_ADD_DEVICE(GPIO13); ++ PINCTRL_ADD_DEVICE(GPIO14); ++ PINCTRL_ADD_DEVICE(GPIO15); ++ PINCTRL_ADD_DEVICE(GPIO16); ++ PINCTRL_ADD_DEVICE(GPIO17); ++ PINCTRL_ADD_DEVICE(GPIO18); ++ PINCTRL_ADD_DEVICE(GPIO19); ++ PINCTRL_ADD_DEVICE(GPIO20); ++ PINCTRL_ADD_DEVICE(GPIO21); ++ PINCTRL_ADD_DEVICE(GPIO22); ++ PINCTRL_ADD_DEVICE(GPIO23); ++ PINCTRL_ADD_DEVICE(GPIO24); ++ PINCTRL_ADD_DEVICE(GPIO25); ++ PINCTRL_ADD_DEVICE(GPIO26); ++ PINCTRL_ADD_DEVICE(GPIO27); ++ PINCTRL_ADD_DEVICE(GPIO28); ++ PINCTRL_ADD_DEVICE(GPIO29); ++ PINCTRL_ADD_DEVICE(GPIO34); ++ PINCTRL_ADD_DEVICE(GPIO38); ++ PINCTRL_ADD_DEVICE(GPIO41); ++ PINCTRL_ADD_DEVICE(GPIO42); ++ PINCTRL_ADD_DEVICE(GPIO43); ++ PINCTRL_ADD_DEVICE(GPIO46); ++ PINCTRL_ADD_DEVICE(GPIO48); ++ PINCTRL_ADD_DEVICE(GPIO49); ++ PINCTRL_ADD_DEVICE(GPIO50); ++ PINCTRL_ADD_DEVICE(GPIO51); ++ PINCTRL_ADD_DEVICE(GPIO52); ++ PINCTRL_ADD_DEVICE(GPIO53); ++ PINCTRL_ADD_DEVICE(GPIO54); ++ PINCTRL_ADD_DEVICE(GPIO55); ++ PINCTRL_ADD_DEVICE(GPIO56); ++ PINCTRL_ADD_DEVICE(GPIO57); ++ PINCTRL_ADD_DEVICE(GPIO60); ++ PINCTRL_ADD_DEVICE(GPIO61); ++ PINCTRL_ADD_DEVICE(GPIO62); ++ PINCTRL_ADD_DEVICE(GPIO63); ++ ++ PINCTRL_ADD_DEVICE(SD1_WIFI_RMII); ++} ++ ++char* fh_pinctrl_selected_devices[] = ++{ ++ CONFIG_PINCTRL_SELECT ++}; +diff --git a/arch/arm/mach-fh/include/mach/fh8856.h b/arch/arm/mach-fh/include/mach/fh8856.h +new file mode 100644 +index 00000000..27ddf27f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh8856.h +@@ -0,0 +1,331 @@ ++/* ++ * ++ * Copyright (C) 2015 Fullhan.com ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ASM_ARCH_FH8856_H ++#define __ASM_ARCH_FH8856_H ++ ++#include <linux/init.h> ++ ++#define SRAM_GRANULARITY 32 ++#define SRAM_SIZE SZ_32K ++ ++#define SIMPLE_TIMER_BASE 2 ++ ++#define RAM_BASE (0x10000000) ++#define DDR_BASE (0xA0000000) ++ ++#define PMU_REG_BASE (0xF0000000) ++#define TIMER_REG_BASE (0xF0C00000) ++#define GPIO0_REG_BASE (0xF0300000) ++#define GPIO1_REG_BASE (0xF4000000) ++#define UART0_REG_BASE (0xF0700000) ++#define UART1_REG_BASE (0xF0800000) ++#define SPI0_REG_BASE (0xF0500000) ++#define SPI1_REG_BASE (0xF0600000) ++#define SPI2_REG_BASE (0xF0640000) ++#define INTC_REG_BASE (0xE0200000) ++#define GMAC_REG_BASE (0xE0600000) ++#define USBC_REG_BASE (0xE0700000) ++#define DMAC_REG_BASE (0xE0300000) ++#define I2C1_REG_BASE (0xF0B00000) ++#define I2C0_REG_BASE (0xF0200000) ++#define SDC0_REG_BASE (0xE2000000) ++#define SDC1_REG_BASE (0xE2200000) ++#define WDT_REG_BASE (0xF0D00000) ++#define PWM_REG_BASE (0xF0400000) ++#define I2S_REG_BASE (0xF0900000) ++#define ACW_REG_BASE (0xF0A00000) ++#define SADC_REG_BASE (0xF1200000) ++#define EFUSE_REG_BASE (0xF1600000) ++#define AES_REG_BASE (0xE8200000) ++#define RTC_REG_BASE (0xF1500000) ++#define DDRC_REG_BASE (0xED000000) ++#define CONSOLE_REG_BASE UART0_REG_BASE ++#define FH_UART_NUMBER 2 ++ ++#define PMU_REG_SIZE 0x2018 ++#define PMU_DEBUG ++ ++#define REG_PMU_CHIP_ID (0x0000) ++#define REG_PMU_IP_VER (0x0004) ++#define REG_PMU_FW_VER (0x0008) ++#define REG_PMU_SYS_CTRL (0x000c) ++#define REG_PMU_PLL0 (0x0010) ++#define REG_PMU_PLL1 (0x0014) ++#define REG_PMU_PLL_CTRL (0x0018) ++#define REG_PMU_CLK_GATE (0x001c) ++#define REG_PMU_CLK_SEL (0x0020) ++#define REG_PMU_CLK_DIV0 (0x0024) ++#define REG_PMU_CLK_DIV1 (0x0028) ++#define REG_PMU_CLK_DIV2 (0x002c) ++#define REG_PMU_CLK_DIV3 (0x0030) ++#define REG_PMU_CLK_DIV4 (0x0034) ++#define REG_PMU_CLK_DIV5 (0x0038) ++#define REG_PMU_CLK_DIV6 (0x003c) ++#define REG_PMU_SWRST_MAIN_CTRL (0x0040) ++#define REG_PMU_SWRST_AXI_CTRL (0x0044) ++#define REG_PMU_SWRST_AHB_CTRL (0x0048) ++#define REG_PMU_SWRST_APB_CTRL (0x004c) ++#define REG_PMU_SPC_IO_STATUS (0x0054) ++#define REG_PMU_SPC_FUN (0x0058) ++#define REG_PMU_DBG_SPOT0 (0x005c) ++#define REG_PMU_DBG_SPOT1 (0x0060) ++#define REG_PMU_DBG_SPOT2 (0x0064) ++#define REG_PMU_DBG_SPOT3 (0x0068) ++#define REG_PMU_CLK_DIV7 (0x006c) ++#define REG_PMU_CLK_DIV8 (0x0070) ++#define REG_PAD_PWR_SEL (0x0074) ++#define REG_PMU_PLL2 (0x0078) ++#define REG_PMU_PLL2_CTRL (0x007c) ++ ++#define REG_PMU_PAD_CIS_HSYNC_CFG (0x0080) ++#define REG_PMU_PAD_CIS_VSYNC_CFG (0x0084) ++#define REG_PMU_PAD_CIS_PCLK_CFG (0x0088) ++#define REG_PMU_PAD_CIS_D_0_CFG (0x008c) ++#define REG_PMU_PAD_CIS_D_1_CFG (0x0090) ++#define REG_PMU_PAD_CIS_D_2_CFG (0x0094) ++#define REG_PMU_PAD_CIS_D_3_CFG (0x0098) ++#define REG_PMU_PAD_CIS_D_4_CFG (0x009c) ++#define REG_PMU_PAD_CIS_D_5_CFG (0x00a0) ++#define REG_PMU_PAD_CIS_D_6_CFG (0x00a4) ++#define REG_PMU_PAD_CIS_D_7_CFG (0x00a8) ++#define REG_PMU_PAD_CIS_D_8_CFG (0x00ac) ++#define REG_PMU_PAD_CIS_D_9_CFG (0x00b0) ++#define REG_PMU_PAD_CIS_D_10_CFG (0x00b4) ++#define REG_PMU_PAD_CIS_D_11_CFG (0x00b8) ++#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00bc) ++#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00c0) ++#define REG_PMU_PAD_MAC_MDC_CFG (0x00c4) ++#define REG_PMU_PAD_MAC_MDIO_CFG (0x00c8) ++#define REG_PMU_PAD_MAC_COL_MII_CFG (0x00cc) ++#define REG_PMU_PAD_MAC_CRS_MII_CFG (0x00d0) ++#define REG_PMU_PAD_MAC_RXCK_CFG (0x00d4) ++#define REG_PMU_PAD_MAC_RXD0_CFG (0x00d8) ++#define REG_PMU_PAD_MAC_RXD1_CFG (0x00dc) ++#define REG_PMU_PAD_MAC_RXD2_MII_CFG (0x00e0) ++#define REG_PMU_PAD_MAC_RXD3_MII_CFG (0x00e4) ++#define REG_PMU_PAD_MAC_RXDV_CFG (0x00e8) ++#define REG_PMU_PAD_MAC_TXCK_CFG (0x00ec) ++#define REG_PMU_PAD_MAC_TXD0_CFG (0x00f0) ++#define REG_PMU_PAD_MAC_TXD1_CFG (0x00f4) ++#define REG_PMU_PAD_MAC_TXD2_MII_CFG (0x00f8) ++#define REG_PMU_PAD_MAC_TXD3_MII_CFG (0x00fc) ++#define REG_PMU_PAD_MAC_TXEN_CFG (0x0100) ++#define REG_PMU_PAD_MAC_RXER_MII_CFG (0x0104) ++#define REG_PMU_PAD_MAC_TXER_MII_CFG (0x0108) ++#define REG_PMU_PAD_GPIO_0_CFG (0x010c) ++#define REG_PMU_PAD_GPIO_1_CFG (0x0110) ++#define REG_PMU_PAD_GPIO_2_CFG (0x0114) ++#define REG_PMU_PAD_GPIO_3_CFG (0x0118) ++#define REG_PMU_PAD_GPIO_4_CFG (0x011c) ++#define REG_PMU_PAD_GPIO_5_CFG (0x0120) ++#define REG_PMU_PAD_GPIO_6_CFG (0x0124) ++#define REG_PMU_PAD_GPIO_7_CFG (0x0128) ++#define REG_PMU_PAD_GPIO_8_CFG (0x012c) ++#define REG_PMU_PAD_GPIO_9_CFG (0x0130) ++#define REG_PMU_PAD_GPIO_10_CFG (0x0134) ++#define REG_PMU_PAD_GPIO_11_CFG (0x0138) ++#define REG_PMU_PAD_GPIO_12_CFG (0x013c) ++#define REG_PMU_PAD_GPIO_13_CFG (0x0140) ++#define REG_PMU_PAD_GPIO_14_CFG (0x0144) ++#define REG_PMU_PAD_UART_RX_CFG (0x0148) ++#define REG_PMU_PAD_UART_TX_CFG (0x014c) ++#define REG_PMU_PAD_CIS_SCL_CFG (0x0150) ++#define REG_PMU_PAD_CIS_SDA_CFG (0x0154) ++#define REG_PMU_PAD_I2C_SCL_CFG (0x0158) ++#define REG_PMU_PAD_I2C_SDA_CFG (0x015c) ++#define REG_PMU_PAD_SSI0_CLK_CFG (0x0160) ++#define REG_PMU_PAD_SSI0_TXD_CFG (0x0164) ++#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x0168) ++#define REG_PMU_PAD_SSI0_CSN_1_CFG (0x016c) ++#define REG_PMU_PAD_SSI0_RXD_CFG (0x0170) ++#define REG_PMU_PAD_SD0_CD_CFG (0x0174) ++#define REG_PMU_PAD_SD0_WP_CFG (0x0178) ++#define REG_PMU_PAD_SD0_CLK_CFG (0x017c) ++#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0180) ++#define REG_PMU_PAD_SD0_DATA_0_CFG (0x0184) ++#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0188) ++#define REG_PMU_PAD_SD0_DATA_2_CFG (0x018c) ++#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0190) ++#define REG_PMU_PAD_SD1_CD_CFG (0x0194) ++#define REG_PMU_PAD_SD1_WP_CFG (0x0198) ++#define REG_PMU_PAD_SD1_CLK_CFG (0x019c) ++#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x01a0) ++#define REG_PMU_PAD_SD1_DATA_0_CFG (0x01a4) ++#define REG_PMU_PAD_SD1_DATA_1_CFG (0x01a8) ++#define REG_PMU_PAD_SD1_DATA_2_CFG (0x01ac) ++#define REG_PMU_PAD_SD1_DATA_3_CFG (0x01b0) ++#define REG_PMU_AXI0_PRIO_CFG0 (0x01b4) ++#define REG_PMU_AXI0_PRIO_CFG1 (0x01b8) ++#define REG_PMU_AXI1_PRIO_CFG0 (0x01bc) ++#define REG_PMU_AXI1_PRIO_CFG1 (0x01c0) ++#define REG_PMU_SWRSTN_NSR (0x01c4) ++#define REG_PMU_ARM_INT_0 (0x01e0) ++#define REG_PMU_ARM_INT_1 (0x01e4) ++#define REG_PMU_ARM_INT_2 (0x01e8) ++#define REG_PMU_A625_INT_0 (0x01ec) ++#define REG_PMU_A625_INT_1 (0x01f0) ++#define REG_PMU_A625_INT_2 (0x01f4) ++#define REG_PMU_DMA (0x01f8) ++#define REG_PMU_WDT_CTRL (0x01fc) ++#define REG_PMU_DBG_STAT0 (0x0200) ++#define REG_PMU_DBG_STAT1 (0x0204) ++#define REG_PMU_DBG_STAT2 (0x0208) ++#define REG_PMU_DBG_STAT3 (0x020c) ++#define REG_PMU_USB_SYS (0x0210) ++#define REG_PMU_USB_CFG (0x0214) ++#define REG_PMU_USB_TUNE (0x0218) ++#define REG_PMU_PAD_CIS_CLK_CFG (0x021c) ++#define REG_PMU_USB_SYS1 (0x0228) ++#define REG_PMU_PTSLO (0x022c) ++#define REG_PMU_PTSHI (0x0230) ++#define REG_PMU_USER0 (0x0234) ++#define REG_PMU_PRDCID_CTRL0 (0x500) ++#define REG_PMU_PAEARCBOOT0 (0x1000) ++#define REG_PMU_PAEARCBOOT1 (0x1004) ++#define REG_PMU_PAEARCBOOT2 (0x1008) ++#define REG_PMU_PAEARCBOOT3 (0x100c) ++#define REG_PMU_PAE_ARC_START_CTRL (0x1010) ++#define REG_PMU_A625BOOT0 (0x2000) ++#define REG_PMU_A625BOOT1 (0x2004) ++#define REG_PMU_A625BOOT2 (0x2008) ++#define REG_PMU_A625BOOT3 (0x200c) ++#define REG_PMU_A625_START_CTRL (0x2010) ++#define REG_PMU_ARC_INTC_MASK (0x2014) ++#define REG_PMU_PAE_ARC_INTC_MASK (0x2018) ++ ++/*ATTENTION: written by ARC */ ++#define PMU_ARM_INT_MASK (0x01ec) ++#define PMU_ARM_INT_RAWSTAT (0x01f0) ++#define PMU_ARM_INT_STAT (0x01f4) ++ ++#define PMU_A625_INT_MASK (0x01e0) ++#define PMU_A625_INT_RAWSTAT (0x01e4) ++#define PMU_A625_INT_STAT (0x01e8) ++ ++#define PMU_IRQ 0 ++#define DDRC_IRQ 1 ++#define WDT_IRQ 2 ++#define TMR0_IRQ 3 ++#define PAE_ARC_IRQ0 4 ++#define PAE_ARC_IRQ1 5 ++#define PAE_ARC_IRQ2 6 ++#define VPU_IRQ 7 ++#define PAE_IRQ 8 ++#define ISPP_IRQ 9 ++#define ISPF_IRQ 10 ++#define I2C0_IRQ 11 ++#define I2C1_IRQ 12 ++#define JPEG_IRQ 13 ++#define BGM_IRQ 14 ++#define GMAC_IRQ 15 ++#define AES_IRQ 16 ++#define SDC0_IRQ 17 ++#define SDC1_IRQ 18 ++#define ACW_IRQ 19 ++#define SADC_IRQ 20 ++#define SPI1_IRQ 21 ++#define SPI2_IRQ 22 ++#define DMAC0_IRQ 23 ++#define DMAC1_IRQ 24 ++#define I2S0_IRQ 25 ++#define GPIO0_IRQ 26 ++#define USBC_IRQ 27 ++#define SPI0_IRQ 28 ++#define ARC_SW_IRQ 29 ++#define UART0_IRQ 30 ++#define UART1_IRQ 31 ++#define ARM_SW_IRQ 32 ++#define RTC_IRQ 33 ++#define AHBC0_IRQ 34 ++#define AHBC1_IRQ 35 ++#define PWM_IRQ 36 ++#define MIPIC_IRQ 37 ++#define MIPI_WRAP_IRQ 38 ++#define WAVE420_IRQ 39 ++#define GPIO1_IRQ 40 ++#define USBC_IDHV_IRQ 41 ++#define USBC_OTG_IRQ 42 ++#define USBC_DP_IRQ 43 ++#define USBC_DM_IRQ 44 ++ ++#define UTMI_RST_BIT (1<<1) ++ ++#define NR_INTERNAL_IRQS (64) ++#define NR_EXTERNAL_IRQS (64) ++#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS) ++ ++/* SWRST_MAIN_CTRL */ ++#define CPU_RSTN_BIT (0) ++#define UTMI_RSTN_BIT (1) ++#define DDRPHY_RSTN_BIT (2) ++#define DDRC_RSTN_BIT (3) ++#define PIXEL_RSTN_BIT (6) ++#define PWM_RSTN_BIT (7) ++#define SPI0_RSTN_BIT (8) ++#define SPI1_RSTN_BIT (9) ++#define I2C0_RSTN_BIT (10) ++#define I2C1_RSTN_BIT (11) ++#define ACODEC_RSTN_BIT (12) ++#define I2S_RSTN_BIT (13) ++#define UART0_RSTN_BIT (14) ++#define UART1_RSTN_BIT (15) ++#define SADC_RSTN_BIT (16) ++#define PTS_RSTN_BIT (17) ++#define TMR_RSTN_BIT (18) ++#define SPI2_RSTN_BIT (20) ++#define PAE_ARC_RSTN_BIT (21) ++#define ARC_RSTN_BIT (22) ++#define EFUSE_RSTN_BIT (23) ++#define WAVE420_ARSTN_BIT (24) ++#define WAVE420_BRSTN_BIT (25) ++#define WAVE420_CRSTN_BIT (26) ++#define SYS_RSTN_BIT (31) ++ ++/* SWRST_AHB_CTRL */ ++#define EMC_HRSTN_BIT (0) ++#define SDC1_HRSTN_BIT (1) ++#define SDC0_HRSTN_BIT (2) ++#define AES_HRSTN_BIT (3) ++#define DMAC0_HRSTN_BIT (4) ++#define INTC_HRSTN_BIT (5) ++#define JPEG_HRSTN_BIT (8) ++#define VCU_HRSTN_BIT (9) ++#define VPU_HRSTN_BIT (10) ++#define ISP_HRSTN_BIT (11) ++#define USB_HRSTN_BIT (12) ++#define HRST1N_BIT (13) ++#define HRST0N_BIT (14) ++#define ARC_HRSTN_BIT (15) ++#define PAE_ARC_HRSTN_BIT (16) ++#define EMAC_HRSTN_BIT (17) ++#define DDRC_P3_UHRSTN_BIT (19) ++#define DMAC1_HRSTN_BIT (20) ++#define H2P_HRSTN_BIT (21) ++#define BGM_HRSTN_BIT (22) ++#define HRST2N_BIT (23) ++#define HRST3N_BIT (24) ++ ++/* FH Serial HardWare HandShake */ ++#define UART1_TX_HW_HANDSHAKE (9) ++#define UART1_RX_HW_HANDSHAKE (8) ++#define UART1_DMA_TX_CHAN (2) ++#define UART1_DMA_RX_CHAN (3) ++ ++ ++/* timer clk */ ++#define TIMER_CLK (50000000) ++ ++ ++#endif /* __ASM_ARCH_FH8856_H */ +diff --git a/arch/arm/mach-fh/include/mach/fh8856_iopad.h b/arch/arm/mach-fh/include/mach/fh8856_iopad.h +new file mode 100644 +index 00000000..becb1a97 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh8856_iopad.h +@@ -0,0 +1,577 @@ ++#include "pinctrl.h" ++#include "pinctrl_osdep.h" ++#include "board_config.h" ++ ++/* PINCTRL_FUNC */ ++PINCTRL_FUNC(GPIO19, 0, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 0, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO20, 1, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 1, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO21, 2, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C1_SDA, 2, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO25, 3, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_TXD, 3, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_TXD, 3, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO26, 4, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_RXD, 4, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_RXD, 4, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO27, 5, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CLK, 5, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CLK, 5, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO28, 6, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 6, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CSN, 6, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(USB_DBG_CLK, 6, FUNC3, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI0_D2, 7, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO50, 7, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SDA, 7, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 7, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_D3, 8, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO51, 8, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SCL, 8, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 8, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO22, 9, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C1_SCL, 9, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO23, 10, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(AC_MCLK, 10, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO24, 11, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(USB_PWREN, 11, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(MAC_RMII_CLK, 15, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO15, 15, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CLK, 15, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 15, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CLK, 15, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CLK, 15, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_REF_CLK, 16, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(MAC_MDC, 17, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO34, 17, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_WP, 17, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(RTC_CLK, 17, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_MCLK, 17, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(USB_PWREN, 17, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_MDIO, 18, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO17, 18, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TDO, 18, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM7, 18, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXD_0, 22, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO16, 22, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_0, 22, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 22, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 22, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_RXD, 22, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXD_1, 23, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO38, 23, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_1, 23, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 23, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 23, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 23, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_RXDV, 26, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO41, 26, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CD, 26, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM3, 26, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXD_0, 28, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO42, 28, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_2, 28, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM4, 28, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXD_1, 29, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO43, 29, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_3, 29, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM5, 29, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 29, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 29, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(MAC_TXEN, 32, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO46, 32, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM6, 32, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 32, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_TXD, 32, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TRSTN, 35, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO0, 35, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 35, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_TXD, 35, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_DO, 35, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_DO, 35, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ACIP_ADDAT, 35, FUNC6, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TMS, 36, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO1, 36, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 36, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_RXD, 36, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_DI, 36, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_DI, 36, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ARM_JTAG_TCK, 37, FUNC0, PUPD_DOWN, 3); ++PINCTRL_FUNC(GPIO2, 37, FUNC1, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI1_CLK, 37, FUNC2, PUPD_DOWN, 3); ++PINCTRL_FUNC(SSI2_CLK, 37, FUNC3, PUPD_DOWN, 3); ++PINCTRL_FUNC(AC_I2S_CLK, 37, FUNC4, PUPD_DOWN, 3); ++PINCTRL_FUNC(DW_I2S_CLK, 37, FUNC5, PUPD_DOWN, 3); ++PINCTRL_FUNC(ACIP_BCLK, 37, FUNC6, PUPD_DOWN, 3); ++PINCTRL_FUNC(ARM_JTAG_TDI, 38, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO3, 38, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(SSI2_CSN, 38, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(AC_I2S_WS, 38, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(DW_I2S_WS, 38, FUNC5, PUPD_UP, 3); ++PINCTRL_FUNC(ACIP_ADLRC, 38, FUNC6, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO4, 39, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CLK, 39, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 39, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO5, 40, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_0, 40, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 40, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO6, 41, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_1, 41, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 41, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO7, 42, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CD, 42, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM3, 42, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO8, 43, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_2, 43, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM4, 43, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO9, 44, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_DATA_3, 44, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM5, 44, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO10, 45, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_CMD_RSP, 45, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM6, 45, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO11, 46, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD1_WP, 46, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM7, 46, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM0, 47, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO12, 47, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(CIS_CLK, 47, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PWM1, 48, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO13, 48, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(PWM2, 49, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(UART0_RX, 50, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO48, 50, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(UART0_TX, 51, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO49, 51, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C0_SCL, 52, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO57, 52, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(I2C0_SDA, 53, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO56, 53, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI0_CLK, 56, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI0_TXD, 57, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_CSN_0, 58, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO54, 58, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_CSN_1, 59, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO55, 59, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SSI0_RXD, 60, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_CD, 61, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO52, 61, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TRSTN, 61, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TRSTN, 61, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_WP, 62, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO53, 62, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_CLK, 63, FUNC0, PUPD_NONE, 3); ++PINCTRL_FUNC(GPIO63, 63, FUNC1, PUPD_NONE, 3); ++PINCTRL_FUNC(ARC_JTAG_TMS, 63, FUNC2, PUPD_NONE, 3); ++PINCTRL_FUNC(PAE_JTAG_TMS, 63, FUNC3, PUPD_NONE, 3); ++PINCTRL_FUNC(SSI1_CLK, 63, FUNC4, PUPD_NONE, 3); ++PINCTRL_FUNC(SD0_CMD_RSP, 64, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO29, 64, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TCK, 64, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TCK, 64, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_TXD, 64, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_0, 65, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO62, 65, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TDI, 65, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TDI, 65, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_RXD, 65, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_1, 66, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO61, 66, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(USB_PWREN, 66, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(AC_MCLK, 66, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 66, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_2, 67, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO60, 67, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SDA, 67, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_TX, 67, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(ARC_JTAG_TDO, 67, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SD0_DATA_3, 68, FUNC0, PUPD_UP, 3); ++PINCTRL_FUNC(GPIO18, 68, FUNC1, PUPD_UP, 3); ++PINCTRL_FUNC(I2C1_SCL, 68, FUNC2, PUPD_UP, 3); ++PINCTRL_FUNC(UART1_RX, 68, FUNC3, PUPD_UP, 3); ++PINCTRL_FUNC(PAE_JTAG_TDO, 68, FUNC4, PUPD_UP, 3); ++PINCTRL_FUNC(SSI1_CSN_0, 68, FUNC5, PUPD_UP, 3); ++ ++ ++/* PINCTRL_MUX */ ++ ++PINCTRL_MUX(ACIP_ADDAT, 0, &PAD35_ACIP_ADDAT); ++PINCTRL_MUX(ACIP_ADLRC, 0, &PAD38_ACIP_ADLRC); ++PINCTRL_MUX(ACIP_BCLK, 0, &PAD37_ACIP_BCLK); ++ ++PINCTRL_MUX(AC_I2S_CLK, 0, &PAD37_AC_I2S_CLK); ++PINCTRL_MUX(AC_I2S_DI, 0, &PAD36_AC_I2S_DI); ++PINCTRL_MUX(AC_I2S_DO, 0, &PAD35_AC_I2S_DO); ++PINCTRL_MUX(AC_I2S_WS, 0, &PAD38_AC_I2S_WS); ++PINCTRL_MUX(AC_MCLK, 0, &PAD10_AC_MCLK, &PAD17_AC_MCLK, &PAD66_AC_MCLK); ++ ++PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD64_ARC_JTAG_TCK); ++PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD65_ARC_JTAG_TDI); ++PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD67_ARC_JTAG_TDO); ++PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD63_ARC_JTAG_TMS); ++PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD61_ARC_JTAG_TRSTN); ++ ++PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD37_ARM_JTAG_TCK); ++PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD38_ARM_JTAG_TDI); ++PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD18_ARM_JTAG_TDO); ++PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD36_ARM_JTAG_TMS); ++PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD35_ARM_JTAG_TRSTN); ++ ++PINCTRL_MUX(CIS_CLK, 0, &PAD47_CIS_CLK); ++ ++PINCTRL_MUX(DW_I2S_CLK, 0, &PAD37_DW_I2S_CLK); ++PINCTRL_MUX(DW_I2S_DI, 0, &PAD36_DW_I2S_DI); ++PINCTRL_MUX(DW_I2S_DO, 0, &PAD35_DW_I2S_DO); ++PINCTRL_MUX(DW_I2S_WS, 0, &PAD38_DW_I2S_WS); ++ ++PINCTRL_MUX(I2C0_SCL, 0, &PAD52_I2C0_SCL); ++PINCTRL_MUX(I2C0_SDA, 0, &PAD53_I2C0_SDA); ++ ++PINCTRL_MUX(I2C1_SCL, 1, &PAD8_I2C1_SCL, &PAD9_I2C1_SCL, &PAD68_I2C1_SCL); ++PINCTRL_MUX(I2C1_SDA, 0, &PAD2_I2C1_SDA, &PAD7_I2C1_SDA, &PAD67_I2C1_SDA); ++ ++PINCTRL_MUX(MAC_MDC, 0, &PAD17_MAC_MDC); ++PINCTRL_MUX(MAC_MDIO, 0, &PAD18_MAC_MDIO); ++PINCTRL_MUX(MAC_REF_CLK, 0, &PAD16_MAC_REF_CLK); ++PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD15_MAC_RMII_CLK); ++PINCTRL_MUX(MAC_RXDV, 0, &PAD26_MAC_RXDV); ++PINCTRL_MUX(MAC_RXD_0, 0, &PAD22_MAC_RXD_0); ++PINCTRL_MUX(MAC_RXD_1, 0, &PAD23_MAC_RXD_1); ++PINCTRL_MUX(MAC_TXD_0, 0, &PAD28_MAC_TXD_0); ++PINCTRL_MUX(MAC_TXD_1, 0, &PAD29_MAC_TXD_1); ++PINCTRL_MUX(MAC_TXEN, 0, &PAD32_MAC_TXEN); ++ ++PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD64_PAE_JTAG_TCK); ++PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD65_PAE_JTAG_TDI); ++PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD68_PAE_JTAG_TDO); ++PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD63_PAE_JTAG_TMS); ++PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD61_PAE_JTAG_TRSTN); ++ ++PINCTRL_MUX(PWM0, 2, &PAD15_PWM0, &PAD39_PWM0, &PAD47_PWM0); ++PINCTRL_MUX(PWM1, 2, &PAD22_PWM1, &PAD40_PWM1, &PAD48_PWM1); ++PINCTRL_MUX(PWM2, 2, &PAD23_PWM2, &PAD41_PWM2, &PAD49_PWM2); ++PINCTRL_MUX(PWM3, 1, &PAD26_PWM3, &PAD42_PWM3); ++PINCTRL_MUX(PWM4, 1, &PAD28_PWM4, &PAD43_PWM4); ++PINCTRL_MUX(PWM5, 1, &PAD29_PWM5, &PAD44_PWM5); ++PINCTRL_MUX(PWM6, 1, &PAD32_PWM6, &PAD45_PWM6); ++PINCTRL_MUX(PWM7, 1, &PAD18_PWM7, &PAD46_PWM7); ++ ++PINCTRL_MUX(RTC_CLK, 0, &PAD17_RTC_CLK); ++ ++PINCTRL_MUX(SD0_CD, 0, &PAD61_SD0_CD); ++PINCTRL_MUX(SD0_CLK, 0, &PAD63_SD0_CLK); ++PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD64_SD0_CMD_RSP); ++PINCTRL_MUX(SD0_DATA_0, 0, &PAD65_SD0_DATA_0); ++PINCTRL_MUX(SD0_DATA_1, 0, &PAD66_SD0_DATA_1); ++PINCTRL_MUX(SD0_DATA_2, 0, &PAD67_SD0_DATA_2); ++PINCTRL_MUX(SD0_DATA_3, 0, &PAD68_SD0_DATA_3); ++PINCTRL_MUX(SD0_WP, 0, &PAD62_SD0_WP); ++ ++PINCTRL_MUX(SD1_CD, 1, &PAD26_SD1_CD, &PAD42_SD1_CD); ++PINCTRL_MUX(SD1_CLK, 1, &PAD15_SD1_CLK, &PAD39_SD1_CLK); ++PINCTRL_MUX(SD1_CMD_RSP, 1, &PAD32_SD1_CMD_RSP, &PAD45_SD1_CMD_RSP); ++PINCTRL_MUX(SD1_DATA_0, 1, &PAD22_SD1_DATA_0, &PAD40_SD1_DATA_0); ++PINCTRL_MUX(SD1_DATA_1, 1, &PAD23_SD1_DATA_1, &PAD41_SD1_DATA_1); ++PINCTRL_MUX(SD1_DATA_2, 1, &PAD28_SD1_DATA_2, &PAD43_SD1_DATA_2); ++PINCTRL_MUX(SD1_DATA_3, 1, &PAD29_SD1_DATA_3, &PAD44_SD1_DATA_3); ++PINCTRL_MUX(SD1_WP, 1, &PAD17_SD1_WP, &PAD46_SD1_WP); ++ ++PINCTRL_MUX(SSI0_CLK, 0, &PAD56_SSI0_CLK); ++PINCTRL_MUX(SSI0_CSN_0, 0, &PAD58_SSI0_CSN_0); ++PINCTRL_MUX(SSI0_CSN_1, 0, &PAD59_SSI0_CSN_1); ++PINCTRL_MUX(SSI0_D2, 0, &PAD7_SSI0_D2); ++PINCTRL_MUX(SSI0_D3, 0, &PAD8_SSI0_D3); ++PINCTRL_MUX(SSI0_RXD, 0, &PAD60_SSI0_RXD); ++PINCTRL_MUX(SSI0_TXD, 0, &PAD57_SSI0_TXD); ++ ++PINCTRL_MUX(SSI1_CLK, 2, &PAD5_SSI1_CLK, &PAD15_SSI1_CLK, &PAD37_SSI1_CLK, ++ &PAD63_SSI1_CLK); ++PINCTRL_MUX(SSI1_CSN_0, 3, &PAD6_SSI1_CSN_0, &PAD23_SSI1_CSN_0, ++ &PAD29_SSI1_CSN_0, &PAD38_SSI1_CSN_0, &PAD66_SSI1_CSN_0, ++ &PAD68_SSI1_CSN_0); ++PINCTRL_MUX(SSI1_RXD, 2, &PAD4_SSI1_RXD, &PAD22_SSI1_RXD, &PAD36_SSI1_RXD, ++ &PAD65_SSI1_RXD); ++PINCTRL_MUX(SSI1_TXD, 2, &PAD3_SSI1_TXD, &PAD32_SSI1_TXD, &PAD35_SSI1_TXD, ++ &PAD64_SSI1_TXD); ++ ++PINCTRL_MUX(SSI2_CLK, 0, &PAD5_SSI2_CLK, &PAD15_SSI2_CLK, &PAD37_SSI2_CLK); ++PINCTRL_MUX(SSI2_CSN, 0, &PAD6_SSI2_CSN, &PAD23_SSI2_CSN, &PAD29_SSI2_CSN, ++ &PAD38_SSI2_CSN); ++PINCTRL_MUX(SSI2_RXD, 0, &PAD4_SSI2_RXD, &PAD22_SSI2_RXD, &PAD36_SSI2_RXD); ++PINCTRL_MUX(SSI2_TXD, 0, &PAD3_SSI2_TXD, &PAD32_SSI2_TXD, &PAD35_SSI2_TXD); ++ ++PINCTRL_MUX(UART0_RX, 0, &PAD50_UART0_RX); ++PINCTRL_MUX(UART0_TX, 0, &PAD51_UART0_TX); ++ ++PINCTRL_MUX(UART1_RX, 0, &PAD1_UART1_RX, &PAD8_UART1_RX, &PAD68_UART1_RX); ++PINCTRL_MUX(UART1_TX, 0, &PAD0_UART1_TX, &PAD7_UART1_TX, &PAD67_UART1_TX); ++ ++PINCTRL_MUX(USB_DBG_CLK, 0, &PAD6_USB_DBG_CLK); ++PINCTRL_MUX(USB_PWREN, 0, &PAD11_USB_PWREN, &PAD17_USB_PWREN, &PAD66_USB_PWREN); ++ ++PINCTRL_MUX(GPIO0, 0, &PAD35_GPIO0); ++PINCTRL_MUX(GPIO1, 0, &PAD36_GPIO1); ++PINCTRL_MUX(GPIO2, 0, &PAD37_GPIO2); ++PINCTRL_MUX(GPIO3, 0, &PAD38_GPIO3); ++PINCTRL_MUX(GPIO4, 0, &PAD39_GPIO4); ++PINCTRL_MUX(GPIO5, 0, &PAD40_GPIO5); ++PINCTRL_MUX(GPIO6, 0, &PAD41_GPIO6); ++PINCTRL_MUX(GPIO7, 0, &PAD42_GPIO7); ++PINCTRL_MUX(GPIO8, 0, &PAD43_GPIO8); ++PINCTRL_MUX(GPIO9, 0, &PAD44_GPIO9); ++PINCTRL_MUX(GPIO10, 0, &PAD45_GPIO10); ++PINCTRL_MUX(GPIO11, 0, &PAD46_GPIO11); ++PINCTRL_MUX(GPIO12, 0, &PAD47_GPIO12); ++PINCTRL_MUX(GPIO13, 0, &PAD48_GPIO13); ++PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14); ++PINCTRL_MUX(GPIO15, 0, &PAD15_GPIO15); ++PINCTRL_MUX(GPIO16, 0, &PAD22_GPIO16); ++PINCTRL_MUX(GPIO17, 0, &PAD18_GPIO17); ++PINCTRL_MUX(GPIO18, 0, &PAD68_GPIO18); ++PINCTRL_MUX(GPIO19, 0, &PAD0_GPIO19); ++PINCTRL_MUX(GPIO20, 0, &PAD1_GPIO20); ++PINCTRL_MUX(GPIO21, 0, &PAD2_GPIO21); ++PINCTRL_MUX(GPIO22, 0, &PAD9_GPIO22); ++PINCTRL_MUX(GPIO23, 0, &PAD10_GPIO23); ++PINCTRL_MUX(GPIO24, 0, &PAD11_GPIO24); ++PINCTRL_MUX(GPIO25, 0, &PAD3_GPIO25); ++PINCTRL_MUX(GPIO26, 0, &PAD4_GPIO26); ++PINCTRL_MUX(GPIO27, 0, &PAD5_GPIO27); ++PINCTRL_MUX(GPIO28, 0, &PAD6_GPIO28); ++PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29); ++PINCTRL_MUX(GPIO34, 0, &PAD17_GPIO34); ++PINCTRL_MUX(GPIO38, 0, &PAD23_GPIO38); ++PINCTRL_MUX(GPIO41, 0, &PAD26_GPIO41); ++PINCTRL_MUX(GPIO42, 0, &PAD28_GPIO42); ++PINCTRL_MUX(GPIO43, 0, &PAD29_GPIO43); ++PINCTRL_MUX(GPIO46, 0, &PAD32_GPIO46); ++PINCTRL_MUX(GPIO48, 0, &PAD50_GPIO48); ++PINCTRL_MUX(GPIO49, 0, &PAD51_GPIO49); ++PINCTRL_MUX(GPIO50, 0, &PAD7_GPIO50); ++PINCTRL_MUX(GPIO51, 0, &PAD8_GPIO51); ++PINCTRL_MUX(GPIO52, 0, &PAD61_GPIO52); ++PINCTRL_MUX(GPIO53, 0, &PAD62_GPIO53); ++PINCTRL_MUX(GPIO54, 0, &PAD58_GPIO54); ++PINCTRL_MUX(GPIO55, 0, &PAD59_GPIO55); ++PINCTRL_MUX(GPIO56, 0, &PAD53_GPIO56); ++PINCTRL_MUX(GPIO57, 0, &PAD52_GPIO57); ++PINCTRL_MUX(GPIO60, 0, &PAD67_GPIO60); ++PINCTRL_MUX(GPIO61, 0, &PAD66_GPIO61); ++PINCTRL_MUX(GPIO62, 0, &PAD65_GPIO62); ++PINCTRL_MUX(GPIO63, 0, &PAD63_GPIO63); ++ ++PINCTRL_MUX(SD1_CLK_RMII, 0, &PAD15_SD1_CLK, &PAD39_SD1_CLK); ++PINCTRL_MUX(SD1_CD_RMII, 0, &PAD26_SD1_CD, &PAD42_SD1_CD); ++PINCTRL_MUX(SD1_CMD_RSP_RMII, 0, &PAD32_SD1_CMD_RSP, &PAD45_SD1_CMD_RSP); ++PINCTRL_MUX(SD1_WP_RMII, 0, &PAD17_SD1_WP, &PAD46_SD1_WP); ++PINCTRL_MUX(SD1_DATA_0_RMII, 0, &PAD22_SD1_DATA_0, &PAD40_SD1_DATA_0); ++PINCTRL_MUX(SD1_DATA_1_RMII, 0, &PAD23_SD1_DATA_1, &PAD41_SD1_DATA_1); ++PINCTRL_MUX(SD1_DATA_2_RMII, 0, &PAD28_SD1_DATA_2, &PAD43_SD1_DATA_2); ++PINCTRL_MUX(SD1_DATA_3_RMII, 0, &PAD29_SD1_DATA_3, &PAD44_SD1_DATA_3); ++ ++/* PINCTRL_DEVICE */ ++PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO, ++ &MUX_AC_I2S_WS, &MUX_AC_MCLK); ++PINCTRL_DEVICE(ACIP, 3, &MUX_ACIP_ADDAT, &MUX_ACIP_ADLRC, &MUX_ACIP_BCLK); ++PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI, ++ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN); ++PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI, ++ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN); ++PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO, ++ &MUX_DW_I2S_WS); ++PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA); ++PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA); ++PINCTRL_DEVICE(MIPI, 1, &MUX_CIS_CLK); ++PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI, ++ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN); ++PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0); ++PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1); ++PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2); ++PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3); ++PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4); ++PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5); ++PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6); ++PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7); ++PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK, ++ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1, ++ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN); ++PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK); ++PINCTRL_DEVICE(SD0, 8, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3, ++ &MUX_SD0_WP); ++PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0); ++PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, ++ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3); ++PINCTRL_DEVICE(SD1, 8, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, ++ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3, ++ &MUX_SD1_WP); ++PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, ++ &MUX_SD1_DATA_0); ++PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, ++ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3); ++PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO54, &MUX_SSI0_CLK, &MUX_SSI0_RXD, ++ &MUX_SSI0_TXD); ++PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO54, &MUX_SSI0_CLK, &MUX_SSI0_D2, ++ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD); ++PINCTRL_DEVICE(SSI1, 4, &MUX_SSI1_CLK, &MUX_SSI1_CSN_0, &MUX_SSI1_RXD, ++ &MUX_SSI1_TXD); ++PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN, &MUX_SSI2_RXD, ++ &MUX_SSI2_TXD); ++PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX); ++PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX); ++PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN); ++PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0); ++PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1); ++PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2); ++PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3); ++PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4); ++PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5); ++PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6); ++PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7); ++PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8); ++PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9); ++PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10); ++PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11); ++PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12); ++PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13); ++PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14); ++PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15); ++PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16); ++PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17); ++PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18); ++PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19); ++PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20); ++PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21); ++PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22); ++PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23); ++PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24); ++PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25); ++PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26); ++PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27); ++PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28); ++PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29); ++PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34); ++PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38); ++PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41); ++PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42); ++PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43); ++PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46); ++PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48); ++PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49); ++PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50); ++PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51); ++PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52); ++PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53); ++PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54); ++PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55); ++PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56); ++PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57); ++PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60); ++PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61); ++PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62); ++PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63); ++ ++PINCTRL_DEVICE(SD1_WIFI_RMII, 7, &MUX_SD1_CLK_RMII, &MUX_SD1_CD_RMII, ++ &MUX_SD1_CMD_RSP_RMII, &MUX_SD1_DATA_0_RMII, &MUX_SD1_DATA_1_RMII, ++ &MUX_SD1_DATA_2_RMII, &MUX_SD1_DATA_3_RMII); ++ ++void fh_pinctrl_init_devicelist(OS_LIST *list) ++{ ++ OS_LIST_EMPTY(list); ++ ++ /*PINCTRL_ADD_DEVICE*/ ++ PINCTRL_ADD_DEVICE(ACI2S); ++ PINCTRL_ADD_DEVICE(ACIP); ++ PINCTRL_ADD_DEVICE(ARCJTAG); ++ PINCTRL_ADD_DEVICE(ARMJTAG); ++ PINCTRL_ADD_DEVICE(DWI2S); ++ PINCTRL_ADD_DEVICE(I2C0); ++ PINCTRL_ADD_DEVICE(I2C1); ++ PINCTRL_ADD_DEVICE(MIPI); ++ PINCTRL_ADD_DEVICE(PAEJTAG); ++ PINCTRL_ADD_DEVICE(PWM0); ++ PINCTRL_ADD_DEVICE(PWM1); ++ PINCTRL_ADD_DEVICE(PWM2); ++ PINCTRL_ADD_DEVICE(PWM3); ++ PINCTRL_ADD_DEVICE(PWM4); ++ PINCTRL_ADD_DEVICE(PWM5); ++ PINCTRL_ADD_DEVICE(PWM6); ++ PINCTRL_ADD_DEVICE(PWM7); ++ PINCTRL_ADD_DEVICE(RMII); ++ PINCTRL_ADD_DEVICE(RTC); ++ PINCTRL_ADD_DEVICE(SD0); ++ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP); ++ PINCTRL_ADD_DEVICE(SD0_NO_WP); ++ PINCTRL_ADD_DEVICE(SD1); ++ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP); ++ PINCTRL_ADD_DEVICE(SD1_NO_WP); ++ PINCTRL_ADD_DEVICE(SSI0); ++ PINCTRL_ADD_DEVICE(SSI0_4BIT); ++ PINCTRL_ADD_DEVICE(SSI1); ++ PINCTRL_ADD_DEVICE(SSI2); ++ PINCTRL_ADD_DEVICE(UART0); ++ PINCTRL_ADD_DEVICE(UART1); ++ PINCTRL_ADD_DEVICE(USB); ++ PINCTRL_ADD_DEVICE(GPIO0); ++ PINCTRL_ADD_DEVICE(GPIO1); ++ PINCTRL_ADD_DEVICE(GPIO2); ++ PINCTRL_ADD_DEVICE(GPIO3); ++ PINCTRL_ADD_DEVICE(GPIO4); ++ PINCTRL_ADD_DEVICE(GPIO5); ++ PINCTRL_ADD_DEVICE(GPIO6); ++ PINCTRL_ADD_DEVICE(GPIO7); ++ PINCTRL_ADD_DEVICE(GPIO8); ++ PINCTRL_ADD_DEVICE(GPIO9); ++ PINCTRL_ADD_DEVICE(GPIO10); ++ PINCTRL_ADD_DEVICE(GPIO11); ++ PINCTRL_ADD_DEVICE(GPIO12); ++ PINCTRL_ADD_DEVICE(GPIO13); ++ PINCTRL_ADD_DEVICE(GPIO14); ++ PINCTRL_ADD_DEVICE(GPIO15); ++ PINCTRL_ADD_DEVICE(GPIO16); ++ PINCTRL_ADD_DEVICE(GPIO17); ++ PINCTRL_ADD_DEVICE(GPIO18); ++ PINCTRL_ADD_DEVICE(GPIO19); ++ PINCTRL_ADD_DEVICE(GPIO20); ++ PINCTRL_ADD_DEVICE(GPIO21); ++ PINCTRL_ADD_DEVICE(GPIO22); ++ PINCTRL_ADD_DEVICE(GPIO23); ++ PINCTRL_ADD_DEVICE(GPIO24); ++ PINCTRL_ADD_DEVICE(GPIO25); ++ PINCTRL_ADD_DEVICE(GPIO26); ++ PINCTRL_ADD_DEVICE(GPIO27); ++ PINCTRL_ADD_DEVICE(GPIO28); ++ PINCTRL_ADD_DEVICE(GPIO29); ++ PINCTRL_ADD_DEVICE(GPIO34); ++ PINCTRL_ADD_DEVICE(GPIO38); ++ PINCTRL_ADD_DEVICE(GPIO41); ++ PINCTRL_ADD_DEVICE(GPIO42); ++ PINCTRL_ADD_DEVICE(GPIO43); ++ PINCTRL_ADD_DEVICE(GPIO46); ++ PINCTRL_ADD_DEVICE(GPIO48); ++ PINCTRL_ADD_DEVICE(GPIO49); ++ PINCTRL_ADD_DEVICE(GPIO50); ++ PINCTRL_ADD_DEVICE(GPIO51); ++ PINCTRL_ADD_DEVICE(GPIO52); ++ PINCTRL_ADD_DEVICE(GPIO53); ++ PINCTRL_ADD_DEVICE(GPIO54); ++ PINCTRL_ADD_DEVICE(GPIO55); ++ PINCTRL_ADD_DEVICE(GPIO56); ++ PINCTRL_ADD_DEVICE(GPIO57); ++ PINCTRL_ADD_DEVICE(GPIO60); ++ PINCTRL_ADD_DEVICE(GPIO61); ++ PINCTRL_ADD_DEVICE(GPIO62); ++ PINCTRL_ADD_DEVICE(GPIO63); ++ ++ PINCTRL_ADD_DEVICE(SD1_WIFI_RMII); ++} ++ ++char* fh_pinctrl_selected_devices[] = ++{ ++ CONFIG_PINCTRL_SELECT ++}; +diff --git a/arch/arm/mach-fh/include/mach/fh_chipid.h b/arch/arm/mach-fh/include/mach/fh_chipid.h +new file mode 100644 +index 00000000..c2f9d1b9 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_chipid.h +@@ -0,0 +1,46 @@ ++/** ++ * Copyright (c) 2015-2019 Shanghai Fullhan Microelectronics Co., Ltd. ++ * ++ * SPDX-License-Identifier: Apache-2.0 ++ * ++ * ++ * Change Logs: ++ * Date Author Notes ++ * 2019-08-20 wangyl add license Apache-2.0 ++ */ ++ ++#ifndef __FH_CHIPID_H__ ++#define __FH_CHIPID_H__ ++ ++#define FH_CHIP_FH8830 0x883000A1 ++#define FH_CHIP_FH8630M 0x883000B1 ++#define FH_CHIP_FH8632 0x863200A1 ++#define FH_CHIP_FH8632v2 0x863200A2 ++#define FH_CHIP_FH8856 0x885600A1 ++#define FH_CHIP_FH8852 0x885600B1 ++#define FH_CHIP_FH8626V100 0x8626A100 ++ ++struct fh_chip_info ++{ ++ int _plat_id; /* 芯片寄存器中的plat_id */ ++ int _chip_id; /* 芯片寄存器中的chip_id */ ++ int _chip_mask; /* 芯片寄存器中的chip_id */ ++ int chip_id; /* 芯片chip_id,详见上述定义 */ ++ int ddr_size; /* 芯片DDR大小,单位Mbit */ ++ char chip_name[32]; /* 芯片名称 */ ++}; ++ ++void fh_get_chipid(unsigned int *plat_id, unsigned int *chip_id); ++unsigned int fh_get_ddrsize_mbit(void); ++char *fh_get_chipname(void); ++struct fh_chip_info *fh_get_chip_info(void); ++ ++unsigned int fh_is_8830(void); ++unsigned int fh_is_8632(void); ++unsigned int fh_is_8852(void); ++unsigned int fh_is_8856(void); ++unsigned int fh_is_8626v100(void); ++ ++int fh_chipid_init(void); ++ ++#endif /* __FH_CHIPID_H__ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_dmac.h b/arch/arm/mach-fh/include/mach/fh_dmac.h +new file mode 100644 +index 00000000..c6d100b6 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_dmac.h +@@ -0,0 +1,151 @@ ++/* ++ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on ++ * AVR32 systems.) ++ * ++ * Copyright (C) 2007 Atmel Corporation ++ * Copyright (C) 2010-2011 ST Microelectronics ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#ifndef FH_DMAC_H ++#define FH_DMAC_H ++ ++#include <linux/dmaengine.h> ++ ++/** ++ * enum fh_dma_slave_width - DMA slave register access width. ++ * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses ++ * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses ++ * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses ++ */ ++enum fh_dma_slave_width { ++ FH_DMA_SLAVE_WIDTH_8BIT, ++ FH_DMA_SLAVE_WIDTH_16BIT, ++ FH_DMA_SLAVE_WIDTH_32BIT, ++}; ++ ++/* bursts size */ ++enum fh_dma_msize { ++ FH_DMA_MSIZE_1, ++ FH_DMA_MSIZE_4, ++ FH_DMA_MSIZE_8, ++ FH_DMA_MSIZE_16, ++ FH_DMA_MSIZE_32, ++ FH_DMA_MSIZE_64, ++ FH_DMA_MSIZE_128, ++ FH_DMA_MSIZE_256, ++}; ++ ++/* flow controller */ ++enum fh_dma_fc { ++ FH_DMA_FC_D_M2M, ++ FH_DMA_FC_D_M2P, ++ FH_DMA_FC_D_P2M, ++ FH_DMA_FC_D_P2P, ++ FH_DMA_FC_P_P2M, ++ FH_DMA_FC_SP_P2P, ++ FH_DMA_FC_P_M2P, ++ FH_DMA_FC_DP_P2P, ++}; ++ ++/** ++ * struct fh_dma_slave - Controller-specific information about a slave ++ * ++ * @dma_dev: required DMA master device ++ * @tx_reg: physical address of data register used for ++ * memory-to-peripheral transfers ++ * @rx_reg: physical address of data register used for ++ * peripheral-to-memory transfers ++ * @reg_width: peripheral register width ++ * @cfg_hi: Platform-specific initializer for the CFG_HI register ++ * @cfg_lo: Platform-specific initializer for the CFG_LO register ++ * @src_master: src master for transfers on allocated channel. ++ * @dst_master: dest master for transfers on allocated channel. ++ * @src_msize: src burst size. ++ * @dst_msize: dest burst size. ++ * @fc: flow controller for DMA transfer ++ */ ++struct fh_dma_slave { ++ struct device *dma_dev; ++ dma_addr_t tx_reg; ++ dma_addr_t rx_reg; ++ enum fh_dma_slave_width reg_width; ++ u32 cfg_hi; ++ u32 cfg_lo; ++ u8 src_master; ++ u8 dst_master; ++ u8 src_msize; ++ u8 dst_msize; ++ u8 fc; ++}; ++ ++ ++/** ++ * struct fh_dma_platform_data - Controller configuration parameters ++ * @nr_channels: Number of channels supported by hardware (max 8) ++ * @is_private: The device channels should be marked as private and not for ++ * by the general purpose DMA channel allocator. ++ * @chan_allocation_order: Allocate channels starting from 0 or 7 ++ * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. ++ * @block_size: Maximum block size supported by the controller ++ * @nr_masters: Number of AHB masters supported by the controller ++ * @data_width: Maximum data width supported by hardware per AHB master ++ * (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) ++ * @sd: slave specific data. Used for configuring channels ++ * @sd_count: count of slave data structures passed. ++ */ ++struct fh_dma_platform_data { ++ unsigned int nr_channels; ++ bool is_private; ++#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ ++#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ ++ unsigned char chan_allocation_order; ++#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ ++#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ ++ unsigned char chan_priority; ++ unsigned short block_size; ++ unsigned char nr_masters; ++ unsigned char data_width[4]; ++}; ++ ++/* Platform-configurable bits in CFG_HI */ ++#define FHC_CFGH_FCMODE (1 << 0) ++#define FHC_CFGH_FIFO_MODE (1 << 1) ++#define FHC_CFGH_PROTCTL(x) ((x) << 2) ++#define FHC_CFGH_SRC_PER(x) ((x) << 7) ++#define FHC_CFGH_DST_PER(x) ((x) << 11) ++ ++/* Platform-configurable bits in CFG_LO */ ++#define FHC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ ++#define FHC_CFGL_LOCK_CH_BLOCK (1 << 12) ++#define FHC_CFGL_LOCK_CH_XACT (2 << 12) ++#define FHC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ ++#define FHC_CFGL_LOCK_BUS_BLOCK (1 << 14) ++#define FHC_CFGL_LOCK_BUS_XACT (2 << 14) ++#define FHC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ ++#define FHC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ ++#define FHC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ ++#define FHC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ ++ ++/* DMA API extensions */ ++struct fh_cyclic_desc { ++ struct fh_desc **desc; ++ unsigned long periods; ++ void (*period_callback)(void *param); ++ void *period_callback_param; ++}; ++ ++struct fh_cyclic_desc *fh_dma_cyclic_prep(struct dma_chan *chan, ++ dma_addr_t buf_addr, size_t buf_len, size_t period_len, ++ enum dma_transfer_direction direction); ++void fh_dma_cyclic_free(struct dma_chan *chan); ++int fh_dma_cyclic_start(struct dma_chan *chan); ++void fh_dma_cyclic_stop(struct dma_chan *chan); ++ ++dma_addr_t fh_dma_get_src_addr(struct dma_chan *chan); ++ ++dma_addr_t fh_dma_get_dst_addr(struct dma_chan *chan); ++ ++#endif /* FH_DMAC_H */ +diff --git a/arch/arm/mach-fh/include/mach/fh_dmac_regs.h b/arch/arm/mach-fh/include/mach/fh_dmac_regs.h +new file mode 100644 +index 00000000..208d686c +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_dmac_regs.h +@@ -0,0 +1,321 @@ ++/* ++ * Driver for the Synopsys DesignWare AHB DMA Controller ++ * ++ * Copyright (C) 2005-2007 Atmel Corporation ++ * Copyright (C) 2010-2011 ST Microelectronics ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/dmaengine.h> ++#include <mach/fh_dmac.h> ++ ++#define FH_DMA_MAX_NR_CHANNELS 8 ++#define FH_DMA_MAX_NR_REQUESTS 16 ++ ++/* ++ * Redefine this macro to handle differences between 32- and 64-bit ++ * addressing, big vs. little endian, etc. ++ */ ++#define FH_REG(name) u32 name; u32 __pad_##name ++ ++/* Hardware register definitions. */ ++struct fh_dma_chan_regs { ++ FH_REG(SAR); /* Source Address Register */ ++ FH_REG(DAR); /* Destination Address Register */ ++ FH_REG(LLP); /* Linked List Pointer */ ++ u32 CTL_LO; /* Control Register Low */ ++ u32 CTL_HI; /* Control Register High */ ++ FH_REG(SSTAT); ++ FH_REG(DSTAT); ++ FH_REG(SSTATAR); ++ FH_REG(DSTATAR); ++ u32 CFG_LO; /* Configuration Register Low */ ++ u32 CFG_HI; /* Configuration Register High */ ++ FH_REG(SGR); ++ FH_REG(DSR); ++}; ++ ++struct fh_dma_irq_regs { ++ FH_REG(XFER); ++ FH_REG(BLOCK); ++ FH_REG(SRC_TRAN); ++ FH_REG(DST_TRAN); ++ FH_REG(ERROR); ++}; ++ ++struct fh_dma_regs { ++ /* per-channel registers */ ++ struct fh_dma_chan_regs CHAN[FH_DMA_MAX_NR_CHANNELS]; ++ ++ /* irq handling */ ++ struct fh_dma_irq_regs RAW; /* r */ ++ struct fh_dma_irq_regs STATUS; /* r (raw & mask) */ ++ struct fh_dma_irq_regs MASK; /* rw (set = irq enabled) */ ++ struct fh_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ ++ ++ FH_REG(STATUS_INT); /* r */ ++ ++ /* software handshaking */ ++ FH_REG(REQ_SRC); ++ FH_REG(REQ_DST); ++ FH_REG(SGL_REQ_SRC); ++ FH_REG(SGL_REQ_DST); ++ FH_REG(LAST_SRC); ++ FH_REG(LAST_DST); ++ ++ /* miscellaneous */ ++ FH_REG(CFG); ++ FH_REG(CH_EN); ++ FH_REG(ID); ++ FH_REG(TEST); ++ ++ /* reserved */ ++ FH_REG(__reserved0); ++ FH_REG(__reserved1); ++ ++ /* optional encoded params, 0x3c8..0x3f7 */ ++ u32 __reserved; ++ ++ /* per-channel configuration registers */ ++ u32 FHC_PARAMS[FH_DMA_MAX_NR_CHANNELS]; ++ u32 MULTI_BLK_TYPE; ++ u32 MAX_BLK_SIZE; ++ ++ /* top-level parameters */ ++ u32 FH_PARAMS; ++}; ++ ++#ifdef CONFIG_FH_DMAC_BIG_ENDIAN_IO ++#define dma_readl_native ioread32be ++#define dma_writel_native iowrite32be ++#else ++#define dma_readl_native readl ++#define dma_writel_native writel ++#endif ++ ++/* To access the registers in early stage of probe */ ++#define dma_read_byaddr(addr, name) \ ++ dma_readl_native((addr) + offsetof(struct fh_dma_regs, name)) ++ ++/* Bitfields in FH_PARAMS */ ++#define FH_PARAMS_NR_CHAN 8 /* number of channels */ ++#define FH_PARAMS_NR_MASTER 11 /* number of AHB masters */ ++#define FH_PARAMS_DATA_WIDTH(n) (15 + 2 * (n)) ++#define FH_PARAMS_DATA_WIDTH1 15 /* master 1 data width */ ++#define FH_PARAMS_DATA_WIDTH2 17 /* master 2 data width */ ++#define FH_PARAMS_DATA_WIDTH3 19 /* master 3 data width */ ++#define FH_PARAMS_DATA_WIDTH4 21 /* master 4 data width */ ++#define FH_PARAMS_EN 28 /* encoded parameters */ ++ ++/* Bitfields in FHC_PARAMS */ ++#define FHC_PARAMS_MBLK_EN 11 /* multi block transfer */ ++ ++/* Bitfields in CTL_LO */ ++#define FHC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ ++#define FHC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ ++#define FHC_CTLL_SRC_WIDTH(n) ((n)<<4) ++#define FHC_CTLL_DST_INC (0<<7) /* DAR update/not */ ++#define FHC_CTLL_DST_DEC (1<<7) ++#define FHC_CTLL_DST_FIX (2<<7) ++#define FHC_CTLL_SRC_INC (0<<9) /* SAR update/not */ ++#define FHC_CTLL_SRC_DEC (1<<9) ++#define FHC_CTLL_SRC_FIX (2<<9) ++#define FHC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ ++#define FHC_CTLL_SRC_MSIZE(n) ((n)<<14) ++#define FHC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ ++#define FHC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ ++#define FHC_CTLL_FC(n) ((n) << 20) ++#define FHC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ ++#define FHC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ ++#define FHC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ ++#define FHC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ ++/* plus 4 transfer types for peripheral-as-flow-controller */ ++#define FHC_CTLL_DMS(n) ((n)<<23) /* dst master select */ ++#define FHC_CTLL_SMS(n) ((n)<<25) /* src master select */ ++#define FHC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ ++#define FHC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ ++ ++/* Bitfields in CTL_HI */ ++#define FHC_CTLH_DONE 0x00001000 ++#define FHC_CTLH_BLOCK_TS_MASK 0x00000fff ++#define FHC_PROTCTL_MASK (7 << 2) ++#define FHC_PROTCTL(n) ((n) << 2) ++/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/fh_dmac.h> */ ++#define FHC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ ++#define FHC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ ++#define FHC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ ++#define FHC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ ++#define FHC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ ++#define FHC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ ++#define FHC_CFGL_MAX_BURST(x) ((x) << 20) ++#define FHC_CFGL_RELOAD_SAR (1 << 30) ++#define FHC_CFGL_RELOAD_DAR (1 << 31) ++ ++/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/fh_dmac.h> */ ++#define FHC_CFGH_DS_UPD_EN (1 << 5) ++#define FHC_CFGH_SS_UPD_EN (1 << 6) ++ ++/* Bitfields in SGR */ ++#define FHC_SGR_SGI(x) ((x) << 0) ++#define FHC_SGR_SGC(x) ((x) << 20) ++ ++/* Bitfields in DSR */ ++#define FHC_DSR_DSI(x) ((x) << 0) ++#define FHC_DSR_DSC(x) ((x) << 20) ++ ++/* Bitfields in CFG */ ++#define FH_CFG_DMA_EN (1 << 0) ++ ++#define FH_REGLEN 0x400 ++#define PROTCTL_ENABLE 0x55 ++#define MASTER_SEL_ENABLE 0x55 ++ ++enum fh_dmac_flags { ++ FH_DMA_IS_CYCLIC = 0, ++ FH_DMA_IS_SOFT_LLP = 1, ++}; ++ ++struct fh_dma_extra { ++ u32 sinc; ++ u32 dinc; ++ u32 protctl_flag; ++ u32 protctl_data; ++ u32 master_flag; ++ u32 src_master; ++ u32 dst_master; ++}; ++ ++struct fh_dma_chan { ++ struct dma_chan chan; ++ void __iomem *ch_regs; ++ u8 mask; ++ u8 priority; ++ enum dma_transfer_direction direction; ++ bool paused; ++ bool initialized; ++ ++ /* software emulation of the LLP transfers */ ++ struct list_head *tx_node_active; ++ ++ spinlock_t lock; ++ ++ /* these other elements are all protected by lock */ ++ unsigned long flags; ++ struct list_head active_list; ++ struct list_head queue; ++ struct list_head free_list; ++ u32 residue; ++ struct fh_cyclic_desc *cdesc; ++ ++ unsigned int descs_allocated; ++ ++ /* hardware configuration */ ++ unsigned int block_size; ++ bool nollp; ++ ++ /* custom slave configuration */ ++ unsigned int request_line; ++ unsigned char src_master; ++ unsigned char dst_master; ++ struct fh_dma_extra ext_para; ++ /* configuration passed via DMA_SLAVE_CONFIG */ ++ struct dma_slave_config dma_sconfig; ++}; ++ ++enum fh_dma_slave_increment { ++ FH_DMA_SLAVE_INC, ++ FH_DMA_SLAVE_DEC, ++ FH_DMA_SLAVE_FIX, ++}; ++ ++ ++static inline struct fh_dma_chan_regs __iomem * ++__fhc_regs(struct fh_dma_chan *fhc) ++{ ++ return fhc->ch_regs; ++} ++ ++#define channel_readl(fhc, name) \ ++ dma_readl_native(&(__fhc_regs(fhc)->name)) ++#define channel_writel(fhc, name, val) \ ++ dma_writel_native((val), &(__fhc_regs(fhc)->name)) ++ ++static inline struct fh_dma_chan *to_fh_dma_chan(struct dma_chan *chan) ++{ ++ return container_of(chan, struct fh_dma_chan, chan); ++} ++ ++struct fh_dma { ++ struct dma_device dma; ++ void __iomem *regs; ++ struct dma_pool *desc_pool; ++ struct tasklet_struct tasklet; ++ struct clk *clk; ++ ++ u8 all_chan_mask; ++ ++ /* hardware configuration */ ++ unsigned char nr_masters; ++ unsigned char data_width[4]; ++ ++ struct fh_dma_chan chan[0]; ++}; ++ ++static inline struct fh_dma_regs __iomem *__fh_regs(struct fh_dma *dw) ++{ ++ return dw->regs; ++} ++ ++#define dma_readl(dw, name) \ ++ dma_readl_native(&(__fh_regs(dw)->name)) ++#define dma_writel(dw, name, val) \ ++ dma_writel_native((val), &(__fh_regs(dw)->name)) ++ ++#define channel_set_bit(dw, reg, mask) \ ++ dma_writel(dw, reg, ((mask) << 8) | (mask)) ++#define channel_clear_bit(dw, reg, mask) \ ++ dma_writel(dw, reg, ((mask) << 8) | 0) ++ ++static inline struct fh_dma *to_fh_dma(struct dma_device *ddev) ++{ ++ return container_of(ddev, struct fh_dma, dma); ++} ++ ++/* LLI == Linked List Item; a.k.a. DMA block descriptor */ ++struct fh_lli { ++ /* values that are not changed by hardware */ ++ u32 sar; ++ u32 dar; ++ u32 llp; /* chain to next lli */ ++ u32 ctllo; ++ /* values that may get written back: */ ++ u32 ctlhi; ++ /* sstat and dstat can snapshot peripheral register state. ++ * silicon config may discard either or both... ++ */ ++ u32 sstat; ++ u32 dstat; ++}; ++ ++struct fh_desc { ++ /* FIRST values the hardware uses */ ++ struct fh_lli lli; ++ ++ /* THEN values for driver housekeeping */ ++ struct list_head desc_node; ++ struct list_head tx_list; ++ struct dma_async_tx_descriptor txd; ++ size_t len; ++ size_t total_len; ++}; ++ ++#define to_fh_desc(h) list_entry(h, struct fh_desc, desc_node) ++ ++static inline struct fh_desc * ++txd_to_fh_desc(struct dma_async_tx_descriptor *txd) ++{ ++ return container_of(txd, struct fh_desc, txd); ++} +diff --git a/arch/arm/mach-fh/include/mach/fh_efuse_plat.h b/arch/arm/mach-fh/include/mach/fh_efuse_plat.h +new file mode 100755 +index 00000000..df742bfa +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_efuse_plat.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright 2009 Texas Instruments. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef __ARCH_ARM_FH_EFUSE_PLAT_H ++#define __ARCH_ARM_FH_EFUSE_PLAT_H ++ ++#include <linux/io.h> ++#include <linux/scatterlist.h> ++ ++struct fh_efuse_platform_data { ++ u32 efuse_support_flag; ++}; ++#endif /* __ARCH_ARM_FH_EFUSE_PLAT_H */ +diff --git a/arch/arm/mach-fh/include/mach/fh_gmac.h b/arch/arm/mach-fh/include/mach/fh_gmac.h +new file mode 100644 +index 00000000..1ab649d0 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_gmac.h +@@ -0,0 +1,33 @@ ++#ifndef __FH_GMAC_PLATFORM_DATA ++#define __FH_GMAC_PLATFORM_DATA ++ ++#include <linux/platform_device.h> ++ ++enum { ++ gmac_phyt_reg_basic_ctrl = 0, ++ gmac_phyt_reg_basic_status = 1, ++ gmac_phyt_reg_phy_id1 = 2, ++ gmac_phyt_reg_phy_id2 = 3, ++ gmac_phyt_rtl8201_rmii_mode = 16, ++ gmac_phyt_ti83848_rmii_mode = 17, ++ gmac_phyt_rtl8201_power_saving = 24, ++ gmac_phyt_rtl8201_page_select = 31, ++ gmac_phyt_ip101g_page_select = 20 ++}; ++ ++enum { ++ gmac_speed_10m, ++ gmac_speed_100m ++}; ++ ++struct fh_gmac_platform_data { ++ int interface; ++ int phyid; ++ void (*early_init)(struct fh_gmac_platform_data *plat_data); ++ void (*plat_init)(struct fh_gmac_platform_data *plat_data); ++ void (*set_rmii_speed)(int speed); ++ void (*phy_reset)(void); ++}; ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/fh_i2s.h b/arch/arm/mach-fh/include/mach/fh_i2s.h +new file mode 100644 +index 00000000..e320c29f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_i2s.h +@@ -0,0 +1,13 @@ ++#ifndef __FH_I2S_PLATFORM_DATA ++#define __FH_I2S_PLATFORM_DATA ++ ++struct fh_i2s_platform_data { ++ int dma_capture_channel; ++ int dma_playback_channel; ++ int dma_master; ++ char *acodec_clk_name; ++ int (*clk_config)(int div_val); ++}; ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/fh_predefined.h b/arch/arm/mach-fh/include/mach/fh_predefined.h +new file mode 100644 +index 00000000..a5572f2f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_predefined.h +@@ -0,0 +1,40 @@ ++/* ++ * fh_predefined.h ++ * ++ * Created on: May 22, 2014 ++ * Author: duobao ++ */ ++ ++#ifndef FH_PREDEFINED_H_ ++#define FH_PREDEFINED_H_ ++ ++typedef unsigned char UINT8; ++typedef unsigned short UINT16; ++typedef unsigned int UINT32; ++typedef unsigned long long UINT64; ++ ++typedef char SINT8; ++typedef short SINT16; ++typedef int SINT32; ++typedef long long SINT64; ++#define FALSE (0) ++#define TRUE (!FALSE) ++#define reg_read(addr) (*((volatile UINT32 *)(addr))) ++#define reg_write(addr,value) (*(volatile UINT32 *)(addr)=(value)) ++ ++#define GET_REG(addr) reg_read(addr) ++#define SET_REG(addr,value) reg_write(addr,value) ++#define SET_REG_M(addr,value,mask) reg_write(addr,(reg_read(addr)&(~(mask)))|((value)&(mask))) ++#define SET_REG_B(addr,element,highbit,lowbit) SET_REG_M((addr),((element)<<(lowbit)),(((1<<((highbit)-(lowbit)+1))-1)<<(lowbit))) ++ ++#define GET_REG8(addr) (*((volatile UINT8 *)(addr))) ++#define SET_REG8(addr,value) (*(volatile UINT8 *)(addr)=(value)) ++ ++#define LD8(addr) (*((volatile u8 *)(addr))) ++#define ST8(addr,value) (*(volatile u8 *)(addr)=(value)) ++#define LD16(addr) (*((volatile u16 *)(addr))) ++#define ST16(addr,value) (*(volatile u16 *)(addr)=(value)) ++#define LD32(addr) (*((volatile u32 *)(addr))) ++#define ST32(addr,value) (*(volatile u32 *)(addr)=(value)) ++ ++#endif /* FH_PREDEFINED_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_rtc_v1.h b/arch/arm/mach-fh/include/mach/fh_rtc_v1.h +new file mode 100644 +index 00000000..594259eb +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_rtc_v1.h +@@ -0,0 +1,238 @@ ++/* ++ * rtc.h ++ * ++ * Created on: Aug 18, 2016 ++ * Author: fullhan ++ */ ++ ++#ifndef ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ ++#define ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ ++#include "fh_predefined.h" ++ ++/* ++ * Registers offset ++ */ ++#define FH_RTC_COUNTER 0x0 ++#define FH_RTC_OFFSET 0x4 ++#define FH_RTC_POWER_FAIL 0x8 ++#define FH_RTC_ALARM_COUNTER 0xC ++#define FH_RTC_INT_STAT 0x10 ++#define FH_RTC_INT_EN 0x14 ++#define FH_RTC_SYNC 0x18 ++#define FH_RTC_DEBUG 0x1C ++#define FH_RTC_USER_REG 0x20 ++ ++#define SEC_BIT_START 0 ++#define SEC_VAL_MASK 0x3f ++ ++#define MIN_BIT_START 6 ++#define MIN_VAL_MASK 0xfc0 ++ ++#define HOUR_BIT_START 12 ++#define HOUR_VAL_MASK 0x1f000 ++ ++#define DAY_BIT_START 17 ++#define DAY_VAL_MASK 0xfffe0000 ++ ++#define FH_RTC_ISR_SEC_POS 1<<0 ++#define FH_RTC_ISR_MIN_POS 1<<1 ++#define FH_RTC_ISR_HOUR_POS 1<<2 ++#define FH_RTC_ISR_DAY_POS 1<<3 ++#define FH_RTC_ISR_ALARM_POS 1<<4 ++#define FH_RTC_ISR_SEC_MASK 1<<27 ++#define FH_RTC_ISR_MIN_MASK 1<<28 ++#define FH_RTC_ISR_HOUR_MASK 1<<29 ++#define FH_RTC_ISR_DAY_MASK 1<<30 ++#define FH_RTC_ISR_ALARM_MASK 1<<31 ++ ++// input: val=fh_rtc_get_time(base_addr) ++#define FH_GET_RTC_SEC(val) ((val & SEC_VAL_MASK) >> SEC_BIT_START) ++#define FH_GET_RTC_MIN(val) ((val & MIN_VAL_MASK) >> MIN_BIT_START) ++#define FH_GET_RTC_HOUR(val) ((val & HOUR_VAL_MASK) >> HOUR_BIT_START) ++#define FH_GET_RTC_DAY(val) ((val & DAY_VAL_MASK) >> DAY_BIT_START) ++ ++#define ELAPSED_LEAP_YEARS(y) (((y -1)/4)-((y-1)/100)+((y+299)/400)-17) ++ ++#define FH_RTC_PROC_FILE "driver/fh_rtc" ++ ++struct fh_rtc_platform_data ++{ ++ u32 clock_in; ++ char *clk_name; ++ char *dev_name; ++ u32 base_year; ++ u32 base_month; ++ u32 base_day; ++ int sadc_channel; ++}; ++enum ++{ ++ init_done=1, ++ initing=0 ++ ++}; ++ ++/******************************************************************************* ++* Function Name : fh_rtc_interrupt_disabel ++* Description : disabale rtc interrupt ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_interrupt_disabel(base_addr) SET_REG(base_addr+REG_RTC_INT_EN,DISABLE) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_time ++* Description : get rtc current time ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_time(base_addr) GET_REG(base_addr+FH_RTC_COUNTER) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_set_time ++* Description : set rtc current time ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_set_time(base_addr,value) SET_REG(base_addr+FH_RTC_COUNTER,value) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_set_alarm_time ++* Description : set rtc alarm ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_set_alarm_time(base_addr,value) SET_REG(base_addr+FH_RTC_ALARM_COUNTER,value) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_alarm_time ++* Description : get alarm register ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_alarm_time(base_addr) GET_REG(base_addr+FH_RTC_ALARM_COUNTER) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_int_status ++* Description : get rtc current interrupt status ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_int_status(base_addr) GET_REG(base_addr+FH_RTC_INT_STAT) ++/******************************************************************************* ++* Function Name : fh_rtc_enable_interrupt ++* Description : enable rtc interrupt ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_enable_interrupt(base_addr,value) SET_REG(base_addr+FH_RTC_INT_EN,value|GET_REG(base_addr+FH_RTC_INT_EN)) ++/******************************************************************************* ++* Function Name : fh_rtc_disenable_interrupt ++* Description : disable interrupt ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_disenable_interrupt(base_addr,value) SET_REG(base_addr+FH_RTC_INT_EN,(~value)&GET_REG(base_addr+FH_RTC_INT_EN)) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_enabled_interrupt ++* Description : get rtc current interrupt enabled ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_enabled_interrupt(base_addr) GET_REG(base_addr+FH_RTC_INT_EN) ++/******************************************************************************* ++* Function Name : fh_rtc_set_mask_interrupt ++* Description : set rtc interrupt mask ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_set_mask_interrupt(base_addr,value) SET_REG(base_addr+FH_RTC_INT_EN,value|GET_REG(base_addr+FH_RTC_INT_EN)) ++/******************************************************************************* ++* Function Name : fh_rtc_clear_interrupt_status ++* Description : clear rtc interrupt status ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_clear_interrupt_status(base_addr,value) SET_REG(base_addr+FH_RTC_INT_STAT,(~value)&GET_REG(base_addr+FH_RTC_INT_STAT)) ++/******************************************************************************* ++* Function Name : fh_rtc_get_offset ++* Description : get rtc offset ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_offset(base_addr) GET_REG(base_addr+FH_RTC_OFFSET) ++/******************************************************************************* ++* Function Name : fh_rtc_get_power_fail ++* Description : get rtc power fail register ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_power_fail(base_addr) GET_REG(base_addr+FH_RTC_POWER_FAIL) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_sync ++* Description : get rtc sync register value ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_sync(base_addr) GET_REG(base_addr+FH_RTC_SYNC) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_set_sync ++* Description : set rtc sync register value ++* Input : rtc base addr,init_done/initing ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_set_sync(base_addr,value) SET_REG(base_addr+FH_RTC_SYNC,value) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_get_debug ++* Description : get rtc debug register value ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_get_debug(base_addr) GET_REG(base_addr+FH_RTC_DEBUG) ++ ++/******************************************************************************* ++* Function Name : fh_rtc_set_debug ++* Description : set rtc debug register value ++* Input : rtc base addr,x pclk ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define fh_rtc_set_debug(base_addr,value) SET_REG(base_addr+FH_RTC_DEBUG,value) ++#endif /* ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_rtc_v2.h b/arch/arm/mach-fh/include/mach/fh_rtc_v2.h +new file mode 100644 +index 00000000..5c4e805c +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_rtc_v2.h +@@ -0,0 +1,268 @@ ++/* ++ * rtc.h ++ * ++ * Created on: Aug 18, 2016 ++ * Author: fullhan ++ */ ++ ++#ifndef ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ ++#define ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ ++#include "fh_predefined.h" ++ ++/* ++ * Registers offset ++ */ ++#define FH_RTC_INT_STATUS 0x0 ++#define FH_RTC_INT_EN 0x4 ++#define FH_RTC_DEBUG0 0x8 ++#define FH_RTC_DEBUG1 0xC ++#define FH_RTC_DEBUG2 0x10 ++#define FH_RTC_CMD 0x14 ++#define FH_RTC_RD_DATA 0x18 ++#define FH_RTC_WR_DATA 0x1C ++ ++#define FH_RTC_CMD_COUNTER (0<<4) ++#define FH_RTC_CMD_OFFSET (1<<4) ++#define FH_RTC_CMD_ALARM_CFG (2<<4) ++#define FH_RTC_CMD_TEMP_INFO (0x3<<4) ++#define FH_RTC_CMD_TEMP_CFG (0x4<<4) ++#define FH_RTC_CMD_ANA_CFG (0x5<<4) ++#define FH_RTC_CMD_INT_STATUS (0x6<<4) ++#define FH_RTC_CMD_INT_EN (0x7<<4) ++#define FH_RTC_CMD_DEBUG (0x8<<4) ++#define FH_RTC_CMD_OFFSET_LUT (0x9<<4) ++ ++#define OFFSET_EN (1<<0) ++#define OFFSET_ATUTO (1<<1) ++#define OFFSET_IDX (1<<2) ++#define OFFSET_BK_EN (1<<8) ++#define OFFSET_BK_AUTO (1<<9) ++#define OFFSET_BK_IDX (1<<10) ++#define OFFSET_CURRENT (1<<16) ++#define LP_MODE (1<<31) ++ ++#define RTC_READ 1 ++#define RTC_WRITE 2 ++#define RTC_TEMP 3 ++#define FH_RTC_INT_STATUS_RX_CRC_ERR (1<<0) ++#define FH_RTC_INT_STATUS_RX_COM_ERR (1<<1) ++#define FH_RTC_INT_STATUS_RX_LEN_ERR (1<<2) ++#define FH_RTC_INT_STATUS_CNT_THL (1<<3) ++#define FH_RTC_INT_STATUS_CNT_THH (1<<4) ++#define FH_RTC_INT_STATUS_CORE_IDLE (1<<5) ++#define FH_RTC_INT_STATUS_CORE (1<<6) ++#define FH_RTC_INT_STATUS_WRAPPER_BUSY (1<<8) ++#define FH_RTC_INT_STATUS_CORE_BUSY (1<<16) ++ ++#define FH_RTC_INT_RX_CRC_ERR_EN (1<<0) ++#define FH_RTC_INT_RX_COM_ERR_EN (1<<1) ++#define FH_RTC_INT_RX_LEN_ERR_EN (1<<2) ++#define FH_RTC_INT_CNT_THL_ERR_EN (1<<3) ++#define FH_RTC_INT_CNT_THH_ERR_EN (1<<4) ++#define FH_RTC_INT_CORE_IDLE_ERR_EN (1<<5) ++#define FH_RTC_INT_CORE_INT_ERR_EN (1<<6) ++#define FH_RTC_INT_RX_CRC_ERR_MASK (1<<16) ++#define FH_RTC_INT_RX_COM_ERR_MASK (1<<17) ++#define FH_RTC_INT_RX_LEN_ERR_MASK (1<<18) ++#define FH_RTC_INT_CNT_THL_ERR_MASK (1<<19) ++#define FH_RTC_INT_CNT_THH_ERR_MASK (1<<20) ++#define FH_RTC_INT_CORE_IDLE_ERR_MASK (1<<21) ++#define FH_RTC_INT_CORE_INT_ERR_MASK (1<<22) ++#define FH_RTC_INT_CORE_INT_ERR_MASK_COV 0xffbfffff ++#define FH_RTC_INT_CORE_INT_STATUS_COV 0xffffff3f ++#define FH_RTC_INT_CORE_INT_ALL_COV 0xffffffff ++ ++#define FH_RTC_CORE_INT_EN_SEC_INT (0x1<<0) ++#define FH_RTC_CORE_INT_EN_MIN_INT (0x1<<1) ++#define FH_RTC_CORE_INT_EN_HOU_INT (0x1<<2) ++#define FH_RTC_CORE_INT_EN_DAY_INT (0x1<<3) ++#define FH_RTC_CORE_INT_EN_ALM_INT (0x1<<4) ++#define FH_RTC_CORE_INT_EN_POW_INT (0x1<<5) ++ ++ ++#define FH_RTC_CORE_INT_EN_SEC_MAS (0x1<<16) ++#define FH_RTC_CORE_INT_EN_MIN_MAS (0x1<<17) ++#define FH_RTC_CORE_INT_EN_HOU_MAS (0x1<<18) ++#define FH_RTC_CORE_INT_EN_DAY_MAS (0x1<<19) ++#define FH_RTC_CORE_INT_EN_ALM_MAS (0x1<<20) ++#define FH_RTC_CORE_INT_EN_POE_MAS (0x1<<21) ++ ++#define FH_RTC_IOCTL_MEM_BASE 'A' ++#define GET_TSENSOR_DATA _IOWR(FH_RTC_IOCTL_MEM_BASE, 0, int) ++#define GET_CURRENT_OFFSET_DATA _IOWR(FH_RTC_IOCTL_MEM_BASE, 1, int) ++#define GET_CURRENT_OFFSET_IDX _IOWR(FH_RTC_IOCTL_MEM_BASE, 2, int) ++#define RTC_GET_LUT _IOWR(FH_RTC_IOCTL_MEM_BASE, 3, int) ++#define RTC_SET_LUT _IOWR(FH_RTC_IOCTL_MEM_BASE, 4, int) ++#define GET_REG_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 5, int) ++#define SET_REG_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 6, int) ++#define GET_TEMP_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 7, int) ++#define GET_WRAPPER_REG _IOWR(FH_RTC_IOCTL_MEM_BASE, 8, int) ++#define SET_WRAPPER_REG _IOWR(FH_RTC_IOCTL_MEM_BASE, 9, int) ++#define SET_REG_VALUE_SINGLE _IOWR(FH_RTC_IOCTL_MEM_BASE, 10, int) ++ ++#define SEC_BIT_START 0 ++#define SEC_VAL_MASK 0x3f ++ ++#define MIN_BIT_START 6 ++#define MIN_VAL_MASK 0xfc0 ++ ++#define HOUR_BIT_START 12 ++#define HOUR_VAL_MASK 0x1f000 ++ ++#define DAY_BIT_START 17 ++#define DAY_VAL_MASK 0xfffe0000 ++ ++#define FH_RTC_ISR_SEC_POS (1<<0) ++#define FH_RTC_ISR_MIN_POS (1<<1) ++#define FH_RTC_ISR_HOUR_POS (1<<2) ++#define FH_RTC_ISR_DAY_POS (1<<3) ++#define FH_RTC_ISR_ALARM_POS (1<<4) ++#define FH_RTC_ISR_POWERFAIL_POS (1<<5) ++#define FH_RTC_ISR_RX_CRC_ERR_INT (1<<6) ++#define FH_RTC_ISR_RX_COM_ERR_INT (1<<7) ++#define FH_RTC_LEN_ERR_INT (1<<8) ++ ++/* input: val=fh_rtc_get_time(base_addr)*/ ++#define FH_GET_RTC_SEC(val) ((val & SEC_VAL_MASK) >> SEC_BIT_START) ++#define FH_GET_RTC_MIN(val) ((val & MIN_VAL_MASK) >> MIN_BIT_START) ++#define FH_GET_RTC_HOUR(val) ((val & HOUR_VAL_MASK) >> HOUR_BIT_START) ++#define FH_GET_RTC_DAY(val) ((val & DAY_VAL_MASK) >> DAY_BIT_START) ++ ++#define ELAPSED_LEAP_YEARS(y) (((y-1)/4)-((y-1)/100)+((y+299)/400)-17) ++#define OUT_TEMP(y) (y/4096*235-73) ++#define FH_RTC_PROC_FILE "fh_zy_rtc" ++ ++struct fh_rtc_platform_data { ++ u32 clock_in; ++ char *clk_name; ++ char *dev_name; ++ u32 base_year; ++ u32 base_month; ++ u32 base_day; ++ int sadc_channel; ++}; ++enum { ++ init_done = 1, ++ initing = 0 ++ ++}; ++ ++/**************************************************** ++* Function Name : fh_rtc_interrupt_disabel ++* Description : disabale rtc interrupt ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ ****************************************************/ ++#define fh_rtc_interrupt_disabel(base_addr) \ ++SET_REG(base_addr+REG_RTC_INT_EN, DISABLE) ++ ++/****************************************************** ++* Function Name : fh_rtc_get_int_status ++* Description : get rtc current interrupt status ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ ******************************************************/ ++#define fh_rtc_get_int_status(base_addr) \ ++GET_REG(base_addr+FH_RTC_INT_STAT) ++/****************************************************** ++* Function Name : fh_rtc_enable_interrupt ++* Description : enable rtc interrupt ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ ******************************************************/ ++#define fh_rtc_enable_interrupt(base_addr, value) \ ++SET_REG(base_addr+FH_RTC_INT_EN, \ ++value|GET_REG(base_addr+FH_RTC_INT_EN)) ++ ++ ++/******************************************************* ++* Function Name : fh_rtc_get_enabled_interrupt ++* Description : get rtc current interrupt enabled ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ ******************************************************/ ++#define fh_rtc_get_enabled_interrupt(base_addr) \ ++GET_REG(base_addr+FH_RTC_INT_EN) ++/******************************************************** ++* Function Name : fh_rtc_set_mask_interrupt ++* Description : set rtc interrupt mask ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************/ ++#define fh_rtc_set_mask_interrupt(base_addr, value) \ ++SET_REG(base_addr+FH_RTC_INT_EN, value|GET_REG(base_addr+FH_RTC_INT_EN)) ++/******************************************************** ++* Function Name : fh_rtc_get_offset ++* Description : get rtc offset ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *******************************************************/ ++#define fh_rtc_get_offset(base_addr) \ ++GET_REG(base_addr+FH_RTC_OFFSET) ++/******************************************************** ++* Function Name : fh_rtc_get_power_fail ++* Description : get rtc power fail register ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ ******************************************************/ ++#define fh_rtc_get_power_fail(base_addr) \ ++GET_REG(base_addr+FH_RTC_POWER_FAIL) ++ ++/******************************************************** ++* Function Name : fh_rtc_get_sync ++* Description : get rtc sync register value ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ *********************************************************/ ++#define fh_rtc_get_sync(base_addr) \ ++GET_REG(base_addr+FH_RTC_SYNC) ++ ++/********************************************************** ++* Function Name : fh_rtc_set_sync ++* Description : set rtc sync register value ++* Input : rtc base addr,init_done/initing ++* Output : None ++* Return : None ++* ++************************************************************/ ++#define fh_rtc_set_sync(base_addr, value) \ ++SET_REG(base_addr+FH_RTC_SYNC, value) ++ ++/*********************************************************** ++* Function Name : fh_rtc_get_debug ++* Description : get rtc debug register value ++* Input : rtc base addr ++* Output : None ++* Return : None ++* ++ **********************************************************/ ++#define fh_rtc_get_debug(base_addr) \ ++GET_REG(base_addr+FH_RTC_DEBUG) ++ ++/************************************************************ ++* Function Name : fh_rtc_set_debug ++* Description : set rtc debug register value ++* Input : rtc base addr,x pclk ++* Output : None ++* Return : None ++* ++ ***********************************************************/ ++#define fh_rtc_set_debug(base_addr, value) \ ++SET_REG(base_addr+FH_RTC_DEBUG, value) ++#endif /* ARCH_ARM_MACH_FH_INCLUDE_MACH_RTC_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_sadc.h b/arch/arm/mach-fh/include/mach/fh_sadc.h +new file mode 100644 +index 00000000..db6d11ce +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_sadc.h +@@ -0,0 +1,108 @@ ++/* ++ * fh_sadc.h ++ * ++ * Created on: Mar 13, 2015 ++ * Author: duobao ++ */ ++ ++#ifndef FH_SADC_H_ ++#define FH_SADC_H_ ++ ++#include <linux/io.h> ++#include <linux/scatterlist.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/scatterlist.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/workqueue.h> ++#include <linux/bug.h> ++#include <linux/completion.h> ++#include <linux/miscdevice.h> ++#include <linux/fs.h> ++ ++/**************************************************************************** ++ * #define section ++ * add constant #define here if any ++ ***************************************************************************/ ++#define FH_SADC_PROC_FILE "driver/sadc" ++#define MAX_CHANNEL_NO (8) ++#define LOOP_MODE (0x55) ++#define ISR_MODE (0xAA) ++ ++ ++#define SADC_TIMEOUT 0x55 ++/**************************************************************************** ++ * ADT section ++ * add Abstract Data Type definition here ++ ***************************************************************************/ ++ ++struct wrap_sadc_reg { ++#ifdef CONFIG_FH_SADC_V21 ++ u32 sadc_model; ++#endif ++ u32 sadc_cmd; ++ u32 sadc_control; ++#ifdef CONFIG_FH_SADC_V21 ++ u32 sadc_scan_en; ++ u32 sadc_chn_cfg; ++ u32 sadc_chn_cfg1; ++ u32 sadc_glitch_cfg; ++ u32 sadc_continuous_time; ++ u32 sadc_glitch_time; ++#endif ++ u32 sadc_ier; ++ u32 sadc_int_status; ++ u32 sadc_dout0; ++ u32 sadc_dout1; ++ u32 sadc_dout2; ++ u32 sadc_dout3; ++#ifdef CONFIG_FH_SADC_V21 ++ u32 sadc_dout0_all; ++ u32 sadc_dout1_all; ++ u32 sadc_dout2_all; ++ u32 sadc_dout3_all; ++#endif ++ u32 sadc_debuge0; ++ u32 sadc_status; ++ u32 sadc_cnt; ++ u32 sadc_timeout; ++ u32 sadc_status2; ++#ifdef CONFIG_FH_SADC_V22 ++ u32 sadc_hit_value0; ++ u32 sadc_hit_value1; ++ u32 sadc_hit_value2; ++ u32 sadc_hit_value3; ++ u32 sadc_hit_cfg; ++ u32 sadc_hit_data0; ++ u32 sadc_hit_data1; ++ u32 sadc_hit_data2; ++ u32 sadc_hit_data3; ++#endif ++}; ++ ++struct wrap_sadc_obj { ++ void *regs; ++ u32 irq_no; ++ u32 active_channel_no; ++ u32 active_channel_status; ++ uint16_t channel_data[MAX_CHANNEL_NO]; ++ u32 error_rec; ++ u32 en_isr; ++ u32 sample_mode; ++ spinlock_t lock; ++ struct mutex sadc_lock; ++ struct completion done; ++ struct proc_dir_entry *proc_file; ++#ifdef CONFIG_FH_SADC_V21 ++ wait_queue_head_t readqueue; ++#endif ++}; ++ ++long fh_sadc_get_value(int channel); ++ ++ ++#endif /* fh_SADC_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_simple_timer.h b/arch/arm/mach-fh/include/mach/fh_simple_timer.h +new file mode 100644 +index 00000000..b6b3729e +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_simple_timer.h +@@ -0,0 +1,80 @@ ++/* ++ * fh_simple_timer.h ++ * ++ * Created on: Jan 22, 2017 ++ * Author: duobao ++ */ ++ ++#ifndef FH_SIMPLE_TIMER_H_ ++#define FH_SIMPLE_TIMER_H_ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/list.h> ++#include <linux/time.h> ++#include <linux/ktime.h> ++#include <linux/timerqueue.h> ++#include <mach/pmu.h> ++#include <mach/timex.h> ++#include <mach/io.h> ++#include <mach/fh_predefined.h> ++ ++ ++static inline unsigned int timern_base(int n) ++{ ++ unsigned int base = 0; ++ switch (n) { ++ case 0: ++ default: ++ base = TIMER_REG_BASE; ++ break; ++ case 1: ++ base = TIMER_REG_BASE + 0x14; ++ break; ++ case 2: ++ base = TIMER_REG_BASE + 0x28; ++ break; ++ case 3: ++ base = TIMER_REG_BASE + 0x3c; ++ break; ++ } ++ return base; ++} ++ ++#define TIMERN_REG_BASE(n) (timern_base(n)) ++ ++#define REG_TIMER_LOADCNT(n) (timern_base(n) + 0x00) ++#define REG_TIMER_CUR_VAL(n) (timern_base(n) + 0x04) ++#define REG_TIMER_CTRL_REG(n) (timern_base(n) + 0x08) ++#define REG_TIMER_EOI_REG(n) (timern_base(n) + 0x0C) ++#define REG_TIMER_INTSTATUS(n) (timern_base(n) + 0x10) ++ ++#define REG_TIMERS_INTSTATUS (TIMER_REG_BASE + 0xa0) ++ ++ ++enum simple_timer_state { ++ SIMPLE_TIMER_STOP, ++ SIMPLE_TIMER_START, ++ SIMPLE_TIMER_ERROR, ++}; ++ ++struct fh_simple_timer ++{ ++ struct timerqueue_node node; ++ ktime_t it_interval; /* timer period */ ++ ktime_t it_value; /* timer expiration */ ++ ktime_t it_delay; ++ void (*function) (void *); ++ void *param; ++}; ++ ++ ++int fh_simple_timer_interrupt(void); ++int fh_simple_timer_create(struct fh_simple_timer *tim); ++int fh_timer_start(void); ++int fh_simple_timer_init(void); ++int fh_simple_timer_periodic_start(struct fh_simple_timer *tim); ++int fh_simple_timer_periodic_stop(void); ++ ++#endif /* FH_SIMPLE_TIMER_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/fh_usb.h b/arch/arm/mach-fh/include/mach/fh_usb.h +new file mode 100644 +index 00000000..09356af4 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_usb.h +@@ -0,0 +1,18 @@ ++#ifndef __FH_USB ++#define __FH_USB ++ ++#include <linux/platform_device.h> ++ ++ ++struct fh_usb_platform_data { ++ ++ void (*utmi_rst)(void); ++ void (*phy_rst)(void); ++ void (*hcd_resume)(void); ++ void (*power_on)(void); ++ unsigned int grxfsiz_pwron_val; ++ unsigned int gnptxfsiz_pwron_val; ++}; ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/fh_wdt.h b/arch/arm/mach-fh/include/mach/fh_wdt.h +new file mode 100644 +index 00000000..457180f9 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fh_wdt.h +@@ -0,0 +1,32 @@ ++#ifndef __FH_WDT_PLATFORM_DATA ++#define __FH_WDT_PLATFORM_DATA ++ ++#include <linux/platform_device.h> ++ ++struct fh_wdt_platform_reset { ++ unsigned int spi0_cs_pin; ++ unsigned int spi0_rst_bit; ++ unsigned int sd0_rst_bit; ++ unsigned int uart0_rst_bit; ++}; ++ ++struct fh_wdt_platform_data { ++ void (*resume)(void); ++ void (*pause)(void); ++ irqreturn_t (*intr)(void *pri); ++ struct fh_wdt_platform_reset *plat_info; ++}; ++ ++struct fh_wdt_t { ++ spinlock_t lock; ++ void __iomem *regs; ++ struct clk *clk; ++ unsigned long in_use; ++ unsigned long next_heartbeat; ++ struct timer_list timer; ++ int expect_close; ++ struct fh_wdt_platform_data *plat_data; ++}; ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/fhmci.h b/arch/arm/mach-fh/include/mach/fhmci.h +new file mode 100644 +index 00000000..b60ad26e +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/fhmci.h +@@ -0,0 +1,178 @@ ++#ifndef _FH_MCI_H_ ++#define _FH_MCI_H_ ++ ++extern int trace_level; ++#define FHMCI_TRACE_LEVEL 5 ++/* ++ 0 - all message ++ 1 - dump all register read/write ++ 2 - flow trace ++ 3 - timeout err and protocol err ++ */ ++ ++#define FHMCI_TRACE_FMT KERN_INFO ++#define ID_SD0 0 ++#define ID_SD1 1 ++ ++#define POWER_ON 1 ++#define POWER_OFF 0 ++ ++#define CARD_UNPLUGED 1 ++#define CARD_PLUGED 0 ++ ++#define ENABLE 1 ++#define DISABLE 0 ++ ++#define FH_MCI_DETECT_TIMEOUT (HZ/4) ++ ++#define FH_MCI_REQUEST_TIMEOUT (5 * HZ) ++ ++#define MAX_RETRY_COUNT 100 ++#define MAX_MCI_HOST (2) /* max num of host on soc */ ++ ++#define fhmci_trace(level, msg...) do { \ ++ if ((level) >= trace_level) { \ ++ printk(FHMCI_TRACE_FMT "%s:%d: ", __func__, __LINE__); \ ++ printk(msg); \ ++ printk("\n"); \ ++ } \ ++} while (0) ++ ++#define fhmci_assert(cond) do { \ ++ if (!(cond)) {\ ++ printk(KERN_ERR "Assert:fhmci:%s:%d\n", \ ++ __func__, \ ++ __LINE__); \ ++ BUG(); \ ++ } \ ++} while (0) ++ ++#define fhmci_error(s...) do { \ ++ printk(KERN_ERR "fhmci:%s:%d: ", __func__, __LINE__); \ ++ printk(s); \ ++ printk("\n"); \ ++} while (0) ++ ++#define fhmci_readl(addr) ({unsigned int reg = readl((unsigned int)addr); \ ++ fhmci_trace(1, "readl(0x%04X) = 0x%08X", (unsigned int)addr, reg); \ ++ reg; }) ++ ++#define fhmci_writel(v, addr) do { \ ++ writel(v, (unsigned int)addr); \ ++ fhmci_trace(1, "writel(0x%04X) = 0x%08X",\ ++ (unsigned int)addr, (unsigned int)(v)); \ ++} while (0) ++ ++ ++struct fhmci_des { ++ unsigned long idmac_des_ctrl; ++ unsigned long idmac_des_buf_size; ++ unsigned long idmac_des_buf_addr; ++ unsigned long idmac_des_next_addr; ++}; ++ ++struct fhmci_host { ++ struct mmc_host *mmc; ++ spinlock_t lock; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ void __iomem *base; ++ unsigned int card_status; ++ struct scatterlist *dma_sg; ++ unsigned int dma_sg_num; ++ unsigned int dma_alloc_size; ++ unsigned int dma_dir; ++ dma_addr_t dma_paddr; ++ unsigned int *dma_vaddr; ++ struct timer_list timer; ++ unsigned int irq; ++ unsigned int irq_status; ++ unsigned int is_tuning; ++ wait_queue_head_t intr_wait; ++ unsigned long pending_events; ++ unsigned int id; ++ struct fh_mci_board *pdata; ++ unsigned int (*get_cd)(struct fhmci_host *host); ++ unsigned int (*get_ro)(struct fhmci_host *host); ++#define FHMCI_PEND_DTO_b (0) ++#define FHMCI_PEND_DTO_m (1 << FHMCI_PEND_DTO_b) ++}; ++ ++/* Board platform data */ ++struct fh_mci_board { ++ unsigned int num_slots; ++ ++ unsigned int quirks; /* Workaround / Quirk flags */ ++ unsigned int bus_hz; /* Bus speed */ ++ ++ unsigned int caps; /* Capabilities */ ++ ++ /* delay in mS before detecting cards after interrupt */ ++ unsigned int detect_delay_ms; ++ ++ int (*init)(unsigned int slot_id,void* irq_handler_t , void *); ++ unsigned int (*get_ro)(struct fhmci_host *host); ++ unsigned int (*get_cd)(struct fhmci_host *host); ++ int (*get_ocr)(unsigned int slot_id); ++ int (*get_bus_wd)(unsigned int slot_id); ++ /* ++ * Enable power to selected slot and set voltage to desired level. ++ * Voltage levels are specified using MMC_VDD_xxx defines defined ++ * in linux/mmc/host.h file. ++ */ ++ void (*setpower)(unsigned int slot_id, unsigned int volt); ++ void (*exit)(unsigned int slot_id); ++ void (*select_slot)(unsigned int slot_id); ++ ++ struct dw_mci_dma_ops *dma_ops; ++ struct dma_pdata *data; ++ struct block_settings *blk_settings; ++ int fifo_depth; ++}; ++ ++union cmd_arg_s { ++ unsigned int cmd_arg; ++ struct cmd_bits_arg { ++ unsigned int cmd_index:6; ++ unsigned int response_expect:1; ++ unsigned int response_length:1; ++ unsigned int check_response_crc:1; ++ unsigned int data_transfer_expected:1; ++ unsigned int read_write:1; ++ unsigned int transfer_mode:1; ++ unsigned int send_auto_stop:1; ++ unsigned int wait_prvdata_complete:1; ++ unsigned int stop_abort_cmd:1; ++ unsigned int send_initialization:1; ++ unsigned int card_number:5; ++ unsigned int update_clk_reg_only:1; /* bit 21 */ ++ unsigned int read_ceata_device:1; ++ unsigned int ccs_expected:1; ++ unsigned int enable_boot:1; ++ unsigned int expect_boot_ack:1; ++ unsigned int disable_boot:1; ++ unsigned int boot_mode:1; ++ unsigned int volt_switch:1; ++ unsigned int use_hold_reg:1; ++ unsigned int reserved:1; ++ unsigned int start_cmd:1; /* HSB */ ++ } bits; ++}; ++ ++struct mmc_ctrl { ++ unsigned int slot_idx; /*0: mmc0; 1: mmc1*/ ++ unsigned int mmc_ctrl_state; /*0: enable mmc_rescan; 1: disable mmc_rescan*/ ++}; ++ ++enum mmc_ctrl_state { ++ RESCAN_ENABLE = 0, ++ RESCAN_DISABLE ++}; ++ ++struct platform_device *get_mci_device(unsigned int index); ++int storage_dev_set_mmc_rescan(struct mmc_ctrl *m_ctrl); ++int read_mci_ctrl_states(int id_mmc_sd); ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/gpio.h b/arch/arm/mach-fh/include/mach/gpio.h +new file mode 100644 +index 00000000..781093dd +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/gpio.h +@@ -0,0 +1,259 @@ ++/* ++ * TI DaVinci GPIO Support ++ * ++ * Copyright (c) 2006 David Brownell ++ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef __FH_GPIO_H ++#define __FH_GPIO_H ++ ++#include <linux/io.h> ++#include <linux/spinlock.h> ++ ++#include <asm-generic/gpio.h> ++ ++#include <mach/irqs.h> ++#include <mach/fh_predefined.h> ++ ++/* ++ * GPIO Direction ++ */ ++#define GPIO_DIR_INPUT 0 ++#define GPIO_DIR_OUTPUT 1 ++ ++/* ++ * GPIO interrupt type ++ */ ++#define GPIO_INT_TYPE_LEVEL 0 ++#define GPIO_INT_TYPE_EDGE 1 ++ ++/* ++ * GPIO interrupt polarity ++ */ ++#define GPIO_INT_POL_LOW 0 ++#define GPIO_INT_POL_HIGH 1 ++ ++#define OFFSET_GPIO_SWPORTA_DR (0x0000) ++#define OFFSET_GPIO_SWPORTA_DDR (0x0004) ++#define OFFSET_GPIO_PORTA_CTL (0x0008) ++#define OFFSET_GPIO_SWPORTB_DR (0x000C) ++#define OFFSET_GPIO_SWPORTB_DDR (0x0010) ++#define OFFSET_GPIO_PORTB_CTL (0x0014) ++#define OFFSET_GPIO_INTEN (0x0030) ++#define OFFSET_GPIO_INTMASK (0x0034) ++#define OFFSET_GPIO_INTTYPE_LEVEL (0x0038) ++#define OFFSET_GPIO_INT_POLARITY (0x003C) ++#define OFFSET_GPIO_INTSTATUS (0x0040) ++#define OFFSET_GPIO_RAWINTSTATUS (0x0044) ++#define OFFSET_GPIO_DEBOUNCE (0x0048) ++#define OFFSET_GPIO_PORTA_EOI (0x004C) ++#define OFFSET_GPIO_EXT_PORTA (0x0050) ++#define OFFSET_GPIO_EXT_PORTB (0x0054) ++ ++static inline void FH_GPIO_SetValue(unsigned int base, int bit, int val) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_SWPORTA_DR); ++ reg = val ? (reg | (1 << bit)) : (reg & ~(1 << bit)); ++ SET_REG(base + OFFSET_GPIO_SWPORTA_DR, reg); ++} ++ ++static inline int FH_GPIO_GetValue(unsigned int base, int bit) ++{ ++ return (GET_REG(base + OFFSET_GPIO_EXT_PORTA) >> bit) & 0x1; ++} ++ ++static inline void FH_GPIO_SetDirection(unsigned int base, int bit, int dir) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_SWPORTA_DDR); ++ reg = dir ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_SWPORTA_DDR, reg); ++} ++ ++static inline int FH_GPIO_GetDirection(unsigned int base, int bit) ++{ ++ return (GET_REG(base + OFFSET_GPIO_SWPORTA_DDR) >> bit) & 0x1; ++} ++ ++static inline void FH_GPIOB_SetValue(unsigned int base, int bit, int val) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_SWPORTB_DR); ++ reg = val ? (reg | (1 << bit)) : (reg & ~(1 << bit)); ++ SET_REG(base + OFFSET_GPIO_SWPORTB_DR, reg); ++} ++ ++static inline int FH_GPIOB_GetValue(unsigned int base, int bit) ++{ ++ return (GET_REG(base + OFFSET_GPIO_EXT_PORTB) >> bit) & 0x1; ++} ++ ++static inline void FH_GPIOB_SetDirection(unsigned int base, int bit, int dir) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_SWPORTB_DDR); ++ reg = dir ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_SWPORTB_DDR, reg); ++} ++ ++static inline int FH_GPIOB_GetDirection(unsigned int base, int bit) ++{ ++ return (GET_REG(base + OFFSET_GPIO_SWPORTB_DDR) >> bit) & 0x1; ++} ++ ++static inline void FH_GPIO_EnableDebounce(unsigned int base, int bit, int bool) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_DEBOUNCE); ++ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_DEBOUNCE, reg); ++} ++ ++static inline void FH_GPIO_SetInterruptType(unsigned int base, int bit, ++ int type) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_INTTYPE_LEVEL); ++ reg = type ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_INTTYPE_LEVEL, reg); ++} ++ ++static inline void FH_GPIO_SetInterruptPolarity(unsigned int base, int bit, ++ int pol) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_INT_POLARITY); ++ reg = pol ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_INT_POLARITY, reg); ++} ++ ++static inline void FH_GPIO_EnableInterruptMask(unsigned int base, int bit, ++ int bool) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_INTMASK); ++ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_INTMASK, reg); ++} ++ ++static inline void FH_GPIO_EnableInterrupt(unsigned int base, int bit, int bool) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_INTEN); ++ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit); ++ SET_REG(base + OFFSET_GPIO_INTEN, reg); ++} ++ ++static inline void FH_GPIO_SetEnableInterrupts(unsigned int base, ++ unsigned int val) ++{ ++ SET_REG(base + OFFSET_GPIO_INTEN, val); ++} ++ ++static inline unsigned int FH_GPIO_GetEnableInterrupts(unsigned int base) ++{ ++ return GET_REG(base + OFFSET_GPIO_INTEN); ++} ++ ++static inline unsigned int FH_GPIO_GetInterruptStatus(unsigned int base) ++{ ++ return GET_REG(base + OFFSET_GPIO_INTSTATUS); ++} ++ ++static inline void FH_GPIO_ClearInterrupt(unsigned int base, int bit) ++{ ++ unsigned int reg; ++ ++ reg = GET_REG(base + OFFSET_GPIO_PORTA_EOI); ++ reg |= (1 << bit); ++ SET_REG(base + OFFSET_GPIO_PORTA_EOI, reg); ++} ++ ++#define GPIO_NAME "FH_GPIO" ++ ++ ++struct gpio_irq_info { ++ int irq_gpio; ++ int irq_line; ++ int irq_type; ++ int irq_gpio_val; ++ int irq_gpio_mode; ++}; ++ ++struct fh_gpio_chip { ++ struct gpio_chip chip; ++ void __iomem *base; ++ ++ struct platform_device *pdev; ++ int irq; ++ spinlock_t lock; ++ ++ u32 gpio_wakeups; ++ u32 gpio_backups; ++}; ++ ++/* ++ * The get/set/clear functions will inline when called with constant ++ * parameters referencing built-in GPIOs, for low-overhead bitbanging. ++ * ++ * gpio_set_value() will inline only on traditional Davinci style controllers ++ * with distinct set/clear registers. ++ * ++ * Otherwise, calls with variable parameters or referencing external ++ * GPIOs (e.g. on GPIO expander chips) use outlined functions. ++ */ ++static inline void gpio_set_value(unsigned gpio, int value) ++{ ++ __gpio_set_value(gpio, value); ++} ++ ++/* Returns zero or nonzero; works for gpios configured as inputs OR ++ * as outputs, at least for built-in GPIOs. ++ * ++ * NOTE: for built-in GPIOs, changes in reported values are synchronized ++ * to the GPIO clock. This is easily seen after calling gpio_set_value() ++ * and then immediately gpio_get_value(), where the gpio_get_value() will ++ * return the old value until the GPIO clock ticks and the new value gets ++ * latched. ++ */ ++static inline int gpio_get_value(unsigned gpio) ++{ ++ return __gpio_get_value(gpio); ++} ++ ++static inline int gpio_cansleep(unsigned gpio) ++{ ++ return 0; ++} ++ ++static inline int gpio_to_irq(unsigned gpio) ++{ ++ return __gpio_to_irq(gpio); ++} ++ ++static inline int irq_to_gpio(unsigned irq) ++{ ++ return 0; ++} ++ ++void fh_gpio_irq_suspend(void); ++void fh_gpio_irq_resume(void); ++ ++#endif ++ +diff --git a/arch/arm/mach-fh/include/mach/hardware.h b/arch/arm/mach-fh/include/mach/hardware.h +new file mode 100644 +index 00000000..af93e037 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/hardware.h +@@ -0,0 +1,18 @@ ++/* ++* Copyright (c) 2010 Shanghai Fullhan Microelectronics Co., Ltd. ++* All Rights Reserved. Confidential. ++* ++*This program is free software; you can redistribute it and/or ++* modify it under the terms of the GNU General Public License as ++* published by the Free Software Foundation version 2. ++* ++* This program is distributed "as is" WITHOUT ANY WARRANTY of any ++* kind, whether express or implied; without even the implied warranty ++* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++*/ ++ ++#ifndef __ASM_ARCH_HARDWARE_H ++#define __ASM_ARCH_HARDWARE_H ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +diff --git a/arch/arm/mach-fh/include/mach/i2c.h b/arch/arm/mach-fh/include/mach/i2c.h +new file mode 100644 +index 00000000..8bf70b6e +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/i2c.h +@@ -0,0 +1,339 @@ ++/* ++* Copyright (c) 2010 Shanghai Fullhan Microelectronics Co., Ltd. ++* All Rights Reserved. Confidential. ++* ++*This program is free software; you can redistribute it and/or ++* modify it under the terms of the GNU General Public License as ++* published by the Free Software Foundation version 2. ++* ++* This program is distributed "as is" WITHOUT ANY WARRANTY of any ++* kind, whether express or implied; without even the implied warranty ++* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++*/ ++ ++#ifndef __ASM_ARCH_I2C_H ++#define __ASM_ARCH_I2C_H ++#include "fh_predefined.h" ++ ++//I2C ++#define REG_I2C_CON (0x0000) ++#define REG_I2C_TAR (0x0004) ++#define REG_I2C_SAR (0x0008) ++#define REG_I2C_HS_MADDR (0x000C) ++#define REG_I2C_DATA_CMD (0x0010) ++#define REG_I2C_SS_SCL_HCNT (0x0014) ++#define REG_I2C_SS_SCL_LCNT (0x0018) ++#define REG_I2C_FS_SCL_HCNT (0x001C) ++#define REG_I2C_FS_SCL_LCNT (0x0020) ++#define REG_I2C_HS_SCL_HCNT (0x0024) ++#define REG_I2C_HS_SCL_LCNT (0x0028) ++#define REG_I2C_INTR_STAT (0x002c) ++#define REG_I2C_INTR_MASK (0x0030) ++#define REG_I2C_RAW_INTR_STAT (0x0034) ++#define REG_I2C_RX_TL (0x0038) ++#define REG_I2C_TX_TL (0x003c) ++#define REG_I2C_CLR_INTR (0x0040) ++#define REG_I2C_ENABLE (0x006c) ++#define REG_I2C_STATUS (0x0070) ++#define REG_I2C_TXFLR (0x0074) ++#define REG_I2C_RXFLR (0x0078) ++#define REG_I2C_DMA_CR (0x0088) ++#define REG_I2C_DMA_TDLR (0x008c) ++#define REG_I2C_DMA_RDLR (0x0090) ++ ++#define DW_IC_INTR_NONE 0x0 ++ ++ ++enum BUS_STATUS { ++ I2C_BUSY, ++ I2C_IDLE ++}; ++enum RESULT { ++ SUCCESS, ++ FAILURE ++}; ++enum ENABLE_SET { ++ DISABLE, ++ ENABLE ++}; ++enum SPEED_MODE { ++ SSPEED = 1, ++ FSPEED = 2, ++ HSPEED = 3, ++}; ++ ++UINT32 I2c_Disable(UINT32 base_addr); ++ ++void I2c_SetSpeed(UINT32 base_addr, UINT8 model); ++void I2c_SetDeviceId(UINT32 base_addr, UINT32 deviceID); ++void I2c_Enable(UINT32 enable); ++UINT32 I2c_GetStatus(UINT32 base_addr); ++void I2c_SetIr(UINT32 base_addr, UINT16 mask); ++UINT32 I2c_Disable(UINT32 base_addr); ++ ++void I2c_Init(UINT32 base_addr, UINT16 slave_addr, enum SPEED_MODE speed, ++ int txtl, int rxtl); ++ ++/* function Macro */ ++ ++/************************************************************************* ++* Function Name : I2C_GetTransmitFifoLevel ++* Description : get tx fifo level ++* Input : base addr ++* Output : None ++* Return : None ++* ++ ***********************************************************************/ ++#define I2C_GetTransmitFifoLevel(base_addr) (GET_REG(base_addr + \ ++ REG_I2C_TXFLR)) ++ ++/******************************************************************************* ++* Function Name : I2c_GetTxFifoDepth ++* Description : get tx fifo depth ++* Input : base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_GetTxFifoDepth( base_addr) (((GET_REG(base_addr + \ ++ DW_IC_COMP_PARAM_1)>> 16) & 0xff) + 1) ++ ++/******************************************************************************* ++* Function Name : I2c_GetRxFifoDepth ++* Description : get rx fifo depth ++* Input : base addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_GetRxFifoDepth( base_addr) (((GET_REG(base_addr + \ ++ DW_IC_COMP_PARAM_1)>> 8) & 0xff) + 1) ++/******************************************************************************* ++* Function Name : I2c_SetDeviceId ++* Description : set the slave addr ++* Input : deviceID:slave addr ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_SetDeviceId( base_addr,deviceID) SET_REG(base_addr + REG_I2C_TAR,deviceID) //set IIC slave address ++ ++/******************************************************************************* ++* Function Name : I2c_Read ++* Description : read data from I2C bus ++* Input : None ++* Output : None ++* Return : data:I2C data ++* ++ *******************************************************************************/ ++ ++#define I2c_Read(base_addr ) (GET_REG(base_addr + REG_I2C_DATA_CMD)&0xff) //DW_I2C_DATA_CMD ++/******************************************************************************* ++* Function Name : I2c_SetSsSclHcnt ++* Description : set i2c ss scl hcnt ++* Input : hcnt ++* Output : None ++* Return : data:I2C data ++* ++ *******************************************************************************/ ++ ++#define I2c_SetSsHcnt(base_addr, hcnt) SET_REG(base_addr + DW_IC_SS_SCL_HCNT,hcnt) ++ ++/******************************************************************************* ++* Function Name : I2c_SetSsSclLcnt ++* Description : set i2c ss scl lcnt ++* Input : lcnt ++* Output : None ++* Return : data:I2C data ++* ++ *******************************************************************************/ ++ ++#define I2c_SetSsLcnt(base_addr, lcnt) SET_REG(base_addr + DW_IC_SS_SCL_LCNT,lcnt) ++/******************************************************************************* ++* Function Name : I2c_SetFsSclHcnt ++* Description : set i2c fs scl hcnt ++* Input : hcnt ++* Output : None ++* Return : data:I2C data ++* ++ *******************************************************************************/ ++ ++#define I2c_SetFsHcnt(base_addr, hcnt) SET_REG(base_addr + DW_IC_FS_SCL_HCNT,hcnt) ++ ++/******************************************************************************* ++* Function Name : I2c_SetFsSclLcnt ++* Description : set i2c fs scl lcnt ++* Input : lcnt ++* Output : None ++* Return : data:I2C data ++* ++ *******************************************************************************/ ++ ++#define I2c_SetFsLcnt(base_addr, lcnt) SET_REG(base_addr + DW_IC_FS_SCL_LCNT,lcnt) ++/******************************************************************************* ++* Function Name : I2c_Disable ++* Description : disable I2C bus ++* Input : None ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_DisEnable(base_addr) SET_REG(base_addr + REG_I2C_ENABLE,DISABLE); ++/******************************************************************************* ++* Function Name : I2c_Enable ++* Description : set the I2C bus enable ++* Input : enable ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_Enable(base_addr) SET_REG(base_addr + REG_I2C_ENABLE,ENABLE); ++/******************************************************************************* ++* Function Name : I2c_Write ++* Description : Write data to I2C bus ++* Input : data:wirte out data ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++#define I2c_Write(base_addr, data) SET_REG(base_addr + REG_I2C_DATA_CMD,data) ++ ++/******************************************************************************* ++* Function Name : I2c_GetTxTl ++* Description : Get TX_TL ++* Input : TX_TL ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetTxTl(base_addr ) (GET_REG(base_addr + REG_I2C_TX_TL)&0xff); ++/******************************************************************************* ++* Function Name : I2c_GetRxTl ++* Description : Get RX_TL ++* Input : RX_TL ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetRxTl(base_addr ) (GET_REG(base_addr + REG_I2C_RX_TL)&0xff); ++/******************************************************************************* ++* Function Name : I2c_GetRxFLR ++* Description : Get RX_FLR ++* Input : base_addr ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetRxFLR(base_addr) (GET_REG(base_addr + DW_IC_RXFLR)&0xff); ++/******************************************************************************* ++* Function Name : I2c_GetTxFLR ++* Description : Get TX_FLR ++* Input : base_addr ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetTxFLR(base_addr) (GET_REG(base_addr + DW_IC_TXFLR)&0xff); ++/******************************************************************************* ++* Function Name : I2c_SetTxRxTl ++* Description : set TX_TL RX_TL ++* Input : TX_TL, RX_TL ++* Return : None ++ *******************************************************************************/ ++#define I2c_SetTxRxTl(base_addr ,txtl,rxtl) \ ++ SET_REG(base_addr + REG_I2C_TX_TL, txtl); \ ++ SET_REG(base_addr + REG_I2C_RX_TL, rxtl) ++ ++/******************************************************************************* ++* Function Name : I2c_IsActiveMst ++* Description : if master mode is active, return 1 ++* Input : none ++* Return : MST_ACTIVITY (IC_STATUS[5]) ++ *******************************************************************************/ ++#define I2c_IsActiveMst(base_addr) (GET_REG(base_addr + REG_I2C_STATUS)>>5 & 1) ++ ++/******************************************************************************* ++* Function Name : I2c_SetCon ++* Description : set config ++* Input : config ++* Return : None ++ *******************************************************************************/ ++#define I2c_SetCon(base_addr,config) SET_REG(base_addr + REG_I2C_CON,config) ++/******************************************************************************* ++* Function Name : I2c_GetCon ++* Description : get config ++* Input : config ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetCon(base_addr) GET_REG(base_addr + REG_I2C_CON) ++ ++/******************************************************************************* ++* Function Name : I2c_Status ++* Description : get i2c status ++* Input : None ++* Return : None ++ *******************************************************************************/ ++#define I2c_Status(base_addr) GET_REG(base_addr + REG_I2C_STATUS) ++ ++/******************************************************************************* ++* Function Name : I2c_SetTar ++* Description : set target address ++* Input : id ++* Return : None ++ *******************************************************************************/ ++#define I2c_SetTar(base_addr, id) SET_REG(base_addr + REG_I2C_TAR,id) ++ ++/******************************************************************************* ++* Function Name : I2c_SetIntrMask ++* Description : set interrupt mask ++* Input : mask ++* Return : None ++ *******************************************************************************/ ++#define I2c_SetIntrMask(base_addr,mask) SET_REG(base_addr + REG_I2C_INTR_MASK,mask) ++ ++/******************************************************************************* ++* Function Name : I2c_ClrIntr ++* Description : clear interrupt ++* Input : mask ++* Return : None ++ *******************************************************************************/ ++#define I2c_ClrIntr(base_addr,mask) GET_REG(base_addr + mask) ++/******************************************************************************* ++* Function Name : I2c_REG_STATUS ++* Description : clear interrupt ++* Input : mask ++* Return : None ++ *******************************************************************************/ ++#define I2c_GetTxAbrtSource(base_addr) GET_REG(base_addr + DW_IC_TX_ABRT_SOURCE) ++ ++/******************************************************************************* ++* Function Name : I2c_TxEmpty ++* Description : TX_EMPTY interrupt assert ++* Input : none ++* Return : TX_EMPTY ++ *******************************************************************************/ ++#define I2c_TxEmpty(base_addr) (GET_REG(base_addr + REG_I2C_RAW_INTR_STAT) & M_TX_EMPTY) ++ ++/******************************************************************************* ++* Function Name : I2c_RxFull ++* Description : RX_FULL interrupt assert ++* Input : none ++* Return : RX_FULL ++ *******************************************************************************/ ++#define I2c_RxFull(base_addr) (GET_REG(base_addr + REG_I2C_RAW_INTR_STAT) & M_RX_FULL) ++/******************************************************************************* ++* Function Name : I2c_RxEmpty ++* Description : RX_EMPTY interrupt assert ++* Input : none ++* Return : RX_EMPTY ++ *******************************************************************************/ ++#define I2c_RxEmpty(base_addr) (GET_REG(base_addr + REG_I2C_RAW_INTR_STAT) & M_RX_OVER) ++ ++/* register define */ ++typedef union { ++ struct { ++ UINT32 MASTER_MODE : 1; ++ UINT32 SPEED : 2; ++ UINT32 IC_10BITADDR_SLAVE : 1; ++ UINT32 IC_10BITADDR_MASTER : 1; ++ UINT32 IC_RESTART_EN : 1; ++ UINT32 IC_SLAVE_DISABLE : 1; ++ UINT32 reserved_31_7 : 25; ++ } x; ++ UINT32 dw; ++} Reg_I2c_Con; ++ ++#endif /* __ASM_ARCH_I2C_H */ +diff --git a/arch/arm/mach-fh/include/mach/io.h b/arch/arm/mach-fh/include/mach/io.h +new file mode 100644 +index 00000000..aa4883a3 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/io.h +@@ -0,0 +1,132 @@ ++/* ++ * fh io definitions ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __ASM_ARCH_IO_H ++#define __ASM_ARCH_IO_H ++ ++#include <mach/chip.h> ++ ++#define IO_SPACE_LIMIT 0xffffffff ++ ++/* ++ * We don't actually have real ISA nor PCI buses, but there is so many ++ * drivers out there that might just work if we fake them... ++ */ ++#define __io(a) __typesafe_io(a) ++#define __mem_pci(a) (a) ++#define __mem_isa(a) (a) ++ ++#ifndef CONFIG_JLINK_DEBUG ++#define FH_VIRT 0xFE000000 ++ ++#define VA_INTC_REG_BASE (FH_VIRT + 0x00000) ++#define VA_TIMER_REG_BASE (FH_VIRT + 0x10000) ++#define VA_UART0_REG_BASE (FH_VIRT + 0x20000) ++/* #define VA_GMAC_REG_BASE (FH_VIRT + 0x30000) */ ++/* #define VA_SPI0_REG_BASE (FH_VIRT + 0x40000) */ ++/* #define VA_GPIO_REG_BASE (FH_VIRT + 0x50000) */ ++/* #define VA_DMAC_REG_BASE (FH_VIRT + 0x60000) */ ++/* #define VA_SDC0_REG_BASE (FH_VIRT + 0x70000) */ ++/* #define VA_I2C_REG_BASE (FH_VIRT + 0x80000) */ ++#define VA_PMU_REG_BASE (FH_VIRT + 0x90000) ++/* #define VA_SDC1_REG_BASE (FH_VIRT + 0xa0000) */ ++#define VA_UART1_REG_BASE (FH_VIRT + 0xa0000) ++#define VA_UART2_REG_BASE (FH_VIRT + 0xb0000) ++#define VA_UART3_REG_BASE (FH_VIRT + 0xc0000) ++ ++#define VA_RAM_REG_BASE (FH_VIRT + 0xd0000) ++#define VA_DDRC_REG_BASE (FH_VIRT + 0xe0000) ++ ++#ifdef CONFIG_ARCH_FH ++#define VA_CONSOLE_REG_BASE VA_UART1_REG_BASE ++#else ++#define VA_CONSOLE_REG_BASE VA_UART0_REG_BASE ++#endif ++ ++#define I2C_OFFSET (VA_I2C_REG_BASE - I2C_REG_BASE) ++#define VI2C(x) (x + I2C_OFFSET) ++ ++#define INTC_OFFSET (VA_INTC_REG_BASE - INTC_REG_BASE) ++#define VINTC(x) (x + INTC_OFFSET) ++ ++#define TIME_OFFSET (VA_TIMER_REG_BASE - TIMER_REG_BASE) ++#define VTIMER(x) (x + TIME_OFFSET) ++ ++#define UART0_OFFSET (VA_UART0_REG_BASE - UART0_REG_BASE) ++#define VUART0(x) (x + UART0_OFFSET) ++ ++#define UART1_OFFSET (VA_UART1_REG_BASE - UART1_REG_BASE) ++#define VUART1(x) (x + UART1_OFFSET) ++ ++#define UART2_OFFSET (VA_UART2_REG_BASE - UART2_REG_BASE) ++#define VUART2(x) (x + UART2_OFFSET) ++ ++#define UART3_OFFSET (VA_UART3_REG_BASE - UART3_REG_BASE) ++#define VUART3(x) (x + UART3_OFFSET) ++ ++ ++#define SPI0_OFFSET (VA_SPI0_REG_BASE - SPI0_REG_BASE) ++#define VSPI0(x) (x + SPI0_OFFSET) ++ ++#define GMAC_OFFSET (VA_GMAC_REG_BASE - GMAC_REG_BASE) ++#define VGMAC(x) (x + GMAC_OFFSET) ++ ++#define DMAC_OFFSET (VA_DMAC_REG_BASE - DMAC_REG_BASE) ++#define VDMAC(x) (x + DMAC_OFFSET) ++ ++#define SDC0_OFFSET (VA_SDC0_REG_BASE - SDC0_REG_BASE) ++#define VSDC0(x) (x + SDC0_OFFSET) ++ ++#define SDC1_OFFSET (VA_SDC1_REG_BASE - SDC1_REG_BASE) ++#define VSDC1(x) (x + SDC1_OFFSET) ++ ++#define GPIO_OFFSET (VA_GPIO_REG_BASE - GPIO_REG_BASE) ++#define VGPIO(x) (x + GPIO_OFFSET) ++ ++#define PMU_OFFSET (VA_PMU_REG_BASE - PMU_REG_BASE) ++#define VPMU(x) (x + PMU_OFFSET) ++ ++#define PAE_OFFSET (VA_PAE_REG_BASE - PAE_REG_BASE) ++#define VPAE(x) (x + PAE_OFFSET) ++ ++#else ++#define VA_INTC_REG_BASE INTC_REG_BASE ++#define VA_TIMER_REG_BASE TIMER_REG_BASE ++#define VA_UART0_REG_BASE UART0_REG_BASE ++#define VA_UART1_REG_BASE UART1_REG_BASE ++#define VA_GMAC_REG_BASE GMAC_REG_BASE ++#define VA_DMAC_REG_BASE DMAC_REG_BASE ++#define VA_I2C_REG_BASE I2C_REG_BASE ++#define VA_SDC0_REG_BASE SDC0_REG_BASE ++ ++#define VA_SPI0_REG_BASE SPI0_REG_BASE ++ ++#define VA_GPIO_REG_BASE GPIO0_REG_BASE ++#define VA_PMU_REG_BASE PMU_REG_BASE ++ ++//#define VA_GPIO_REG_BASE (FH_VIRT + 0x500000) ++ ++#define VINTC(x) x ++#define VTIMER(x) x ++#define VUART0(x) x ++#define VUART1(x) x ++#define VUART2(x) x ++#define VUART3(x) x ++#define VGMAC(x) x ++ ++#define VDMAC(x) x ++#define VI2C(x) x ++#define VSDC0(x) x ++ ++#define VSPI0(x) x ++#define VPMU(x) x ++ ++#endif ++#endif /* __ASM_ARCH_IO_H */ +diff --git a/arch/arm/mach-fh/include/mach/iomux.h b/arch/arm/mach-fh/include/mach/iomux.h +new file mode 100644 +index 00000000..398b0a6e +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/iomux.h +@@ -0,0 +1,165 @@ ++#ifndef IOMUX_H_ ++#define IOMUX_H_ ++#include <linux/types.h> ++#include <linux/io.h> ++#include <mach/io.h> ++ ++#define IOMUX_PADTYPE(n) (Iomux_PadType##n *) ++#define IOMUX_PUPD_NONE 0 ++#define IOMUX_PUPD_DOWN 1 ++#define IOMUX_PUPD_UP 2 ++#define IOMUX_PUPD_KEEPER 3 ++//#define IOMUX_DEBUG ++ ++ ++typedef union { ++ struct { ++ __u32 sr : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 e8_e4 : 2; ++ __u32 reserved_31_6 : 24; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType5; ++ ++typedef union { ++ struct { ++ __u32 sr : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 e8_e4 : 2; ++ __u32 reserved_7_6 : 2; ++ ++ __u32 mfs : 1; ++ __u32 reserved_31_9 : 23; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType8; ++ ++ ++typedef union { ++ struct { ++ __u32 smt : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 ie : 1; ++ __u32 reserved_7_5 : 3; ++ ++ __u32 pu_pd : 2; ++ __u32 reserved_31_10 : 22; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType9; ++ ++ ++typedef union { ++ struct { ++ __u32 e4_e2 : 2; ++ __u32 reserved_3_2 : 2; ++ ++ __u32 smt : 1; ++ __u32 reserved_7_5 : 3; ++ ++ __u32 ie : 1; ++ __u32 reserved_11_9 : 3; ++ ++ __u32 mfs : 2; ++ __u32 reserved_31_14 : 18; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType13; ++ ++typedef union { ++ struct { ++ __u32 sr : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 e8_e4 : 2; ++ __u32 reserved_7_6 : 2; ++ ++ __u32 smt : 1; ++ __u32 reserved_11_9 : 3; ++ ++ __u32 ie : 1; ++ __u32 e : 1; //only for PAD_MAC_REF_CLK_CFG (0x00a4) ++ __u32 reserved_15_12 : 2; ++ ++ __u32 pu_pd : 2; ++ __u32 reserved_31_18 : 14; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType17; ++ ++typedef union { ++ struct { ++ __u32 sr : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 e4_e2 : 2; ++ __u32 reserved_7_6 : 2; ++ ++ __u32 smt : 1; ++ __u32 reserved_11_9 : 3; ++ ++ __u32 ie : 1; ++ __u32 reserved_15_13 : 3; ++ ++ __u32 pu_pd : 2; ++ __u32 reserved_19_18 : 2; ++ ++ __u32 mfs : 1; ++ __u32 reserved_31_21 : 11; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType20; ++ ++ ++typedef union { ++ struct { ++ __u32 sr : 1; ++ __u32 reserved_3_1 : 3; ++ ++ __u32 e4_e2 : 2; ++ __u32 reserved_7_6 : 2; ++ ++ __u32 smt : 1; ++ __u32 reserved_11_9 : 3; ++ ++ __u32 ie : 1; ++ __u32 reserved_15_13 : 3; ++ ++ __u32 pu_pd : 2; ++ __u32 reserved_19_18 : 2; ++ ++ __u32 mfs : 2; ++ __u32 reserved_31_21 : 10; ++ ++ } bit; ++ __u32 dw; ++} Iomux_PadType21; ++ ++typedef struct { ++ u32 *reg; ++ u32 reg_offset; ++ char *func_name[4]; ++ int reg_type; ++ int func_sel; ++ int drv_cur; ++ int pupd; ++} Iomux_Pad; ++ ++typedef struct { ++ void __iomem *base; ++ Iomux_Pad *pads; ++} Iomux_Object; ++ ++void fh_iomux_init(Iomux_Object *iomux_obj); ++ ++#endif /* IOMUX_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/irqs.h b/arch/arm/mach-fh/include/mach/irqs.h +new file mode 100644 +index 00000000..0138006f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/irqs.h +@@ -0,0 +1,43 @@ ++/* ++ * fh interrupt controller definitions ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __ASM_ARCH_IRQS_H ++#define __ASM_ARCH_IRQS_H ++ ++#include <mach/chip.h> ++ ++#define REG_IRQ_EN_LOW (INTC_REG_BASE + 0x0000) ++#define REG_IRQ_EN_HIGH (INTC_REG_BASE + 0x0004) ++#define REG_IRQ_IRQMASK_LOW (INTC_REG_BASE + 0x0008) ++#define REG_IRQ_IRQMASK_HIGH (INTC_REG_BASE + 0x000C) ++#define REG_IRQ_IRQFORCE_LOW (INTC_REG_BASE + 0x0010) ++#define REG_IRQ_IRQFORCE_HIGH (INTC_REG_BASE + 0x0014) ++#define REG_IRQ_RAWSTATUS_LOW (INTC_REG_BASE + 0x0018) ++#define REG_IRQ_RAWSTATUS_HIGH (INTC_REG_BASE + 0x001C) ++#define REG_IRQ_STATUS_LOW (INTC_REG_BASE + 0x0020) ++#define REG_IRQ_STATUS_HIGH (INTC_REG_BASE + 0x0024) ++#define REG_IRQ_MASKSTATUS_LOW (INTC_REG_BASE + 0x0028) ++#define REG_IRQ_MASKSTATUS_HIGH (INTC_REG_BASE + 0x002C) ++#define REG_IRQ_FINSTATUS_LOW (INTC_REG_BASE + 0x0030) ++#define REG_IRQ_FINSTATUS_HIGH (INTC_REG_BASE + 0x0034) ++#define REG_FIQ_EN_LOW (INTC_REG_BASE + 0x02C0) ++#define REG_FIQ_EN_HIGH (INTC_REG_BASE + 0x02C4) ++#define REG_FIQ_FIQMASK_LOW (INTC_REG_BASE + 0x02C8) ++#define REG_FIQ_FIQMASK_HIGH (INTC_REG_BASE + 0x02CC) ++#define REG_FIQ_FIQFORCE_LOW (INTC_REG_BASE + 0x02D0) ++#define REG_FIQ_FIQFORCE_HIGH (INTC_REG_BASE + 0x02D4) ++#define REG_FIQ_RAWSTATUS_LOW (INTC_REG_BASE + 0x02D8) ++#define REG_FIQ_RAWSTATUS_HIGH (INTC_REG_BASE + 0x02DC) ++#define REG_FIQ_STATUS_LOW (INTC_REG_BASE + 0x02E0) ++#define REG_FIQ_STATUS_HIGH (INTC_REG_BASE + 0x02E4) ++#define REG_FIQ_FINSTATUS_LOW (INTC_REG_BASE + 0x02E8) ++#define REG_FIQ_FINSTATUS_HIGH (INTC_REG_BASE + 0x02EC) ++ ++#endif /* __ASM_ARCH_IRQS_H */ +diff --git a/arch/arm/mach-fh/include/mach/memory.h b/arch/arm/mach-fh/include/mach/memory.h +new file mode 100644 +index 00000000..c8c984a9 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/memory.h +@@ -0,0 +1,27 @@ ++/* ++ * fh memory space definitions ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __ASM_ARCH_MEMORY_H ++#define __ASM_ARCH_MEMORY_H ++ ++/************************************************************************** ++ * Included Files ++ **************************************************************************/ ++#include <asm/page.h> ++#include <asm/sizes.h> ++ ++/************************************************************************** ++ * Definitions ++ **************************************************************************/ ++#define FH_DDR_BASE 0xA0000000 ++ ++#define PLAT_PHYS_OFFSET FH_DDR_BASE ++ ++#endif /* __ASM_ARCH_MEMORY_H */ +diff --git a/arch/arm/mach-fh/include/mach/pinctrl.h b/arch/arm/mach-fh/include/mach/pinctrl.h +new file mode 100644 +index 00000000..2d1355ff +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/pinctrl.h +@@ -0,0 +1,137 @@ ++#ifndef PINCTRL_H_ ++#define PINCTRL_H_ ++#include "pinctrl_osdep.h" ++#include <linux/seq_file.h> ++ ++#define MSC_3_3V (0) ++#define MSC_1_8V (1) ++ ++#define PINCTRL_UNUSED (-1) ++ ++#define PUPD_NONE (0) ++#define PUPD_UP (1) ++#define PUPD_DOWN (2) ++ ++#define INPUT_DISABLE (0) ++#define INPUT_ENABLE (1) ++#define OUTPUT_DISABLE (0) ++#define OUTPUT_ENABLE (1) ++ ++#if defined(CONFIG_ARCH_FH8626V100) ++#define PUPD_DISABLE (1) ++#define PUPD_ENABLE (0) ++#define PUPD_ZERO (0) ++#else ++#define PUPD_DISABLE (0) ++#define PUPD_ENABLE (1) ++#define PUPD_ZERO (0) ++#endif ++ ++#define FUNC0 (0) ++#define FUNC1 (1) ++#define FUNC2 (2) ++#define FUNC3 (3) ++#define FUNC4 (4) ++#define FUNC5 (5) ++#define FUNC6 (6) ++#define FUNC7 (7) ++ ++#define NEED_CHECK_PINLIST (1) ++ ++#define MAX_FUNC_NUM 6 ++ ++#define PINCTRL_FUNC(name, id, sel, pupd, ds) \ ++PinCtrl_Pin PAD##id##_##name = \ ++{ \ ++ .pad_id = id, \ ++ .func_name = #name, \ ++ .reg_offset = (id * 4), \ ++ .func_sel = sel, \ ++ .pullup_pulldown = pupd, \ ++ .driving_curr = ds, \ ++} ++ ++#define PINCTRL_MUX(pname, sel, ...) \ ++PinCtrl_Mux MUX_##pname = \ ++{ \ ++ .mux_pin = { __VA_ARGS__ }, \ ++ .cur_pin = sel, \ ++} ++ ++#define PINCTRL_DEVICE(name, count, ...) \ ++typedef struct \ ++{ \ ++ char *dev_name; \ ++ int mux_count; \ ++ OS_LIST list; \ ++ PinCtrl_Mux *mux[count]; \ ++} PinCtrl_Device_##name; \ ++PinCtrl_Device_##name pinctrl_dev_##name = \ ++{ \ ++ .dev_name = #name, \ ++ .mux_count = count, \ ++ .mux = { __VA_ARGS__ }, \ ++} ++ ++typedef union { ++ struct { ++ unsigned int sl : 1; /*0*/ ++ unsigned int : 3; /*1~3*/ ++ unsigned int ds : 3; /*4~6*/ ++ unsigned int msc : 1; /*7*/ ++ unsigned int st : 1; /*8*/ ++ unsigned int : 3; /*9~11*/ ++ unsigned int ie : 1; /*12*/ ++ unsigned int : 3; /*13~15*/ ++ unsigned int pdn : 1; /*16*/ ++ unsigned int : 3; /*17~19*/ ++ unsigned int pun : 1; /*20*/ ++ unsigned int : 3; /*21~23*/ ++ unsigned int mfs : 4; /*24~27*/ ++ unsigned int oe : 1; /*28*/ ++ unsigned int : 3; /*29~31*/ ++ } bit; ++ unsigned int dw; ++} PinCtrl_Register; ++ ++typedef struct ++{ ++ char *func_name; ++ PinCtrl_Register *reg; ++ unsigned int pad_id : 8; ++ unsigned int reg_offset : 12; ++ unsigned int func_sel : 4; ++ unsigned int input_enable : 1; ++ unsigned int output_enable : 1; ++ unsigned int pullup_pulldown : 2; ++ unsigned int volt_mode : 1; ++ unsigned int driving_curr : 3; ++}PinCtrl_Pin; ++ ++typedef struct ++{ ++ int cur_pin; ++ PinCtrl_Pin *mux_pin[MUX_NUM]; ++} PinCtrl_Mux; ++ ++typedef struct ++{ ++ void *vbase; ++ void *pbase; ++ PinCtrl_Pin *pinlist[PAD_NUM]; ++} PinCtrl_Object; ++ ++typedef struct ++{ ++ char *dev_name; ++ int mux_count; ++ OS_LIST list; ++ void *mux; ++}PinCtrl_Device; ++ ++void fh_pinctrl_init(unsigned int base); ++void fh_pinctrl_prt(struct seq_file *sfile); ++int fh_pinctrl_smux(char *devname, char* muxname, int muxsel, unsigned int flag); ++int fh_pinctrl_sdev(char *devname, unsigned int flag); ++void fh_pinctrl_init_devicelist(OS_LIST *list); ++#endif /* PINCTRL_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/pinctrl_osdep.h b/arch/arm/mach-fh/include/mach/pinctrl_osdep.h +new file mode 100644 +index 00000000..8e3d24de +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/pinctrl_osdep.h +@@ -0,0 +1,23 @@ ++#ifndef PINCTRL_OSDEP_H_ ++#define PINCTRL_OSDEP_H_ ++ ++#include <linux/list.h> ++#include <linux/kernel.h> ++#include <mach/fh_predefined.h> ++#include <linux/string.h> ++ ++#define OS_LIST_INIT LIST_HEAD_INIT ++#define OS_LIST struct list_head ++#define OS_PRINT printk ++#define OS_LIST_EMPTY INIT_LIST_HEAD ++#define OS_NULL NULL ++ ++#define PINCTRL_ADD_DEVICE(name) \ ++ list_add(&pinctrl_dev_##name.list, \ ++ list) ++ ++#define PAD_NUM (77) ++ ++#define MUX_NUM (6) ++ ++#endif /* PINCTRL_OSDEP_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/pmu.h b/arch/arm/mach-fh/include/mach/pmu.h +new file mode 100644 +index 00000000..33c75f53 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/pmu.h +@@ -0,0 +1,16 @@ ++ ++#ifndef _FH_PMU_H_ ++#define _FH_PMU_H_ ++ ++#include <linux/types.h> ++#include "fh_chipid.h" ++ ++void fh_pmu_set_reg(u32 offset, u32 data); ++u32 fh_pmu_get_reg(u32 offset); ++int fh_pmu_init(void); ++ ++void fh_pmu_stop(void); ++ ++void fh_pae_set_reg(u32 offset, u32 data); ++ ++#endif /* _FH_PMU_H_ */ +diff --git a/arch/arm/mach-fh/include/mach/spi.h b/arch/arm/mach-fh/include/mach/spi.h +new file mode 100644 +index 00000000..7123ce94 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/spi.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2009 Texas Instruments. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef __ARCH_ARM_FH_SPI_H ++#define __ARCH_ARM_FH_SPI_H ++ ++#include <linux/io.h> ++#include <linux/scatterlist.h> ++ ++#define SPI_MASTER_CONTROLLER_MAX_SLAVE (2) ++#define SPI_TRANSFER_USE_DMA (0x77888877) ++ ++struct fh_spi_cs { ++ u32 GPIO_Pin; ++ char *name; ++}; ++ ++struct fh_spi_chip { ++ u8 poll_mode; /* 0 for contoller polling mode */ ++ u8 type; /* SPI/SSP/Micrwire */ ++ u8 enable_dma; ++ void *cs_control; ++ /* void (*cs_control)(u32 command);*/ ++}; ++ ++struct fh_spi_platform_data { ++ u32 apb_clock_in; ++ u32 fifo_len; ++ u32 slave_max_num; ++ struct fh_spi_cs cs_data[SPI_MASTER_CONTROLLER_MAX_SLAVE]; ++ /*below is dma transfer needed*/ ++ u32 dma_transfer_enable; ++ u32 rx_handshake_num; ++ u32 tx_handshake_num; ++ u32 bus_no; ++ char *clk_name; ++ u32 rx_dma_channel; ++ u32 tx_dma_channel; ++#define RX_ONLY_MODE 0x30 ++#define TX_RX_MODE 0x31 ++ u32 spidma_xfer_mode; ++ /* add support wire width*/ ++ u32 ctl_wire_support; ++ u32 max_speed_support; ++ u32 data_reg_offset; ++#define INC_SUPPORT 0x55 ++ u32 data_increase_support; ++ u32 data_field_size; ++#define SWAP_SUPPORT 0x55 ++ u32 swap_support; ++ void (*plat_init)(struct fh_spi_platform_data *plat_data); ++#define SPI_DMA_PROTCTL_ENABLE 0x55 ++ u32 dma_protctl_enable; ++ u32 dma_protctl_data; ++ ++#define SPI_DMA_MASTER_SEL_ENABLE 0x55 ++ u32 dma_master_sel_enable; ++ u32 dma_master_ctl_sel; ++ u32 dma_master_mem_sel; ++}; ++ ++#endif /* __ARCH_ARM_FH_SPI_H */ +diff --git a/arch/arm/mach-fh/include/mach/sram.h b/arch/arm/mach-fh/include/mach/sram.h +new file mode 100644 +index 00000000..46d2dcd1 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/sram.h +@@ -0,0 +1,25 @@ ++/* ++ * mach/sram.h - FH simple SRAM allocator ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __MACH_SRAM_H ++#define __MACH_SRAM_H ++ ++/* ++ * SRAM allocations return a CPU virtual address, or NULL on error. ++ * If a DMA address is requested and the SRAM supports DMA, its ++ * mapped address is also returned. ++ * ++ * Errors include SRAM memory not being available, and requesting ++ * DMA mapped SRAM on systems which don't allow that. ++ */ ++extern void *sram_alloc(size_t len, dma_addr_t *dma); ++extern void sram_free(void *addr, size_t len); ++ ++#endif /* __MACH_SRAM_H */ +diff --git a/arch/arm/mach-fh/include/mach/system.h b/arch/arm/mach-fh/include/mach/system.h +new file mode 100644 +index 00000000..6ff6766f +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/system.h +@@ -0,0 +1,43 @@ ++/* ++ * mach/system.h ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __ASM_ARCH_SYSTEM_H ++#define __ASM_ARCH_SYSTEM_H ++ ++#include <mach/io.h> ++#include <mach/fh_predefined.h> ++#include <mach/pmu.h> ++#include <linux/compiler.h> ++#include <linux/types.h> ++#include <asm/mach/time.h> ++#include <asm/proc-fns.h> ++ ++extern void fh_intc_init(void); ++ ++void fh_irq_suspend(void); ++void fh_irq_resume(void); ++ ++extern unsigned int fh_cpu_suspend_sz; ++extern void fh_cpu_suspend(void); ++ ++static inline void arch_idle(void) ++{ ++ ++} ++ ++static inline void arch_reset(char mode, const char *cmd) ++{ ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0x7fffffff); ++} ++ ++/*change the scheduling policy and/or RT priority of `current` thread. */ ++extern void fh_setscheduler(int policy, int priority); ++ ++#endif /* __ASM_ARCH_SYSTEM_H */ +diff --git a/arch/arm/mach-fh/include/mach/timex.h b/arch/arm/mach-fh/include/mach/timex.h +new file mode 100644 +index 00000000..7c6fafc9 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/timex.h +@@ -0,0 +1,21 @@ ++/* ++ * FH timer subsystem ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __ASM_ARCH_TIMEX_H ++#define __ASM_ARCH_TIMEX_H ++#include "mach/chip.h" ++ ++#define PAE_PTS_CLK (1000000) ++ ++#define CLOCK_TICK_RATE TIMER_CLK ++ ++extern struct sys_timer fh_timer; ++ ++#endif /* __ASM_ARCH_TIMEX_H__ */ +diff --git a/arch/arm/mach-fh/include/mach/uncompress.h b/arch/arm/mach-fh/include/mach/uncompress.h +new file mode 100644 +index 00000000..819c6257 +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/uncompress.h +@@ -0,0 +1,57 @@ ++/* ++ * Serial port stubs for kernel decompress status messages ++ * ++ * Initially based on: ++ * arch/arm/plat-omap/include/mach/uncompress.h ++ * ++ * Original copyrights follow. ++ * ++ * Copyright (C) 2000 RidgeRun, Inc. ++ * Author: Greg Lonnon <glonnon@ridgerun.com> ++ * ++ * Rewritten by: ++ * Author: <source@mvista.com> ++ * 2004 (c) MontaVista Software, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include <linux/types.h> ++ ++#include <asm/mach-types.h> ++#include <mach/chip.h> ++ ++#define REG_UART_THR (0x0000) ++#define REG_UART_USR (0x007c) ++ ++#define REG_UART0_THR (*(unsigned char *)(CONSOLE_REG_BASE + REG_UART_THR)) ++#define REG_UART0_USR (*(unsigned char *)(CONSOLE_REG_BASE + REG_UART_USR)) ++ ++static void putc(char c) ++{ ++ while (!(REG_UART0_USR & (1 << 1))) ++ barrier(); ++ ++ REG_UART0_THR = c; ++} ++ ++static inline void flush(void) ++{ ++ while (!(REG_UART0_USR & (1 << 2))) ++ barrier(); ++} ++ ++static inline void set_uart_info(u32 phys, void *__iomem virt) ++{ ++ ++} ++ ++static inline void __arch_decomp_setup(unsigned long arch_id) ++{ ++ ++} ++ ++#define arch_decomp_setup() __arch_decomp_setup(arch_id) ++#define arch_decomp_wdog() +diff --git a/arch/arm/mach-fh/include/mach/vmalloc.h b/arch/arm/mach-fh/include/mach/vmalloc.h +new file mode 100644 +index 00000000..7796486e +--- /dev/null ++++ b/arch/arm/mach-fh/include/mach/vmalloc.h +@@ -0,0 +1,16 @@ ++/* ++ * DaVinci vmalloc definitions ++ * ++ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> ++ * ++ * 2007 (c) MontaVista Software, Inc. This file is licensed under ++ * the terms of the GNU General Public License version 2. This program ++ * is licensed "as is" without any warranty of any kind, whether express ++ * or implied. ++ */ ++#include <mach/hardware.h> ++ ++/* Allow vmalloc range until the IO virtual range minus a 2M "hole" */ ++///#define VMALLOC_END (IO_VIRT - (2<<20)) ++ ++#define VMALLOC_END (PAGE_OFFSET + 0x3e000000) +diff --git a/arch/arm/mach-fh/iomux.c b/arch/arm/mach-fh/iomux.c +new file mode 100644 +index 00000000..f042a4bd +--- /dev/null ++++ b/arch/arm/mach-fh/iomux.c +@@ -0,0 +1,854 @@ ++#include <mach/iomux.h> ++#include <mach/pmu.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/string.h> ++#include <linux/printk.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++ ++ ++Iomux_Pad fh_iomux_cfg[] = { ++ { ++ .func_name = { "RESETN", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "TEST", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "CIS_CLK", "", "", "", }, ++ .reg_type = 5, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_HSYNC", "GPIO20", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_VSYNC", "GPIO21", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_PCLK", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 0, ++ }, ++ { ++ .func_name = { "CIS_D0", "GPIO22", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D1", "GPIO23", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D2", "GPIO24", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D3", "GPIO25", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D4", "GPIO26", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D5", "GPIO27", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D6", "GPIO28", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D7", "GPIO29", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D8", "GPIO30", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D9", "GPIO31", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D10", "GPIO32", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_D11", "GPIO33", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_REF_CLK", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "MAC_MDC", "GPIO34", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 0, ++ }, ++ { ++ .func_name = { "MAC_MDIO", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_COL", "GPIO35", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_CRS", "GPIO36", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_RXCK", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "MAC_RXD0", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = -1, ++ }, ++ ++ { ++ .func_name = { "MAC_RXD1", "GPIO38", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_RXD2", "GPIO39", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_RXD3", "GPIO40", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_RXDV", "GPIO41", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_TXCK", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "MAC_TXD0", "GPIO42", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_TXD1", "GPIO43", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_TXD2", "GPIO44", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_TXD3", "GPIO45", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_TXEN", "GPIO46", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "MAC_RXER", "GPIO47", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO0", "ARC_JTAG_TCK", "GPIO0", "CIS_SSI0_CSN1", }, ++ .reg_type = 21, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO1", "ARC_JTAG_TRSTN", "GPIO1", "CIS_SSI0_RXD", }, ++ .reg_type = 21, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO2", "ARC_JTAG_TMS", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO3", "ARC_JTAG_TDI", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO4", "ARC_JTAG_TDO", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "JTAG_TCK", "GPIO5", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "JTAG_TRSTN", "GPIO6", "PWM_OUT3", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "JTAG_TMS", "GPIO7", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "JTAG_TDI", "GPIO8", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "JTAG_TDO", "GPIO9", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO10", "UART1_OUT", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO11", "UART1_IN", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO12", "PWM_OUT0", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO13", "PWM_OUT1", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "GPIO14", "PWM_OUT2", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "UART0_IN", "GPIO48", "UART0_IN", " I2S_WS", }, ++ .reg_type = 21, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "UART0_OUT", "GPIO49", "UART0_OUT", "I2S_CLK", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_SCL", "GPIO56", "CIS_SCL", "CIS_SSI0_CLK", }, ++ .reg_type = 13, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "CIS_SDA", "GPIO57", "CIS_SDA", "CIS_SSI0_TXD", }, ++ .reg_type = 13, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SCL1", "GPIO50", "SCL1", "I2S_DI", }, ++ .reg_type = 21, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SDA1", "GPIO51", "I2S_DO", "", }, ++ .reg_type = 21, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SSI0_CLK", "", "", "", }, ++ .reg_type = 5, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SSI0_TXD", "", "", "", }, ++ .reg_type = 5, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SSI0_CSN0", "GPIO54", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SSI0_CSN1", "GPIO55", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SSI0_RXD", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "SD0_CD", "GPIO52", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SD0_WP", "GPIO53", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SD0_CLK", "", "", "", }, ++ .reg_type = 5, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD0_CMD_RSP", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD0_DATA0", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD0_DATA1", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 2, ++ }, ++ { ++ .func_name = { "SD0_DATA2", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD0_DATA3", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD1_CLK", "SSI1_CLK", "", "", }, ++ .reg_type = 8, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_NONE, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SD1_CD", "GPIO_58", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SD1_WP", "GPIO_59", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++ { ++ .func_name = { "SD1_DATA0", "SSI1_TXD", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD1_DATA1", "SSI1_CSN0", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD1_DATA2", "SSI1_CSN1", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD1_DATA3", "", "", "", }, ++ .reg_type = 17, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "SD1_CMD_RSP", "SSI1_RXD", "", "", }, ++ .reg_type = 20, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = 3, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "CLK_SW0", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "CLK_SW1", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "CLK_SW2", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "CLK_SW3", "", "", "", }, ++ .reg_type = 9, ++ .func_sel = 0, ++ .pupd = IOMUX_PUPD_UP, ++ .drv_cur = -1, ++ }, ++ { ++ .func_name = { "RESERVED", "", "", "", }, ++ .reg_type = 20, ++ .func_sel = -1, ++ }, ++ { ++ .func_name = { "MAC_TXER", "GPIO37", "", "", }, ++ .reg_type = 20, ++ .func_sel = 1, ++ .pupd = IOMUX_PUPD_DOWN, ++ .drv_cur = 1, ++ }, ++}; ++ ++ ++static void fh_iomux_setmfs(Iomux_Object *iomux_obj, Iomux_Pad *pad) ++{ ++ switch (pad->reg_type) { ++ case 8: ++ (IOMUX_PADTYPE(8)pad->reg)->bit.mfs = pad->func_sel; ++ break; ++ case 13: ++ (IOMUX_PADTYPE(13)pad->reg)->bit.mfs = pad->func_sel; ++ break; ++ case 20: ++ (IOMUX_PADTYPE(20)pad->reg)->bit.mfs = pad->func_sel; ++ break; ++ case 21: ++ (IOMUX_PADTYPE(21)pad->reg)->bit.mfs = pad->func_sel; ++ break; ++ default: ++ break; ++ } ++ ++} ++ ++#ifdef IOMUX_DEBUG ++ ++static int fh_iomux_getmfs(Iomux_Object *iomux_obj, Iomux_Pad *pad) ++{ ++ int mfs; ++ ++ switch (pad->reg_type) { ++ case 8: ++ mfs = (IOMUX_PADTYPE(8)pad->reg)->bit.mfs; ++ break; ++ case 13: ++ mfs = (IOMUX_PADTYPE(13)pad->reg)->bit.mfs; ++ break; ++ case 20: ++ mfs = (IOMUX_PADTYPE(20)pad->reg)->bit.mfs; ++ break; ++ case 21: ++ mfs = (IOMUX_PADTYPE(21)pad->reg)->bit.mfs; ++ break; ++ default: ++ mfs = -1; ++ break; ++ ++ } ++ return mfs; ++} ++ ++ ++static void fh_iomux_print(Iomux_Object *iomux_obj) ++{ ++ int i; ++ u32 reg; ++ ++ printk("\tPad No.\t\tFunction Select\t\tRegister\n"); ++ ++ for (i = 0; i < ARRAY_SIZE(fh_iomux_cfg); i++) { ++ int curr_func; ++ ++ curr_func = fh_iomux_getmfs(iomux_obj, &iomux_obj->pads[i]); ++ reg = readl((u32)iomux_obj->pads[i].reg); ++ ++ if (curr_func < 0) ++ printk("\t%d\t\t%-8s(no mfs)\t0x%08x\n", i, iomux_obj->pads[i].func_name[0], ++ reg); ++ else ++ printk("\t%d\t\t%-16s\t0x%08x\n", i, iomux_obj->pads[i].func_name[curr_func], ++ reg); ++ ++ } ++ ++} ++ ++#endif ++ ++static void fh_iomux_setcur(Iomux_Object *iomux_obj, Iomux_Pad *pad) ++{ ++ switch (pad->reg_type) { ++ case 5: ++ (IOMUX_PADTYPE(5)pad->reg)->bit.e8_e4 = pad->drv_cur; ++ break; ++ case 8: ++ (IOMUX_PADTYPE(8)pad->reg)->bit.e8_e4 = pad->drv_cur; ++ break; ++ case 13: ++ (IOMUX_PADTYPE(13)pad->reg)->bit.e4_e2 = pad->drv_cur; ++ break; ++ case 17: ++ (IOMUX_PADTYPE(17)pad->reg)->bit.e8_e4 = pad->drv_cur; ++ break; ++ case 20: ++ (IOMUX_PADTYPE(20)pad->reg)->bit.e4_e2 = pad->drv_cur; ++ break; ++ case 21: ++ (IOMUX_PADTYPE(21)pad->reg)->bit.e4_e2 = pad->drv_cur; ++ break; ++ default: ++ break; ++ } ++ ++} ++ ++static void fh_iomux_setpupd(Iomux_Object *iomux_obj, Iomux_Pad *pad) ++{ ++ switch (pad->reg_type) { ++ case 9: ++ (IOMUX_PADTYPE(9)pad->reg)->bit.pu_pd = pad->pupd; ++ break; ++ case 17: ++ (IOMUX_PADTYPE(17)pad->reg)->bit.pu_pd = pad->pupd; ++ break; ++ case 20: ++ (IOMUX_PADTYPE(20)pad->reg)->bit.pu_pd = pad->pupd; ++ break; ++ case 21: ++ (IOMUX_PADTYPE(21)pad->reg)->bit.pu_pd = pad->pupd; ++ break; ++ default: ++ break; ++ } ++} ++ ++static void fh_iomux_setrest(Iomux_Object *iomux_obj, Iomux_Pad *pad) ++{ ++ switch (pad->reg_type) { ++ case 5: ++ (IOMUX_PADTYPE(5)pad->reg)->bit.sr = 0; ++ break; ++ case 8: ++ (IOMUX_PADTYPE(8)pad->reg)->bit.sr = 0; ++ break; ++ case 9: ++ (IOMUX_PADTYPE(9)pad->reg)->bit.ie = 1; ++ (IOMUX_PADTYPE(9)pad->reg)->bit.smt = 1; ++ break; ++ case 13: ++ (IOMUX_PADTYPE(13)pad->reg)->bit.ie = 1; ++ (IOMUX_PADTYPE(13)pad->reg)->bit.smt = 1; ++ break; ++ case 17: ++ (IOMUX_PADTYPE(17)pad->reg)->bit.sr = 0; ++ (IOMUX_PADTYPE(17)pad->reg)->bit.ie = 1; ++ (IOMUX_PADTYPE(17)pad->reg)->bit.e = 1; ++ (IOMUX_PADTYPE(17)pad->reg)->bit.smt = 1; ++ break; ++ case 20: ++ (IOMUX_PADTYPE(20)pad->reg)->bit.sr = 0; ++ (IOMUX_PADTYPE(20)pad->reg)->bit.ie = 1; ++ (IOMUX_PADTYPE(20)pad->reg)->bit.smt = 1; ++ break; ++ case 21: ++ (IOMUX_PADTYPE(21)pad->reg)->bit.sr = 0; ++ (IOMUX_PADTYPE(21)pad->reg)->bit.ie = 1; ++ (IOMUX_PADTYPE(21)pad->reg)->bit.smt = 1; ++ break; ++ default: ++ break; ++ } ++ ++} ++ ++void fh_iomux_init(Iomux_Object *iomux_obj) ++{ ++ int i; ++ u32 reg = 0; ++ ++ iomux_obj->pads = fh_iomux_cfg; ++ ++ for (i = 0; i < ARRAY_SIZE(fh_iomux_cfg); i++) { ++ iomux_obj->pads[i].reg_offset = i * 4; ++ iomux_obj->pads[i].reg = ® ++ ++#if defined(CONFIG_FH_PWM_NUM) && CONFIG_FH_PWM_NUM == 4 ++ //for pwm3 only ++ if(fh_iomux_cfg[i].func_sel == 2 ++ && iomux_obj->pads[i].reg_offset == 0xa8) ++ { ++ fh_pmu_set_reg(0x128, 0x00101110); ++ fh_iomux_cfg[i].func_sel = 1; ++ } ++#endif ++ ++ if(iomux_obj->pads[i].func_sel < 0) ++ continue; ++ ++ fh_iomux_setmfs(iomux_obj, &fh_iomux_cfg[i]); ++ fh_iomux_setcur(iomux_obj, &fh_iomux_cfg[i]); ++ fh_iomux_setpupd(iomux_obj, &fh_iomux_cfg[i]); ++ fh_iomux_setrest(iomux_obj, &fh_iomux_cfg[i]); ++ fh_pmu_set_reg(0x5c + iomux_obj->pads[i].reg_offset, reg); ++ } ++#ifdef CONFIG_FH_GMAC_RMII ++ //(IOMUX_PADTYPE(17)(iomux_obj->pads[18]).reg)->bit.e = 1; ++ reg = fh_pmu_get_reg(REG_PMU_PAD_MAC_REF_CLK_CFG); ++ reg |= (1 << 13); ++ fh_pmu_set_reg(REG_PMU_PAD_MAC_REF_CLK_CFG, reg); ++#else ++ //(IOMUX_PADTYPE(17)(iomux_obj->pads[18]).reg)->bit.e = 0; ++ reg = fh_pmu_get_reg(REG_PMU_PAD_MAC_REF_CLK_CFG); ++ reg &= ~(1 << 13); ++ fh_pmu_set_reg(REG_PMU_PAD_MAC_REF_CLK_CFG, reg); ++#endif ++#ifdef IOMUX_DEBUG ++ fh_iomux_print(iomux_obj); ++#endif ++} +diff --git a/arch/arm/mach-fh/irq.c b/arch/arm/mach-fh/irq.c +new file mode 100644 +index 00000000..a17666fa +--- /dev/null ++++ b/arch/arm/mach-fh/irq.c +@@ -0,0 +1,151 @@ ++/* ++ * Fullhan FH board support ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++#include <linux/io.h> ++ ++#include <mach/hardware.h> ++#include <mach/system.h> ++#include <asm/mach/irq.h> ++ ++#include <mach/chip.h> ++#include <mach/fh_predefined.h> ++#include <mach/irqs.h> ++ ++static void fh_intc_ack(struct irq_data *d) ++{ ++ ++} ++static void fh_intc_enable(struct irq_data *d) ++{ ++ if (d->irq >= NR_INTERNAL_IRQS) ++ return; ++ ++ if (d->irq > 31) { ++ SET_REG_M(VINTC(REG_IRQ_EN_HIGH), 1 << (d->irq - 32), ++ 1 << (d->irq - 32)); ++ } else ++ SET_REG_M(VINTC(REG_IRQ_EN_LOW), 1 << d->irq, 1 << d->irq); ++ ++} ++static void fh_intc_disable(struct irq_data *d) ++{ ++ if (d->irq >= NR_INTERNAL_IRQS) ++ return; ++ if (d->irq > 31) ++ SET_REG_M(VINTC(REG_IRQ_EN_HIGH), 0, 1 << (d->irq - 32)); ++ else ++ SET_REG_M(VINTC(REG_IRQ_EN_LOW), 0, 1 << d->irq); ++} ++ ++static void fh_intc_mask(struct irq_data *d) ++{ ++ if (d->irq >= NR_INTERNAL_IRQS) ++ return; ++ if (d->irq > 31) { ++ SET_REG_M(VINTC(REG_IRQ_IRQMASK_HIGH), 1 << (d->irq - 32), ++ 1 << (d->irq - 32)); ++ } else ++ SET_REG_M(VINTC(REG_IRQ_IRQMASK_LOW), 1 << d->irq, 1 << d->irq); ++} ++ ++static void fh_intc_unmask(struct irq_data *d) ++{ ++ if (d->irq >= NR_INTERNAL_IRQS) ++ return; ++ if (d->irq > 31) ++ SET_REG_M(VINTC(REG_IRQ_IRQMASK_HIGH), 0, 1 << (d->irq - 32)); ++ else ++ SET_REG_M(VINTC(REG_IRQ_IRQMASK_LOW), 0, 1 << d->irq); ++} ++ ++#ifdef CONFIG_PM ++ ++static u32 wakeups_high; ++static u32 wakeups_low; ++static u32 backups_high; ++static u32 backups_low; ++ ++static int fh_intc_set_wake(struct irq_data *d, unsigned value) ++{ ++ if (unlikely(d->irq >= NR_IRQS)) ++ return -EINVAL; ++ ++ if (value) { ++ if (d->irq > 31) ++ wakeups_high |= (1 << (d->irq - 32)); ++ else ++ wakeups_low |= (1 << d->irq); ++ } else { ++ if (d->irq > 31) ++ wakeups_high &= ~(1 << (d->irq - 32)); ++ else ++ wakeups_low &= ~(1 << d->irq); ++ } ++ return 0; ++} ++ ++void fh_irq_suspend(void) ++{ ++ backups_high = GET_REG(VINTC(REG_IRQ_EN_HIGH)); ++ backups_low = GET_REG(VINTC(REG_IRQ_EN_LOW)); ++ ++ SET_REG(VINTC(REG_IRQ_EN_HIGH), wakeups_high); ++ SET_REG(VINTC(REG_IRQ_EN_LOW), wakeups_low); ++} ++ ++void fh_irq_resume(void) ++{ ++ SET_REG(VINTC(REG_IRQ_EN_HIGH), backups_high); ++ SET_REG(VINTC(REG_IRQ_EN_LOW), backups_low); ++} ++ ++#else ++#define fh_intc_set_wake NULL ++#endif ++ ++static struct irq_chip fh_irq_chip = { ++ .name = "FH_INTC", ++ .irq_ack = fh_intc_ack, ++ .irq_mask = fh_intc_mask, ++ .irq_unmask = fh_intc_unmask, ++ ++ .irq_enable = fh_intc_enable, ++ .irq_disable = fh_intc_disable, ++ .irq_set_wake = fh_intc_set_wake, ++}; ++ ++void __init fh_intc_init(void) ++{ ++ int i; ++ ++ //disable all interrupts ++ SET_REG(VINTC(REG_IRQ_EN_LOW), 0x0); ++ SET_REG(VINTC(REG_IRQ_EN_HIGH), 0x0); ++ ++ for (i = 0; i < NR_IRQS; i++) { ++ irq_set_chip_and_handler(i, &fh_irq_chip, handle_level_irq); ++ set_irq_flags(i, IRQF_VALID | IRQF_PROBE); ++ } ++ ++} +diff --git a/arch/arm/mach-fh/pinctrl.c b/arch/arm/mach-fh/pinctrl.c +new file mode 100644 +index 00000000..2b8f6ef1 +--- /dev/null ++++ b/arch/arm/mach-fh/pinctrl.c +@@ -0,0 +1,345 @@ ++#ifdef CONFIG_MACH_FH8830 ++#ifdef CONFIG_MACH_FH8830_QFN ++#include <mach/fh8830_iopad_qfn.h> ++#else ++#include <mach/fh8830_iopad_bga.h> ++#endif ++#endif ++ ++#ifdef CONFIG_MACH_FH8833 ++#ifdef CONFIG_MACH_FH8833_QFN56 ++#include <mach/fh8633_iopad_dvp.h> ++#else ++#include <mach/fh8833_iopad_mipi.h> ++#endif ++#endif ++ ++#if defined(CONFIG_MACH_FH8856) || defined(CONFIG_MACH_FH8852) ++#include <mach/board_config.h> ++#ifdef FH_BOARD_8856 ++#include <mach/fh8856_iopad.h> ++#endif ++#ifdef FH_BOARD_8852 ++#include <mach/fh8852_iopad.h> ++#endif ++#ifdef FH_BOARD_8858 ++#include <mach/fh8858_iopad.h> ++#endif ++#endif ++ ++#ifdef CONFIG_MACH_FH8626V100 ++#include <mach/board_config.h> ++#include <mach/fh8626v100_iopad.h> ++#endif ++ ++#ifdef CONFIG_MACH_ZY2 ++#include <mach/board_config.h> ++#include <mach/zy2_iopad.h> ++#endif ++ ++#include <mach/pinctrl.h> ++#include <linux/module.h> ++ ++/* #define FH_PINCTRL_DEBUG */ ++#ifdef FH_PINCTRL_DEBUG ++#define PRINT_DBG(fmt,args...) OS_PRINT(fmt,##args) ++#else ++#define PRINT_DBG(fmt,args...) do{} while(0) ++#endif ++ ++static PinCtrl_Object pinctrl_obj; ++OS_LIST fh_pinctrl_devices = OS_LIST_INIT(fh_pinctrl_devices); ++ ++static void fh_pinctrl_check_duplicate_pin(PinCtrl_Pin *pin, int start_pad) ++{ ++ int i; ++ PinCtrl_Pin *p; ++ if (!pin) ++ return; ++ for (i = start_pad; i < PAD_NUM; i++) { ++ p = pinctrl_obj.pinlist[i]; ++ if (p && p != pin && !strcmp(pin->func_name, p->func_name)) { ++ OS_PRINT("WARNING: %s already exists in pad %d\n", ++ p->func_name, p->pad_id); ++ } ++ } ++} ++ ++static int fh_pinctrl_func_select(PinCtrl_Pin *pin, unsigned int flag) ++{ ++ unsigned int reg; ++ ++ if(!pin) ++ { ++ OS_PRINT("ERROR: pin is null\n\n"); ++ return -1; ++ } ++ ++ if(flag & NEED_CHECK_PINLIST) ++ { ++ if(pinctrl_obj.pinlist[pin->pad_id]) ++ { ++ OS_PRINT("ERROR: pad %d has already been set\n\n", pin->pad_id); ++ return -2; ++ } ++ } ++ fh_pinctrl_check_duplicate_pin(pin, 0); ++ ++ reg = GET_REG(pinctrl_obj.vbase + pin->reg_offset); ++ ++ pin->reg = (PinCtrl_Register *)® ++ ++ pin->reg->bit.mfs = pin->func_sel; ++ ++ if (pin->pullup_pulldown == PUPD_DOWN) { ++ pin->reg->bit.pun = PUPD_DISABLE; ++ pin->reg->bit.pdn = PUPD_ENABLE; ++ } ++ else if(pin->pullup_pulldown == PUPD_UP) ++ { ++ pin->reg->bit.pun = PUPD_ENABLE; ++ pin->reg->bit.pdn = PUPD_DISABLE; ++ } ++ else ++ { ++ pin->reg->bit.pdn = PUPD_ZERO; ++ pin->reg->bit.pun = PUPD_ZERO; ++ } ++ ++ pin->reg->bit.ds = pin->driving_curr; ++ pin->reg->bit.st = 1; ++ ++ pin->reg->bit.ie = 1; ++ ++ SET_REG(pinctrl_obj.vbase + pin->reg_offset, pin->reg->dw); ++ ++ pinctrl_obj.pinlist[pin->pad_id] = pin; ++ ++ return 0; ++} ++ ++static int fh_pinctrl_mux_switch(PinCtrl_Mux *mux, unsigned int flag) ++{ ++ if(mux->cur_pin >= MUX_NUM) ++ { ++ OS_PRINT("ERROR: selected function is not exist, sel_func=%d\n\n", mux->cur_pin); ++ return -3; ++ } ++ ++ if(!mux->mux_pin[mux->cur_pin]) ++ { ++ OS_PRINT("ERROR: mux->mux_pin[%d] has no pin\n\n", mux->cur_pin); ++ return -4; ++ } ++ ++ PRINT_DBG("\t%s[%d]\n", mux->mux_pin[mux->cur_pin]->func_name, mux->cur_pin); ++ return fh_pinctrl_func_select(mux->mux_pin[mux->cur_pin], flag); ++} ++ ++ ++static int fh_pinctrl_device_switch(PinCtrl_Device *dev, unsigned int flag) ++{ ++ int i, ret; ++ for(i=0; i<dev->mux_count; i++) ++ { ++ unsigned int *mux_addr = (unsigned int *)((unsigned int)dev ++ + sizeof(*dev) - 4 + i*4); ++ PinCtrl_Mux *mux = (PinCtrl_Mux *)(*mux_addr); ++ ++ ret = fh_pinctrl_mux_switch(mux, flag); ++ if(ret) ++ { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static PinCtrl_Device * fh_pinctrl_get_device_by_name(char *name) ++{ ++ PinCtrl_Device *dev = OS_NULL; ++ ++ list_for_each_entry(dev, &fh_pinctrl_devices, list) ++ { ++ if(!strcmp(name, dev->dev_name)) ++ { ++ return dev; ++ } ++ } ++ ++ return 0; ++} ++ ++int fh_pinctrl_check_pinlist(void) ++{ ++ int i; ++ for (i=0; i<PAD_NUM; i++) { ++ if (!pinctrl_obj.pinlist[i]) { ++ PRINT_DBG("ERROR: pad %d is still empty\n", i); ++ } ++ } ++ ++ return 0; ++} ++ ++static int fh_pinctrl_init_devices(char** devlist, int listsize, unsigned int flag) ++{ ++ int i, ret; ++ PinCtrl_Device *dev; ++ ++ memset(pinctrl_obj.pinlist, 0, sizeof(pinctrl_obj.pinlist)); ++ ++ for(i=0; i<listsize; i++) ++ { ++ dev = fh_pinctrl_get_device_by_name(devlist[i]); ++ ++ if(!dev) ++ { ++ OS_PRINT("ERROR: cannot find device %s\n", devlist[i]); ++ return -5; ++ } ++ ++ PRINT_DBG("%s:\n", dev->dev_name); ++ ret = fh_pinctrl_device_switch(dev, flag); ++ PRINT_DBG("\n"); ++ if(ret) ++ { ++ return ret; ++ } ++ ++ } ++ ++ fh_pinctrl_check_pinlist(); ++ ++ return 0; ++ ++} ++ ++static void fh_pinctrl_init_pin(void) ++{ ++ int i; ++ ++ for(i=0; i<PAD_NUM; i++) ++ { ++ PinCtrl_Pin *pin = pinctrl_obj.pinlist[i]; ++ if(!pin) ++ { ++ unsigned int reg; ++ PRINT_DBG("ERROR: pad %d is empty\n", i); ++ reg = GET_REG(pinctrl_obj.vbase + i * 4); ++ reg &= ~(0x1000); ++ SET_REG(pinctrl_obj.vbase + i * 4, reg); ++ continue; ++ } ++ pin->reg->dw = GET_REG(pinctrl_obj.vbase + ++ pin->reg_offset); ++ ++ pin->input_enable = pin->reg->bit.ie; ++ pin->output_enable = pin->reg->bit.oe; ++ } ++} ++ ++ ++void fh_pinctrl_init(unsigned int base) ++{ ++ pinctrl_obj.vbase = pinctrl_obj.pbase = (void *)base; ++ ++ fh_pinctrl_init_devicelist(&fh_pinctrl_devices); ++ fh_pinctrl_init_devices(fh_pinctrl_selected_devices, ++ ARRAY_SIZE(fh_pinctrl_selected_devices), ++ NEED_CHECK_PINLIST); ++ fh_pinctrl_init_pin(); ++} ++ ++void fh_pinctrl_prt(struct seq_file *sfile) ++{ ++ int i; ++ seq_printf(sfile, "%2s\t%8s\t%4s\t%8s\t%4s\t%4s\t%4s\t%4s\n", ++ "id", "name", "addr", "reg", "sel", "ie", "oe", "pupd"); ++ for(i=0; i<PAD_NUM; i++) ++ { ++ if(!pinctrl_obj.pinlist[i]) ++ { ++ OS_PRINT("ERROR: pad %d is empty\n", i); ++ continue; ++ } ++ fh_pinctrl_check_duplicate_pin(pinctrl_obj.pinlist[i], i+1); ++ seq_printf(sfile, "%02d\t%8s\t0x%04x\t0x%08x\t%04d\t%04d\t%04d\t%04d\n", ++ pinctrl_obj.pinlist[i]->pad_id, ++ pinctrl_obj.pinlist[i]->func_name, ++ pinctrl_obj.pinlist[i]->reg_offset + 0x80, ++ GET_REG(pinctrl_obj.vbase + pinctrl_obj.pinlist[i]->reg_offset), ++ pinctrl_obj.pinlist[i]->func_sel, ++ pinctrl_obj.pinlist[i]->input_enable, ++ pinctrl_obj.pinlist[i]->output_enable, ++ pinctrl_obj.pinlist[i]->pullup_pulldown); ++ } ++ ++} ++ ++ ++int fh_pinctrl_smux(char *devname, char* muxname, int muxsel, unsigned int flag) ++{ ++ PinCtrl_Device *dev; ++ int i, ret; ++ ++ dev = fh_pinctrl_get_device_by_name(devname); ++ ++ if(!dev) ++ { ++ OS_PRINT("ERROR: cannot find device %s\n", devname); ++ return -4; ++ } ++ ++ for(i=0; i<dev->mux_count; i++) ++ { ++ unsigned int *mux_addr = (unsigned int *)((unsigned int)dev ++ + sizeof(*dev) - 4 + i*4); ++ PinCtrl_Mux *mux = (PinCtrl_Mux *)(*mux_addr); ++ ++ if(!strcmp(muxname, mux->mux_pin[0]->func_name)) ++ { ++ mux->cur_pin = muxsel; ++ ret = fh_pinctrl_mux_switch(mux, flag); ++ return ret; ++ } ++ } ++ ++ if(i == dev->mux_count) ++ { ++ OS_PRINT("ERROR: cannot find mux %s of device %s\n", muxname, devname); ++ return -6; ++ } ++ ++ fh_pinctrl_check_pinlist(); ++ ++ return 0; ++} ++EXPORT_SYMBOL(fh_pinctrl_smux); ++ ++int fh_pinctrl_sdev(char *devname, unsigned int flag) ++{ ++ PinCtrl_Device *dev; ++ int ret; ++ ++ dev = fh_pinctrl_get_device_by_name(devname); ++ if(!dev) ++ { ++ OS_PRINT("ERROR: cannot find device %s\n", devname); ++ return -7; ++ } ++ ++ OS_PRINT("%s:\n", dev->dev_name); ++ ret = fh_pinctrl_device_switch(dev, flag); ++ OS_PRINT("\n"); ++ if(ret) ++ { ++ return ret; ++ } ++ ++ fh_pinctrl_check_pinlist(); ++ ++ return 0; ++} ++EXPORT_SYMBOL(fh_pinctrl_sdev); +diff --git a/arch/arm/mach-fh/pm.c b/arch/arm/mach-fh/pm.c +new file mode 100644 +index 00000000..a7ec90b5 +--- /dev/null ++++ b/arch/arm/mach-fh/pm.c +@@ -0,0 +1,223 @@ ++/* ++ * FH Power Management Routines ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/pm.h> ++#include <linux/suspend.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/clk.h> ++#include <linux/spinlock.h> ++#include <linux/io.h> ++ ++#include <asm/cacheflush.h> ++#include <asm/delay.h> ++ ++#include <mach/sram.h> ++#include <mach/system.h> ++#include <mach/io.h> ++#include <mach/gpio.h> ++#include <mach/ddrc.h> ++#include <mach/pmu.h> ++ ++#ifdef CONFIG_PM ++static u32 old_clk_gate = 0; ++ ++static void (*fh_sram_suspend)(void); ++ ++static inline void fh_pm_pll0_to_xtal(void) ++{ ++ u32 reg; ++ ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg &= ~(0x1); ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++} ++ ++static inline void fh_pm_xtal_to_pll0(void) ++{ ++ u32 reg; ++ ++ reg = fh_pmu_get_reg(REG_PMU_SYS_CTRL); ++ reg |= 0x1; ++ fh_pmu_set_reg(REG_PMU_SYS_CTRL, reg); ++} ++ ++static inline void fh_pm_gate_clocks(void) ++{ ++ u32 reg; ++ old_clk_gate = fh_pmu_get_reg(REG_PMU_CLK_GATE); ++ reg = fh_pmu_get_reg(REG_PMU_CLK_GATE); ++ reg |= 0x7fff3fb1; ++ fh_pmu_set_reg(REG_PMU_CLK_GATE, reg); ++} ++ ++static inline void fh_pm_ungate_clocks(void) ++{ ++ u32 reg; ++ ++ reg = old_clk_gate; ++ fh_pmu_set_reg(REG_PMU_CLK_GATE, reg); ++} ++ ++ ++static void fh_sram_push(void *dest, void *src, unsigned int size) ++{ ++ memcpy(dest, src, size); ++ flush_icache_range((unsigned long)dest, (unsigned long)(dest + size)); ++} ++ ++static int fh_pm_valid_state(suspend_state_t state) ++{ ++ switch (state) { ++ case PM_SUSPEND_ON: ++ case PM_SUSPEND_STANDBY: ++ case PM_SUSPEND_MEM: ++ return 1; ++ ++ default: ++ return 0; ++ } ++} ++ ++static void fh_pm_suspend_to_ram(void) ++{ ++ fh_pm_pll0_to_xtal(); ++ fh_pm_gate_clocks(); ++ ++ fh_sram_suspend(); ++ ++ fh_pm_ungate_clocks(); ++ fh_pm_xtal_to_pll0(); ++} ++ ++static inline void fh_ddrc_selfrefresh_enable(void) ++{ ++ u32 reg; ++ ++ /* ++ * Ensure that the Cadence DDR Controller is idle, ++ * that is when the controller_busy signal is low. ++ */ ++ do { ++ reg = readl(VA_DDRC_REG_BASE + OFFSET_DENAL_CTL_57); ++ } while (reg & DDRC_CONTROLLER_BUSY); ++ ++ /* ++ * Put the memories into self-refresh mode ++ * by issuing one of the self-refresh entry commands ++ * through the Low Power Control Module ++ */ ++ writel(DDRC_LPI_SR_WAKEUP_TIME | DDRC_LP_CMD_SELFREFRESH | DDRC_CKSRX_DELAY, ++ VA_DDRC_REG_BASE + OFFSET_DENAL_CTL_31); ++ ++ //wait no more ++ /* ++ do ++ { ++ reg = readl(VA_DDRC_REG_BASE + OFFSET_DENAL_CTL_97); ++ } ++ while(reg & DDRC_CKE_STATUS); ++ */ ++} ++ ++static inline void fh_ddrc_selfrefresh_disable(void) ++{ ++ //Exit any low power state ++ writel(DDRC_LPI_SR_WAKEUP_TIME | DDRC_LP_CMD_EXITLOWPOWER | DDRC_CKSRX_DELAY, ++ VA_DDRC_REG_BASE + OFFSET_DENAL_CTL_31); ++} ++ ++static void fh_pm_suspend_to_cache(void) ++{ ++ asm volatile("mov r1, #0\n\t" ++ "mcr p15, 0, r1, c7, c10, 4\n\t" ++ "mcr p15, 0, r1, c7, c0, 4\n\t" ++ : /* no output */ ++ : /* no input */ ++ : "r1"); ++ ++ fh_ddrc_selfrefresh_enable(); ++ ++ asm volatile("mov r1, #0\n\t" ++ "mcr p15, 0, r1, c7, c10, 4\n\t" ++ "mcr p15, 0, r1, c7, c0, 4\n\t" ++ : /* no output */ ++ : /* no input */ ++ : "r1"); ++ fh_ddrc_selfrefresh_disable(); ++} ++ ++static int fh_pm_enter(suspend_state_t state) ++{ ++ int ret = 0; ++ ++ fh_irq_suspend(); ++ fh_gpio_irq_suspend(); ++ ++ switch (state) { ++ case PM_SUSPEND_ON: ++ cpu_do_idle(); ++ break; ++ case PM_SUSPEND_STANDBY: ++ fh_pm_suspend_to_cache(); ++ break; ++ case PM_SUSPEND_MEM: ++ fh_pm_suspend_to_ram(); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ fh_gpio_irq_resume(); ++ fh_irq_resume(); ++ ++ return ret; ++} ++ ++static const struct platform_suspend_ops fh_pm_ops = { ++ .enter = fh_pm_enter, ++ .valid = fh_pm_valid_state, ++}; ++ ++static int __init fh_pm_probe(struct platform_device *pdev) ++{ ++ fh_sram_suspend = sram_alloc(fh_cpu_suspend_sz, NULL); ++ if (!fh_sram_suspend) { ++ dev_err(&pdev->dev, "cannot allocate SRAM memory\n"); ++ return -ENOMEM; ++ } ++ fh_sram_push(fh_sram_suspend, fh_cpu_suspend, ++ fh_cpu_suspend_sz); ++ suspend_set_ops(&fh_pm_ops); ++ ++ return 0; ++} ++ ++static int __exit fh_pm_remove(struct platform_device *pdev) ++{ ++ sram_free(fh_sram_suspend, fh_cpu_suspend_sz); ++ return 0; ++} ++ ++static struct platform_driver fh_pm_driver = { ++ .driver = ++ { ++ .name = "pm-fh", ++ .owner = THIS_MODULE, ++ }, ++ .remove = __exit_p(fh_pm_remove), ++}; ++ ++static int __init fh_pm_init(void) ++{ ++ return platform_driver_probe(&fh_pm_driver, fh_pm_probe); ++} ++late_initcall(fh_pm_init); ++#endif +diff --git a/arch/arm/mach-fh/pmu.c b/arch/arm/mach-fh/pmu.c +new file mode 100644 +index 00000000..ed97a53f +--- /dev/null ++++ b/arch/arm/mach-fh/pmu.c +@@ -0,0 +1,48 @@ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <asm/io.h> ++ ++#include <mach/io.h> ++#include <mach/chip.h> ++#include <mach/pmu.h> ++ ++static int fh_pmu_flag_stop = 0; ++ ++void fh_pmu_stop(void) ++{ ++ fh_pmu_flag_stop = 1; ++} ++EXPORT_SYMBOL(fh_pmu_stop); ++ ++void fh_pmu_set_reg(u32 offset, u32 data) ++{ ++ if (fh_pmu_flag_stop) ++ return; ++ ++ if (offset > PMU_REG_SIZE) { ++ pr_err("fh_pmu_set_reg: offset is out of range"); ++ return; ++ } ++ writel(data, VPMU(PMU_REG_BASE + offset)); ++} ++EXPORT_SYMBOL(fh_pmu_set_reg); ++ ++u32 fh_pmu_get_reg(u32 offset) ++{ ++ if (fh_pmu_flag_stop) ++ return 0; ++ ++ if (offset > PMU_REG_SIZE) { ++ pr_err("fh_pmu_get_reg: offset is out of range"); ++ return 0; ++ } ++ return readl(VPMU(PMU_REG_BASE + offset)); ++} ++EXPORT_SYMBOL(fh_pmu_get_reg); ++ ++int fh_pmu_init(void) ++{ ++ return fh_chipid_init(); ++} +diff --git a/arch/arm/mach-fh/sleep.S b/arch/arm/mach-fh/sleep.S +new file mode 100644 +index 00000000..5eb4ac23 +--- /dev/null ++++ b/arch/arm/mach-fh/sleep.S +@@ -0,0 +1,144 @@ ++#include <linux/linkage.h> ++#include <asm/assembler.h> ++#include <mach/chip.h> ++#include <mach/io.h> ++#include <mach/ddrc.h> ++ ++#ifdef CONFIG_PM ++#define PMU_MASK_SWITCH_PLL0 0x1 ++#define PMU_MASK_DDR_SEL 0x1000000 ++#define PMU_MASK_DDR_DIV 0xff ++#define PMU_MASK_PLL1_PDN 0x80000000 ++ ++ ++ .macro wait_ddrc_idle ++1: ldr r3, [r1, #OFFSET_DENAL_CTL_57] ++ tst r3, #DDRC_CONTROLLER_BUSY ++ bne 1b ++ .endm ++ ++ ++ .macro enable_ddrc_selfrefresh ++ ldr r3, .fh_ddrc_cmd_en_self_refresh ++ str r3, [r1, #OFFSET_DENAL_CTL_31] ++ .endm ++ ++ ++ .macro wait_ddrc_cke ++1: ldr r3, [r1, #OFFSET_DENAL_CTL_97] ++ tst r3, #DDRC_CKE_STATUS ++ bne 1b ++ .endm ++ ++ ++ .macro disable_ddrc_selfrefresh ++ ldr r3, .fh_ddrc_cmd_dis_self_refresh ++ str r3, [r1, #OFFSET_DENAL_CTL_31] ++ .endm ++ ++ ++ .macro ddr_to_pll0 ++ ldr r3, [r2, #REG_PMU_CLK_SEL] ++ bic r3, r3, #PMU_MASK_DDR_SEL ++ str r3, [r2, #REG_PMU_CLK_SEL] ++ .endm ++ ++ ++ .macro ddr_to_pll1 ++ ldr r3, [r2, #REG_PMU_CLK_SEL] ++ orr r3, r3, #PMU_MASK_DDR_SEL ++ str r3, [r2, #REG_PMU_CLK_SEL] ++ .endm ++ ++#if 1 ++ .macro ddr_dec_feq ++ ldr r3, [r2, #REG_PMU_CLK_DIV1] ++ orr r3, r3, #PMU_MASK_DDR_DIV ++ str r3, [r2, #REG_PMU_CLK_SEL] ++ .endm ++ ++ ++ .macro ddr_inc_feq ++ ldr r3, [r2, #REG_PMU_CLK_DIV1] ++ bic r3, r3, #PMU_MASK_DDR_DIV ++ orr r3, r3, #0x1 ++ str r3, [r2, #REG_PMU_CLK_SEL] ++ .endm ++ ++ ++ .macro pll1_power_down ++ ldr r3, [r2, #REG_PMU_PLL1_CTRL] ++ bic r3, r3, #PMU_MASK_PLL1_PDN ++ str r3, [r2, #REG_PMU_PLL1_CTRL] ++ .endm ++ ++ ++ .macro pll1_power_on ++ ldr r3, [r2, #REG_PMU_PLL1_CTRL] ++ orr r3, r3, #PMU_MASK_PLL1_PDN ++ str r3, [r2, #REG_PMU_PLL1_CTRL] ++ .endm ++#endif ++ ++ .text ++ENTRY(fh_cpu_suspend) ++ ++ stmfd sp!, {r0-r12, lr} @ save registers on stack ++ ++ /* ++ ++ * Register usage: ++ * R1 = Base address of DDRC ++ * R2 = Base register for PMU ++ * R3 = temporary register ++ * R4 = temporary register ++ * ++ * R9 = Test address ++ */ ++ ++ ldr r1, .fh_va_base_ddrc ++ ldr r2, .fh_va_base_pmu ++ ldr r9, .fh_va_test_addr ++ ++ wait_ddrc_idle ++ enable_ddrc_selfrefresh ++ wait_ddrc_cke ++ ++ @ddr_dec_feq ++ ddr_to_pll0 ++ ++ @pll1_power_down ++ ++ mcr p15, 0, r0, c7, c10, 4 @ Data Synchronization Barrier operation ++ mcr p15, 0, r0, c7, c0, 4 @ Wait-for-Interrupt ++ ++ @pll1_power_on ++ ++ @ddr_inc_feq ++ ddr_to_pll1 ++ ++ disable_ddrc_selfrefresh ++ ++ ldmfd sp!, {r0-r12, pc} ++ ++ENDPROC(fh_cpu_suspend) ++ ++.fh_va_base_ddrc: ++ .word VA_DDRC_REG_BASE ++ ++.fh_va_base_pmu: ++ .word VA_PMU_REG_BASE ++ ++.fh_va_test_addr: ++ .word 0xc03efef0 ++ ++.fh_ddrc_cmd_en_self_refresh: ++ .word 0x3000a01 ++ ++.fh_ddrc_cmd_dis_self_refresh: ++ .word 0x3000101 ++ ++ENTRY(fh_cpu_suspend_sz) ++ .word . - fh_cpu_suspend ++ENDPROC(fh_cpu_suspend_sz) ++#endif +diff --git a/arch/arm/mach-fh/sram.c b/arch/arm/mach-fh/sram.c +new file mode 100644 +index 00000000..4df4838b +--- /dev/null ++++ b/arch/arm/mach-fh/sram.c +@@ -0,0 +1,53 @@ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/genalloc.h> ++#include <asm-generic/sizes.h> ++#include <mach/sram.h> ++#include <mach/chip.h> ++#include <mach/io.h> ++ ++static struct gen_pool *sram_pool; ++ ++void *sram_alloc(size_t len, dma_addr_t *dma) ++{ ++ unsigned long vaddr; ++ ++ if (!sram_pool) ++ return NULL; ++ ++ vaddr = gen_pool_alloc(sram_pool, len); ++ if (!vaddr) ++ return NULL; ++ ++ return (void *)vaddr; ++} ++EXPORT_SYMBOL(sram_alloc); ++ ++void sram_free(void *addr, size_t len) ++{ ++ gen_pool_free(sram_pool, (unsigned long) addr, len); ++} ++EXPORT_SYMBOL(sram_free); ++ ++ ++/* ++ * REVISIT This supports CPU and DMA access to/from SRAM, but it ++ * doesn't (yet?) support some other notable uses of SRAM: as TCM ++ * for data and/or instructions; and holding code needed to enter ++ * and exit suspend states (while DRAM can't be used). ++ */ ++static int __init sram_init(void) ++{ ++ int status = 0; ++ ++ sram_pool = gen_pool_create(ilog2(SRAM_GRANULARITY), -1); ++ if (!sram_pool) ++ status = -ENOMEM; ++ ++ if (sram_pool) ++ status = gen_pool_add(sram_pool, VA_RAM_REG_BASE, SRAM_SIZE, -1); ++ WARN_ON(status < 0); ++ return status; ++} ++core_initcall(sram_init); ++ +diff --git a/arch/arm/mach-fh/time.c b/arch/arm/mach-fh/time.c +new file mode 100644 +index 00000000..bde1f79e +--- /dev/null ++++ b/arch/arm/mach-fh/time.c +@@ -0,0 +1,281 @@ ++/* ++ * FH timer subsystem ++ * ++ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/interrupt.h> ++#include <linux/clocksource.h> ++#include <linux/clockchips.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/platform_device.h> ++#include <linux/sched.h> ++#include <linux/time.h> ++#include <linux/irqreturn.h> ++#include <linux/math64.h> ++#include <linux/delay.h> ++ ++#include <asm/system.h> ++#include <asm/mach-types.h> ++#include <asm/sched_clock.h> ++#include <asm/mach/irq.h> ++#include <asm/mach/time.h> ++ ++#include <mach/hardware.h> ++#include <mach/timex.h> ++#include <mach/chip.h> ++#include <mach/fh_predefined.h> ++#include <mach/irqs.h> ++#include <mach/pmu.h> ++#include <mach/clock.h> ++#include <mach/fh_simple_timer.h> ++ ++ ++static struct clock_event_device clockevent_fh; ++static struct clocksource clocksource_fh; ++#ifndef CONFIG_USE_PTS_AS_CLOCKSOURCE ++static unsigned int prev_cycle; ++#endif ++ ++struct clk *timer_clk, *pts_clk; ++ ++/* ++ * clockevent ++ */ ++static int fh_set_next_event(unsigned long cycles, ++ struct clock_event_device *evt) ++{ ++ int sync_cnt = 0; ++ ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(1)), 0x00, 0x1); ++ /* zy/ticket/100 : update apb Timer LOADCNT */ ++ /* CURRENTVALE could,t be start from new LOADCOUNT */ ++ /* cause is timer clk 1M hz and apb is 150M hz */ ++ /* check current cnt for it is disabled */ ++ while (GET_REG(VTIMER(REG_TIMER_CUR_VAL(1))) != 0) { ++ sync_cnt++; ++ if (sync_cnt >= 50) { ++ /* typical cnt is 5 when in 1M timer clk */ ++ /* so here use 50 to check whether it is err */ ++ pr_err("timer problem,can't disable"); ++ } ++ } ++ ++ SET_REG(VTIMER(REG_TIMER_LOADCNT(1)), cycles); ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(1)), 0x01, 0x1); ++#ifdef CONFIG_ARCH_FH8810 ++ unsigned int curr_val; ++ ++ curr_val = GET_REG(VTIMER(REG_TIMER_CUR_VAL(1))) ; ++ if (curr_val > 0x80000000) { ++ panic("timer curr %u, want cycles %lu\n", curr_val, cycles); ++ ++ SET_REG_M(VTIMER(REG_TIMER_CTRL_REG(1)), 0x01, 0x1); ++ SET_REG(VTIMER(REG_TIMER_LOADCNT(1)), cycles); ++ ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0xfff7ffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL) != 0xffffffff) ++ ; ++ } ++#endif ++ return 0; ++} ++ ++static void fh_set_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++ switch (mode) { ++ case CLOCK_EVT_MODE_PERIODIC: ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(1)), 0x3); ++ SET_REG(VTIMER(REG_TIMER_LOADCNT(1)), TIMER_CLK / HZ); ++#ifdef CONFIG_ARCH_FH8810 ++ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0xfff7ffff); ++ while (fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL) != 0xffffffff) ++ ; ++#endif ++ break; ++ case CLOCK_EVT_MODE_ONESHOT: ++ break; ++ case CLOCK_EVT_MODE_UNUSED: ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(1)), 0x0); ++ break; ++ case CLOCK_EVT_MODE_RESUME: ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(1)), 0x3); ++ break; ++ } ++} ++ ++ ++static irqreturn_t fh_clock_timer_interrupt_handle(int irq, void *dev_id) ++{ ++ unsigned int status; ++ status = GET_REG(VTIMER(REG_TIMERS_INTSTATUS)); ++ ++ ++#ifdef CONFIG_FH_SIMPLE_TIMER ++ if (status & (1 << SIMPLE_TIMER_BASE)) ++ fh_simple_timer_interrupt(); ++#endif ++ if (status & 0x2) { ++ GET_REG(VTIMER(REG_TIMER_EOI_REG(1))); ++ clockevent_fh.event_handler(&clockevent_fh); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction fh_eventtimer_irq = { ++ .name = "System Timer Tick", ++ .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, ++ .handler = fh_clock_timer_interrupt_handle, ++ .dev_id = &clockevent_fh, ++}; ++ ++ ++static void fh_timer_resources(void) ++{ ++ ++} ++static DEFINE_CLOCK_DATA(cd); ++ ++static void notrace fh_update_sched_clock(void) ++{ ++ const cycle_t cyc = clocksource_fh.read(&clocksource_fh); ++ update_sched_clock(&cd, cyc, (u32)~0); ++} ++ ++unsigned long long notrace sched_clock(void) ++{ ++ const cycle_t cyc = clocksource_fh.read(&clocksource_fh); ++ ++ return cyc_to_sched_clock(&cd, cyc, (u32)~0); ++} ++ ++static void fh_clocksource_init(void) ++{ ++#ifdef CONFIG_USE_PTS_AS_CLOCKSOURCE ++ unsigned long clock_tick_rate = pts_clk->frequency; ++#else ++ unsigned long clock_tick_rate = timer_clk->frequency; ++ prev_cycle = 0; ++#endif ++ ++ if (clocksource_register_hz(&clocksource_fh, clock_tick_rate)) ++ panic("register clocksouce :%s error\n", clocksource_fh.name); ++ ++ printk(KERN_INFO "timer mult: 0x%x, timer shift: 0x%x\n", ++ clocksource_fh.mult, clocksource_fh.shift); ++ ++ /* force check the mult/shift of clocksource */ ++ init_fixed_sched_clock(&cd, fh_update_sched_clock, 32, clock_tick_rate, ++ clocksource_fh.mult, clocksource_fh.shift); ++ ++ SET_REG(VTIMER(REG_TIMER_CTRL_REG(0)), 0x5); ++} ++ ++static cycle_t fh_clocksource_read(struct clocksource *cs) ++{ ++#ifdef CONFIG_USE_PTS_AS_CLOCKSOURCE ++#if (defined(CONFIG_ARCH_FH8856) || defined(CONFIG_ARCH_ZY2) \ ++ || defined(CONFIG_ARCH_FH8626V100)) ++ fh_pmu_set_reg(REG_PMU_PTSLO, 0x01); ++ u64 high = fh_pmu_get_reg(REG_PMU_PTSHI); ++ u64 low = fh_pmu_get_reg(REG_PMU_PTSLO); ++ u64 pts = (((unsigned long long)high)<<32)|((unsigned long long)low); ++ return pts; ++#else ++ return GET_REG(VPAE(REG_PAE_PTS_REG)); ++#endif ++#else ++ unsigned int cycle; ++ cycle = ~GET_REG(VTIMER(REG_TIMER_CUR_VAL(0))); ++#ifdef CONFIG_ARCH_FH8810 ++ if (unlikely(prev_cycle > cycle)) ++ cycle = ~GET_REG(VTIMER(REG_TIMER_CUR_VAL(0))); ++ prev_cycle = cycle; ++#endif ++ return cycle; ++#endif ++} ++ ++static void fh_clockevent_init(void) ++{ ++ setup_irq(TMR0_IRQ, &fh_eventtimer_irq); ++ clockevent_fh.mult = div_sc(timer_clk->frequency, ++ NSEC_PER_SEC, clockevent_fh.shift); ++ clockevent_fh.max_delta_ns = clockevent_delta2ns(0xffffffff, ++ &clockevent_fh); ++ ++ clockevent_fh.min_delta_ns = clockevent_delta2ns(0xf, &clockevent_fh); ++ ++ clockevent_fh.cpumask = cpumask_of(0); ++ clockevents_register_device(&clockevent_fh); ++} ++ ++ ++static void __init fh_timer_init(void) ++{ ++ ++ timer_clk = clk_get(NULL, "tmr0_clk"); ++ pts_clk = clk_get(NULL, "pts_clk"); ++ ++#ifdef CONFIG_USE_PTS_AS_CLOCKSOURCE ++ clk_set_rate(pts_clk, PAE_PTS_CLK); ++ clk_enable(pts_clk); ++ pts_clk->frequency = PAE_PTS_CLK; ++#if (defined(CONFIG_ARCH_FH8856) || defined(CONFIG_ARCH_ZY2) \ ++ || defined(CONFIG_ARCH_FH8626V100)) ++ u32 pmuuser0 = fh_pmu_get_reg(REG_PMU_USER0); ++ pmuuser0 &= ~(0x1); /*pts hw refresh mode */ ++ fh_pmu_set_reg(REG_PMU_USER0, pmuuser0); ++#endif ++#endif ++ ++ clk_set_rate(timer_clk, TIMER_CLK); ++ clk_enable(timer_clk); ++ ++ timer_clk->frequency = TIMER_CLK; ++ ++ if (IS_ERR(timer_clk) || IS_ERR(pts_clk)) ++ pr_err("fh_timer: clock is not defined\n"); ++ ++ ++ fh_timer_resources(); ++ fh_clocksource_init(); ++ fh_clockevent_init(); ++#ifdef CONFIG_FH_SIMPLE_TIMER ++ fh_simple_timer_init(); ++#endif ++} ++ ++ ++ ++static struct clocksource clocksource_fh = { ++ .name = "fh_clocksource", ++ .rating = 300, ++ .read = fh_clocksource_read, ++ .mask = CLOCKSOURCE_MASK(32), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++}; ++ ++ ++static struct clock_event_device clockevent_fh = { ++ .name = "fh_clockevent", ++ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, ++ .shift = 32, ++ .set_next_event = fh_set_next_event, ++ .set_mode = fh_set_mode, ++}; ++ ++struct sys_timer fh_timer = { ++ .init = fh_timer_init, ++}; +diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types +index 3b3776d0..4e198455 100644 +--- a/arch/arm/tools/mach-types ++++ b/arch/arm/tools/mach-types +@@ -1113,3 +1113,10 @@ blissc MACH_BLISSC BLISSC 3491 + thales_adc MACH_THALES_ADC THALES_ADC 3492 + ubisys_p9d_evp MACH_UBISYS_P9D_EVP UBISYS_P9D_EVP 3493 + atdgp318 MACH_ATDGP318 ATDGP318 3494 ++fh8810 MACH_FH8810 FH8810 9999 ++fh8830 MACH_FH8830 FH8830 9999 ++fh8833 MACH_FH8833 FH8833 9999 ++fh8856 MACH_FH8856 FH8856 9999 ++fh8852 MACH_FH8852 FH8852 9999 ++fh8626v100 MACH_FH8626V100 FH8626V100 9999 ++zy2 MACH_ZY2 ZY2 9999 +diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts +deleted file mode 120000 +index 7cb65789..00000000 +--- a/arch/microblaze/boot/dts/system.dts ++++ /dev/null +@@ -1 +0,0 @@ +-../../platform/generic/system.dts +\ No newline at end of file +diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts +new file mode 100644 +index 00000000..3f85df2b +--- /dev/null ++++ b/arch/microblaze/boot/dts/system.dts +@@ -0,0 +1,367 @@ ++/* ++ * Device Tree Generator version: 1.1 ++ * ++ * (C) Copyright 2007-2008 Xilinx, Inc. ++ * (C) Copyright 2007-2009 Michal Simek ++ * ++ * Michal SIMEK <monstr@monstr.eu> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ * CAUTION: This file is automatically generated by libgen. ++ * Version: Xilinx EDK 10.1.03 EDK_K_SP3.6 ++ * ++ * XPS project directory: Xilinx-ML505-ll_temac-sgdma-MMU-FDT-edk101 ++ */ ++ ++/dts-v1/; ++/ { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "xlnx,microblaze"; ++ hard-reset-gpios = <&LEDs_8Bit 2 1>; ++ model = "testing"; ++ DDR2_SDRAM: memory@90000000 { ++ device_type = "memory"; ++ reg = < 0x90000000 0x10000000 >; ++ } ; ++ aliases { ++ ethernet0 = &Hard_Ethernet_MAC; ++ serial0 = &RS232_Uart_1; ++ } ; ++ chosen { ++ bootargs = "console=ttyUL0,115200 highres=on"; ++ linux,stdout-path = "/plb@0/serial@84000000"; ++ } ; ++ cpus { ++ #address-cells = <1>; ++ #cpus = <0x1>; ++ #size-cells = <0>; ++ microblaze_0: cpu@0 { ++ clock-frequency = <125000000>; ++ compatible = "xlnx,microblaze-7.10.d"; ++ d-cache-baseaddr = <0x90000000>; ++ d-cache-highaddr = <0x9fffffff>; ++ d-cache-line-size = <0x10>; ++ d-cache-size = <0x2000>; ++ device_type = "cpu"; ++ i-cache-baseaddr = <0x90000000>; ++ i-cache-highaddr = <0x9fffffff>; ++ i-cache-line-size = <0x10>; ++ i-cache-size = <0x2000>; ++ model = "microblaze,7.10.d"; ++ reg = <0>; ++ timebase-frequency = <125000000>; ++ xlnx,addr-tag-bits = <0xf>; ++ xlnx,allow-dcache-wr = <0x1>; ++ xlnx,allow-icache-wr = <0x1>; ++ xlnx,area-optimized = <0x0>; ++ xlnx,cache-byte-size = <0x2000>; ++ xlnx,d-lmb = <0x1>; ++ xlnx,d-opb = <0x0>; ++ xlnx,d-plb = <0x1>; ++ xlnx,data-size = <0x20>; ++ xlnx,dcache-addr-tag = <0xf>; ++ xlnx,dcache-always-used = <0x1>; ++ xlnx,dcache-byte-size = <0x2000>; ++ xlnx,dcache-line-len = <0x4>; ++ xlnx,dcache-use-fsl = <0x1>; ++ xlnx,debug-enabled = <0x1>; ++ xlnx,div-zero-exception = <0x1>; ++ xlnx,dopb-bus-exception = <0x0>; ++ xlnx,dynamic-bus-sizing = <0x1>; ++ xlnx,edge-is-positive = <0x1>; ++ xlnx,family = "virtex5"; ++ xlnx,endianness = <0x1>; ++ xlnx,fpu-exception = <0x1>; ++ xlnx,fsl-data-size = <0x20>; ++ xlnx,fsl-exception = <0x0>; ++ xlnx,fsl-links = <0x0>; ++ xlnx,i-lmb = <0x1>; ++ xlnx,i-opb = <0x0>; ++ xlnx,i-plb = <0x1>; ++ xlnx,icache-always-used = <0x1>; ++ xlnx,icache-line-len = <0x4>; ++ xlnx,icache-use-fsl = <0x1>; ++ xlnx,ill-opcode-exception = <0x1>; ++ xlnx,instance = "microblaze_0"; ++ xlnx,interconnect = <0x1>; ++ xlnx,interrupt-is-edge = <0x0>; ++ xlnx,iopb-bus-exception = <0x0>; ++ xlnx,mmu-dtlb-size = <0x4>; ++ xlnx,mmu-itlb-size = <0x2>; ++ xlnx,mmu-tlb-access = <0x3>; ++ xlnx,mmu-zones = <0x10>; ++ xlnx,number-of-pc-brk = <0x1>; ++ xlnx,number-of-rd-addr-brk = <0x0>; ++ xlnx,number-of-wr-addr-brk = <0x0>; ++ xlnx,opcode-0x0-illegal = <0x1>; ++ xlnx,pvr = <0x2>; ++ xlnx,pvr-user1 = <0x0>; ++ xlnx,pvr-user2 = <0x0>; ++ xlnx,reset-msr = <0x0>; ++ xlnx,sco = <0x0>; ++ xlnx,unaligned-exceptions = <0x1>; ++ xlnx,use-barrel = <0x1>; ++ xlnx,use-dcache = <0x1>; ++ xlnx,use-div = <0x1>; ++ xlnx,use-ext-brk = <0x1>; ++ xlnx,use-ext-nm-brk = <0x1>; ++ xlnx,use-extended-fsl-instr = <0x0>; ++ xlnx,use-fpu = <0x2>; ++ xlnx,use-hw-mul = <0x2>; ++ xlnx,use-icache = <0x1>; ++ xlnx,use-interrupt = <0x1>; ++ xlnx,use-mmu = <0x3>; ++ xlnx,use-msr-instr = <0x1>; ++ xlnx,use-pcmp-instr = <0x1>; ++ } ; ++ } ; ++ mb_plb: plb@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus"; ++ ranges ; ++ FLASH: flash@a0000000 { ++ bank-width = <2>; ++ compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash"; ++ reg = < 0xa0000000 0x2000000 >; ++ xlnx,family = "virtex5"; ++ xlnx,include-datawidth-matching-0 = <0x1>; ++ xlnx,include-datawidth-matching-1 = <0x0>; ++ xlnx,include-datawidth-matching-2 = <0x0>; ++ xlnx,include-datawidth-matching-3 = <0x0>; ++ xlnx,include-negedge-ioregs = <0x0>; ++ xlnx,include-plb-ipif = <0x1>; ++ xlnx,include-wrbuf = <0x1>; ++ xlnx,max-mem-width = <0x10>; ++ xlnx,mch-native-dwidth = <0x20>; ++ xlnx,mch-plb-clk-period-ps = <0x1f40>; ++ xlnx,mch-splb-awidth = <0x20>; ++ xlnx,mch0-accessbuf-depth = <0x10>; ++ xlnx,mch0-protocol = <0x0>; ++ xlnx,mch0-rddatabuf-depth = <0x10>; ++ xlnx,mch1-accessbuf-depth = <0x10>; ++ xlnx,mch1-protocol = <0x0>; ++ xlnx,mch1-rddatabuf-depth = <0x10>; ++ xlnx,mch2-accessbuf-depth = <0x10>; ++ xlnx,mch2-protocol = <0x0>; ++ xlnx,mch2-rddatabuf-depth = <0x10>; ++ xlnx,mch3-accessbuf-depth = <0x10>; ++ xlnx,mch3-protocol = <0x0>; ++ xlnx,mch3-rddatabuf-depth = <0x10>; ++ xlnx,mem0-width = <0x10>; ++ xlnx,mem1-width = <0x20>; ++ xlnx,mem2-width = <0x20>; ++ xlnx,mem3-width = <0x20>; ++ xlnx,num-banks-mem = <0x1>; ++ xlnx,num-channels = <0x0>; ++ xlnx,priority-mode = <0x0>; ++ xlnx,synch-mem-0 = <0x0>; ++ xlnx,synch-mem-1 = <0x0>; ++ xlnx,synch-mem-2 = <0x0>; ++ xlnx,synch-mem-3 = <0x0>; ++ xlnx,synch-pipedelay-0 = <0x2>; ++ xlnx,synch-pipedelay-1 = <0x2>; ++ xlnx,synch-pipedelay-2 = <0x2>; ++ xlnx,synch-pipedelay-3 = <0x2>; ++ xlnx,tavdv-ps-mem-0 = <0x1adb0>; ++ xlnx,tavdv-ps-mem-1 = <0x3a98>; ++ xlnx,tavdv-ps-mem-2 = <0x3a98>; ++ xlnx,tavdv-ps-mem-3 = <0x3a98>; ++ xlnx,tcedv-ps-mem-0 = <0x1adb0>; ++ xlnx,tcedv-ps-mem-1 = <0x3a98>; ++ xlnx,tcedv-ps-mem-2 = <0x3a98>; ++ xlnx,tcedv-ps-mem-3 = <0x3a98>; ++ xlnx,thzce-ps-mem-0 = <0x88b8>; ++ xlnx,thzce-ps-mem-1 = <0x1b58>; ++ xlnx,thzce-ps-mem-2 = <0x1b58>; ++ xlnx,thzce-ps-mem-3 = <0x1b58>; ++ xlnx,thzoe-ps-mem-0 = <0x1b58>; ++ xlnx,thzoe-ps-mem-1 = <0x1b58>; ++ xlnx,thzoe-ps-mem-2 = <0x1b58>; ++ xlnx,thzoe-ps-mem-3 = <0x1b58>; ++ xlnx,tlzwe-ps-mem-0 = <0x88b8>; ++ xlnx,tlzwe-ps-mem-1 = <0x0>; ++ xlnx,tlzwe-ps-mem-2 = <0x0>; ++ xlnx,tlzwe-ps-mem-3 = <0x0>; ++ xlnx,twc-ps-mem-0 = <0x2af8>; ++ xlnx,twc-ps-mem-1 = <0x3a98>; ++ xlnx,twc-ps-mem-2 = <0x3a98>; ++ xlnx,twc-ps-mem-3 = <0x3a98>; ++ xlnx,twp-ps-mem-0 = <0x11170>; ++ xlnx,twp-ps-mem-1 = <0x2ee0>; ++ xlnx,twp-ps-mem-2 = <0x2ee0>; ++ xlnx,twp-ps-mem-3 = <0x2ee0>; ++ xlnx,xcl0-linesize = <0x4>; ++ xlnx,xcl0-writexfer = <0x1>; ++ xlnx,xcl1-linesize = <0x4>; ++ xlnx,xcl1-writexfer = <0x1>; ++ xlnx,xcl2-linesize = <0x4>; ++ xlnx,xcl2-writexfer = <0x1>; ++ xlnx,xcl3-linesize = <0x4>; ++ xlnx,xcl3-writexfer = <0x1>; ++ } ; ++ Hard_Ethernet_MAC: xps-ll-temac@81c00000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "xlnx,compound"; ++ ranges ; ++ ethernet@81c00000 { ++ compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a"; ++ device_type = "network"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 5 2 >; ++ llink-connected = <&PIM3>; ++ local-mac-address = [ 00 0a 35 00 00 00 ]; ++ reg = < 0x81c00000 0x40 >; ++ xlnx,bus2core-clk-ratio = <0x1>; ++ xlnx,phy-type = <0x1>; ++ xlnx,phyaddr = <0x1>; ++ xlnx,rxcsum = <0x0>; ++ xlnx,rxfifo = <0x1000>; ++ xlnx,temac-type = <0x0>; ++ xlnx,txcsum = <0x0>; ++ xlnx,txfifo = <0x1000>; ++ } ; ++ } ; ++ IIC_EEPROM: i2c@81600000 { ++ compatible = "xlnx,xps-iic-2.00.a"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 6 2 >; ++ reg = < 0x81600000 0x10000 >; ++ xlnx,clk-freq = <0x7735940>; ++ xlnx,family = "virtex5"; ++ xlnx,gpo-width = <0x1>; ++ xlnx,iic-freq = <0x186a0>; ++ xlnx,scl-inertial-delay = <0x0>; ++ xlnx,sda-inertial-delay = <0x0>; ++ xlnx,ten-bit-adr = <0x0>; ++ } ; ++ LEDs_8Bit: gpio@81400000 { ++ compatible = "xlnx,xps-gpio-1.00.a"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 7 2 >; ++ reg = < 0x81400000 0x10000 >; ++ xlnx,all-inputs = <0x0>; ++ xlnx,all-inputs-2 = <0x0>; ++ xlnx,dout-default = <0x0>; ++ xlnx,dout-default-2 = <0x0>; ++ xlnx,family = "virtex5"; ++ xlnx,gpio-width = <0x8>; ++ xlnx,interrupt-present = <0x1>; ++ xlnx,is-bidir = <0x1>; ++ xlnx,is-bidir-2 = <0x1>; ++ xlnx,is-dual = <0x0>; ++ xlnx,tri-default = <0xffffffff>; ++ xlnx,tri-default-2 = <0xffffffff>; ++ #gpio-cells = <2>; ++ gpio-controller; ++ } ; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ heartbeat { ++ label = "Heartbeat"; ++ gpios = <&LEDs_8Bit 4 1>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ yellow { ++ label = "Yellow"; ++ gpios = <&LEDs_8Bit 5 1>; ++ }; ++ ++ red { ++ label = "Red"; ++ gpios = <&LEDs_8Bit 6 1>; ++ }; ++ ++ green { ++ label = "Green"; ++ gpios = <&LEDs_8Bit 7 1>; ++ }; ++ } ; ++ RS232_Uart_1: serial@84000000 { ++ clock-frequency = <125000000>; ++ compatible = "xlnx,xps-uartlite-1.00.a"; ++ current-speed = <115200>; ++ device_type = "serial"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 8 0 >; ++ port-number = <0>; ++ reg = < 0x84000000 0x10000 >; ++ xlnx,baudrate = <0x1c200>; ++ xlnx,data-bits = <0x8>; ++ xlnx,family = "virtex5"; ++ xlnx,odd-parity = <0x0>; ++ xlnx,use-parity = <0x0>; ++ } ; ++ SysACE_CompactFlash: sysace@83600000 { ++ compatible = "xlnx,xps-sysace-1.00.a"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 4 2 >; ++ reg = < 0x83600000 0x10000 >; ++ xlnx,family = "virtex5"; ++ xlnx,mem-width = <0x10>; ++ } ; ++ debug_module: debug@84400000 { ++ compatible = "xlnx,mdm-1.00.d"; ++ reg = < 0x84400000 0x10000 >; ++ xlnx,family = "virtex5"; ++ xlnx,interconnect = <0x1>; ++ xlnx,jtag-chain = <0x2>; ++ xlnx,mb-dbg-ports = <0x1>; ++ xlnx,uart-width = <0x8>; ++ xlnx,use-uart = <0x1>; ++ xlnx,write-fsl-ports = <0x0>; ++ } ; ++ mpmc@90000000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "xlnx,mpmc-4.02.a"; ++ ranges ; ++ PIM3: sdma@84600180 { ++ compatible = "xlnx,ll-dma-1.00.a"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 2 2 1 2 >; ++ reg = < 0x84600180 0x80 >; ++ } ; ++ } ; ++ xps_intc_0: interrupt-controller@81800000 { ++ #interrupt-cells = <0x2>; ++ compatible = "xlnx,xps-intc-1.00.a"; ++ interrupt-controller ; ++ reg = < 0x81800000 0x10000 >; ++ xlnx,kind-of-intr = <0x100>; ++ xlnx,num-intr-inputs = <0x9>; ++ } ; ++ xps_timer_1: timer@83c00000 { ++ compatible = "xlnx,xps-timer-1.00.a"; ++ interrupt-parent = <&xps_intc_0>; ++ interrupts = < 3 2 >; ++ reg = < 0x83c00000 0x10000 >; ++ xlnx,count-width = <0x20>; ++ xlnx,family = "virtex5"; ++ xlnx,gen0-assert = <0x1>; ++ xlnx,gen1-assert = <0x1>; ++ xlnx,one-timer-only = <0x0>; ++ xlnx,trig0-assert = <0x1>; ++ xlnx,trig1-assert = <0x1>; ++ } ; ++ } ; ++} ; +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +old mode 100644 +new mode 100755 +index 940d70cb..5ae0fdea +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -396,7 +396,7 @@ EXPORT_SYMBOL_GPL(af_alg_free_sg); + int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) + { + struct cmsghdr *cmsg; +- ++ struct af_alg_usr_def *p_usr_def; + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (!CMSG_OK(msg, cmsg)) + return -EINVAL; +@@ -418,7 +418,11 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) + return -EINVAL; + con->op = *(u32 *)CMSG_DATA(cmsg); + break; +- ++ case ALG_USR_DEF: ++ p_usr_def = (struct af_alg_usr_def *)CMSG_DATA(cmsg); ++ memcpy(&con->usr_def, p_usr_def, ++ sizeof(struct af_alg_usr_def)); ++ break; + default: + return -EINVAL; + } +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +old mode 100644 +new mode 100755 +index 6a6dfc06..d89ddbc7 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -247,6 +247,7 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock, + struct skcipher_ctx *ctx = ask->private; + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req); + unsigned ivsize = crypto_ablkcipher_ivsize(tfm); ++ struct af_alg_usr_def *p_usr_def = crypto_ablkcipher_usr_def(tfm); + struct skcipher_sg_list *sgl; + struct af_alg_control con = {}; + long copied = 0; +@@ -270,6 +271,8 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock, + return -EINVAL; + } + ++ memcpy(p_usr_def, &con.usr_def, sizeof(struct af_alg_usr_def)); ++ + if (con.iv && con.iv->ivlen != ivsize) + return -EINVAL; + } +diff --git a/drivers/Kconfig b/drivers/Kconfig +index 3bb154d8..67f5c27f 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -126,4 +126,6 @@ source "drivers/hwspinlock/Kconfig" + + source "drivers/clocksource/Kconfig" + ++source "drivers/pwm/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index 09f3232b..c3217634 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -6,6 +6,7 @@ + # + + obj-y += gpio/ ++obj-y += pwm/ + obj-$(CONFIG_PCI) += pci/ + obj-$(CONFIG_PARISC) += parisc/ + obj-$(CONFIG_RAPIDIO) += rapidio/ +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index e0b25de1..8624d851 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -292,4 +292,24 @@ config CRYPTO_DEV_S5P + Select this to offload Samsung S5PV210 or S5PC110 from AES + algorithms execution. + ++config FH_AES ++ tristate "FH AES support" ++ select CRYPTO_BLKCIPHER ++ select CRYPTO_AES ++ select CRYPTO_DES ++# select CRYPTO_AUTHENC ++# select CRYPTO_ALGAPI ++ select CRYPTO_CBC ++ select CRYPTO_ECB ++ select CRYPTO_SEQIV ++ ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_aes. ++ ++ ++config FH_AES_SELF_TEST ++ bool "fh aes self test" ++ depends on FH_AES ++ + endif # CRYPTO_HW +diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile +index 53ea5015..46f30b50 100644 +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -13,3 +13,6 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o + obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o + obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o + obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o ++ ++obj-$(CONFIG_FH_AES) += fh_aes.o ++obj-$(CONFIG_FH_AES_SELF_TEST) += fh_aes_test.o +diff --git a/drivers/crypto/fh_aes.c b/drivers/crypto/fh_aes.c +new file mode 100755 +index 00000000..d1bcf899 +--- /dev/null ++++ b/drivers/crypto/fh_aes.c +@@ -0,0 +1,1548 @@ ++/***************************************************************************** ++ * Include Section ++ * add all #include here ++ *****************************************************************************/ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/errno.h> ++#include <linux/in.h> ++#include <linux/ioport.h> ++#include <linux/slab.h> ++#include <linux/mm.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++#include <linux/skbuff.h> ++#include <linux/highmem.h> ++#include <linux/proc_fs.h> ++#include <linux/ctype.h> ++#include <linux/version.h> ++#include <linux/spinlock.h> ++#include <linux/dma-mapping.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/bitops.h> ++#include <linux/io.h> ++#include <linux/irqreturn.h> ++#include <asm/irq.h> ++#include <asm/page.h> ++#include <crypto/hash.h> ++#include <linux/err.h> ++#include <linux/module.h> ++#include <linux/scatterlist.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#include <crypto/rng.h> ++#include "fh_aes.h" ++ ++/***************************************************************************** ++ * Define section ++ * add all #define here ++ *****************************************************************************/ ++ ++#define CRYPTO_QUEUE_LEN (1000) ++#define CRYPTION_POS (0) ++#define METHOD_POS (1) ++#define EMODE_POS (4) ++ ++#define aes_readl(aes, name) \ ++ __raw_readl(&(((struct fh_aes_reg *)aes->regs)->name)) ++ ++#define aes_writel(aes, name, val) \ ++ __raw_writel((val), &(((struct fh_aes_reg *)aes->regs)->name)) ++ ++#define aes_readw(aes, name) \ ++ __raw_readw(&(((struct fh_aes_reg *)aes->regs)->name)) ++ ++#define aes_writew(aes, name, val) \ ++ __raw_writew((val), &(((struct fh_aes_reg *)aes->regs)->name)) ++ ++#define aes_readb(aes, name) \ ++ __raw_readb(&(((struct fh_aes_reg *)aes->regs)->name)) ++ ++#define aes_writeb(aes, name, val) \ ++ __raw_writeb((val), &(((struct fh_aes_reg *)aes->regs)->name)) ++ ++ ++#ifdef CONFIG_FH_EFUSE ++#define FH_AESV2 ++#else ++#undef FH_AESV2 ++#endif ++ ++#define FH_AES_ALLIGN_SIZE 64 ++#define FH_AES_MALLOC_SIZE 4096 ++#define FH_AES_CTL_MAX_PROCESS_SIZE (FH_AES_MALLOC_SIZE - 1) ++ ++#ifdef FH_AESV2 ++#include <../drivers/misc/fh_efuse.h> ++extern struct wrap_efuse_obj s_efuse_obj; ++#endif ++/**************************************************************************** ++ * ADT section ++ * add definition of user defined Data Type that only be used in this file here ++ ***************************************************************************/ ++enum { ++ ENCRYPT = 0 << CRYPTION_POS, ++ DECRYPT = 1 << CRYPTION_POS, ++}; ++ ++enum { ++ ECB_MODE = 0 << EMODE_POS, ++ CBC_MODE = 1 << EMODE_POS, ++ CTR_MODE = 2 << EMODE_POS, ++ CFB_MODE = 4 << EMODE_POS, ++ OFB_MODE = 5 << EMODE_POS, ++}; ++ ++enum { ++ DES_METHOD = 0 << METHOD_POS, ++ TRIPLE_DES_METHOD = 1 << METHOD_POS, ++ AES_128_METHOD = 4 << METHOD_POS, ++ AES_192_METHOD = 5 << METHOD_POS, ++ AES_256_METHOD = 6 << METHOD_POS, ++}; ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++ ++static int fh_aes_handle_req(struct fh_aes_dev *dev, ++ struct ablkcipher_request *req); ++/*aes*/ ++static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode); ++static int fh_aes_ecb_encrypt(struct ablkcipher_request *req); ++static int fh_aes_ecb_decrypt(struct ablkcipher_request *req); ++static int fh_aes_cbc_encrypt(struct ablkcipher_request *req); ++static int fh_aes_cbc_decrypt(struct ablkcipher_request *req); ++static int fh_aes_ctr_encrypt(struct ablkcipher_request *req); ++static int fh_aes_ctr_decrypt(struct ablkcipher_request *req); ++static int fh_aes_ofb_encrypt(struct ablkcipher_request *req); ++static int fh_aes_ofb_decrypt(struct ablkcipher_request *req); ++static int fh_aes_cfb_encrypt(struct ablkcipher_request *req); ++static int fh_aes_cfb_decrypt(struct ablkcipher_request *req); ++ ++/*des*/ ++static int fh_des_ecb_encrypt(struct ablkcipher_request *req); ++static int fh_des_ecb_decrypt(struct ablkcipher_request *req); ++static int fh_des_cbc_encrypt(struct ablkcipher_request *req); ++static int fh_des_cbc_decrypt(struct ablkcipher_request *req); ++static int fh_des_ofb_encrypt(struct ablkcipher_request *req); ++static int fh_des_ofb_decrypt(struct ablkcipher_request *req); ++static int fh_des_cfb_encrypt(struct ablkcipher_request *req); ++static int fh_des_cfb_decrypt(struct ablkcipher_request *req); ++ ++/*tri des*/ ++static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req); ++static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req); ++static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req); ++static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req); ++static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req); ++static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req); ++static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req); ++static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req); ++static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key, ++ unsigned int keylen); ++static int fh_aes_cra_init(struct crypto_tfm *tfm); ++static void fh_aes_tx(struct fh_aes_dev *dev); ++static void fh_aes_rx(struct fh_aes_dev *dev); ++static irqreturn_t fh_aes_interrupt(int irq, void *dev_id); ++static void aes_biglittle_swap(u8 *buf); ++static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg); ++static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg); ++static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key, ++ uint8_t *iv, unsigned int keylen); ++static void fh_set_dma_indata(struct fh_aes_dev *dev, ++ struct scatterlist *sg); ++static void fh_set_dma_outdata(struct fh_aes_dev *dev, ++ struct scatterlist *sg); ++static void fh_unset_indata(struct fh_aes_dev *dev); ++static void fh_unset_outdata(struct fh_aes_dev *dev); ++static void fh_aes_complete(struct fh_aes_dev *dev, int err); ++static void fh_aes_crypt_start(struct fh_aes_dev *dev, unsigned long mode); ++static void fh_aes_work_cb(struct work_struct *w); ++ ++#define fh_des_setkey fh_aes_setkey ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++struct fh_aes_dev *pobj_aes_dev = NULL; ++static struct crypto_alg algs[] = { ++ { ++ .cra_name = "ecb(aes)", ++ .cra_driver_name = "ecb-aes-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .setkey = fh_aes_setkey, ++ .encrypt = fh_aes_ecb_encrypt, ++ .decrypt = fh_aes_ecb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cbc(aes)", ++ .cra_driver_name = "cbc-aes-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = fh_aes_setkey, ++ .encrypt = fh_aes_cbc_encrypt, ++ .decrypt = fh_aes_cbc_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ctr(aes)", ++ .cra_driver_name = "ctr-aes-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = fh_aes_setkey, ++ .encrypt = fh_aes_ctr_encrypt, ++ .decrypt = fh_aes_ctr_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ofb(aes)", ++ .cra_driver_name = "ofb-aes-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = fh_aes_setkey, ++ .encrypt = fh_aes_ofb_encrypt, ++ .decrypt = fh_aes_ofb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cfb(aes)", ++ .cra_driver_name = "cfb-aes-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = fh_aes_setkey, ++ .encrypt = fh_aes_cfb_encrypt, ++ .decrypt = fh_aes_cfb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ecb(des)", ++ .cra_driver_name = "ecb-des-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_ecb_encrypt, ++ .decrypt = fh_des_ecb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cbc(des)", ++ .cra_driver_name = "cbc-des-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_cbc_encrypt, ++ .decrypt = fh_des_cbc_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ofb(des)", ++ .cra_driver_name = "ofb-des-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_ofb_encrypt, ++ .decrypt = fh_des_ofb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cfb(des)", ++ .cra_driver_name = "cfb-des-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_cfb_encrypt, ++ .decrypt = fh_des_cfb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ecb(des3)", ++ .cra_driver_name = "ecb-des3-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_tri_ecb_encrypt, ++ .decrypt = fh_des_tri_ecb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cbc(des3)", ++ .cra_driver_name = "cbc-des3-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_tri_cbc_encrypt, ++ .decrypt = fh_des_tri_cbc_decrypt, ++ } ++ }, ++ { ++ .cra_name = "ofb(des3)", ++ .cra_driver_name = "ofb-des3-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_tri_ofb_encrypt, ++ .decrypt = fh_des_tri_ofb_decrypt, ++ } ++ }, ++ { ++ .cra_name = "cfb(des3)", ++ .cra_driver_name = "cfb-des3-fh", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct fh_aes_ctx), ++ .cra_alignmask = 0x0f, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = fh_aes_cra_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setkey = fh_des_setkey, ++ .encrypt = fh_des_tri_cfb_encrypt, ++ .decrypt = fh_des_tri_cfb_decrypt, ++ } ++ }, ++}; ++ ++#ifdef CONFIG_FH_AES_SELF_TEST ++extern void fh_aes_self_test_all(void); ++#endif ++ ++/* function body */ ++static int fh_aes_handle_req(struct fh_aes_dev *dev, ++ struct ablkcipher_request *req) ++{ ++ unsigned long flags; ++ int err; ++ spin_lock_irqsave(&dev->lock, flags); ++ err = ablkcipher_enqueue_request(&dev->queue, req); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ queue_work(dev->workqueue, &dev->work); ++ return err; ++} ++ ++static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); ++ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); ++ struct fh_aes_reqctx *reqctx = ablkcipher_request_ctx(req); ++ struct fh_aes_dev *dev = ctx->dev; ++ AES_DBG("%s\n", __func__); ++ dev->reqctx = reqctx; ++ /*if (!(mode & CFB_MODE)) {*/ ++ if ((!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) ++ && (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE))) { ++ pr_err("request size is not exact amount of AES blocks\n"); ++ return -EINVAL; ++ } ++ /*}*/ ++ AES_DBG("reqctx->mode value: %x\n", (unsigned int)mode); ++ reqctx->mode = mode; ++ return fh_aes_handle_req(dev, req); ++} ++ ++static int fh_aes_ecb_encrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); ++ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); ++ u32 method = 0; ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT); ++} ++ ++ ++static int fh_aes_ecb_decrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); ++ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); ++ u32 method = 0; ++ ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT); ++} ++ ++static int fh_aes_cbc_encrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); ++ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); ++ u32 method = 0; ++ ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT); ++} ++ ++static int fh_aes_cbc_decrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ AES_DBG("%s\n", __func__); ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ ++ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT); ++} ++ ++static int fh_aes_ctr_encrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ ++ return fh_aes_crypt(req, method | CTR_MODE | ENCRYPT); ++} ++ ++static int fh_aes_ctr_decrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ AES_DBG("%s\n", __func__); ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | CTR_MODE | DECRYPT); ++} ++ ++static int fh_aes_ofb_encrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT); ++} ++ ++static int fh_aes_ofb_decrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ ++ AES_DBG("%s\n", __func__); ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ ++ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT); ++} ++ ++static int fh_aes_cfb_encrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT); ++} ++ ++static int fh_aes_cfb_decrypt(struct ablkcipher_request *req) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct fh_aes_ctx *ctx; ++ u32 method; ++ ++ tfm = crypto_ablkcipher_reqtfm(req); ++ ctx = crypto_ablkcipher_ctx(tfm); ++ method = 0; ++ ++ AES_DBG("%s\n", __func__); ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ method = AES_128_METHOD; ++ break; ++ case AES_KEYSIZE_192: ++ method = AES_192_METHOD; ++ break; ++ case AES_KEYSIZE_256: ++ method = AES_256_METHOD; ++ break; ++ default: ++ break; ++ } ++ ++ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT); ++} ++static int fh_des_ecb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT); ++} ++ ++static int fh_des_ecb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT); ++} ++ ++static int fh_des_cbc_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT); ++} ++ ++static int fh_des_cbc_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT); ++} ++ ++static int fh_des_ofb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT); ++} ++ ++static int fh_des_ofb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT); ++} ++ ++static int fh_des_cfb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT); ++} ++ ++static int fh_des_cfb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = DES_METHOD; ++ ++ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT); ++} ++static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT); ++} ++ ++static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT); ++} ++ ++static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT); ++} ++ ++static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT); ++} ++ ++static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT); ++} ++ ++static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT); ++} ++ ++static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT); ++} ++ ++static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req) ++{ ++ u32 method; ++ method = 0; ++ method = TRIPLE_DES_METHOD; ++ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT); ++} ++static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key, ++ unsigned int keylen) ++{ ++ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); ++ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ int i = 0; ++ AES_DBG("%s\n", __func__); ++ if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 ++ && keylen != AES_KEYSIZE_256 && keylen != DES_KEY_SIZE ++ && keylen != DES3_EDE_KEY_SIZE) ++ return -EINVAL; ++ ++ for (; i < keylen; i++) ++ AES_DBG("%x", key[i]); ++ AES_DBG("\n"); ++ ++ memcpy(ctx->aes_key, key, keylen); ++ ctx->keylen = keylen; ++ return 0; ++} ++ ++static int fh_aes_cra_init(struct crypto_tfm *tfm) ++{ ++ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm); ++ ctx->dev = pobj_aes_dev; ++ tfm->crt_ablkcipher.reqsize = sizeof(struct fh_aes_reqctx); ++ AES_DBG("%s\n", __func__); ++ return 0; ++} ++ ++static void fh_aes_tx(struct fh_aes_dev *dev) ++{ ++ /*int err = 0;*/ ++ unsigned int i = 0; ++ struct ablkcipher_request *req = dev->req; ++ struct scatterlist *temp_sg = req->dst; ++ int len = 0; ++ fh_unset_outdata(dev); ++ do { ++ sg_copy_from_buffer(temp_sg, 1, &dev->ctl_dst_xbuf[i], ++ sg_dma_len(temp_sg)); ++ len += sg_dma_len(temp_sg); ++ i += sg_dma_len(temp_sg); ++ temp_sg = sg_next(temp_sg); ++ } while (temp_sg != NULL); ++ /*fh_aes_complete(dev, err);*/ ++} ++ ++static void fh_aes_rx(struct fh_aes_dev *dev) ++{ ++ fh_unset_indata(dev); ++} ++ ++static irqreturn_t fh_aes_interrupt(int irq, void *dev_id) ++{ ++ ++ u32 isr_status; ++ /*unsigned long flags;*/ ++ struct platform_device *pdev = (struct platform_device *) dev_id; ++ struct fh_aes_dev *dev = platform_get_drvdata(pdev); ++ /*u32 isr = dev->en_isr;*/ ++ AES_DBG("%s\n", __func__); ++ /*spin_lock_irqsave(&dev->lock, flags);*/ ++ aes_writel(dev, dma_control, 0); ++ isr_status = aes_readl(dev, intr_src); ++ aes_writel(dev, intr_clear_status, 0x07); ++ aes_writel(dev, intr_enable, 0); ++ if (isr_status & 0x02) ++ printk("dma rev hreap error...\n"); ++ if (isr_status & 0x04) ++ printk("dma stop src ..\n"); ++ if (isr_status & 0x01) { ++ AES_DBG("dma done..\n"); ++ complete(&(dev->done)); ++ } ++ /*spin_unlock_irqrestore(&dev->lock, flags);*/ ++ return IRQ_HANDLED; ++} ++ ++static void aes_biglittle_swap(u8 *buf) ++{ ++ u8 tmp, tmp1; ++ tmp = buf[0]; ++ tmp1 = buf[1]; ++ buf[0] = buf[3]; ++ buf[1] = buf[2]; ++ buf[2] = tmp1; ++ buf[3] = tmp; ++} ++ ++static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg) ++{ ++ int err; ++ unsigned int i = 0; ++ unsigned int len = 0; ++ struct scatterlist *temp_sg = sg; ++ unsigned char *src_xbuf; ++ src_xbuf = &dev->ctl_src_xbuf[0]; ++ do { ++ if (len + sg_dma_len(temp_sg) > FH_AES_CTL_MAX_PROCESS_SIZE) { ++ printk("%s: total size > driver size 0x%x\n", __func__, FH_AES_CTL_MAX_PROCESS_SIZE); ++ err = -ENOMEM; ++ goto exit; ++ } ++ sg_copy_to_buffer(temp_sg, 1, &src_xbuf[i], sg_dma_len(temp_sg)); ++ len += sg_dma_len(temp_sg); ++ i += sg_dma_len(temp_sg); ++ temp_sg = sg_next(temp_sg); ++ } while (temp_sg != NULL); ++ ++ sg_init_one(&dev->src_sg[0], &src_xbuf[0], len); ++ err = dma_map_sg(dev->dev, &dev->src_sg[0], 1, DMA_TO_DEVICE); ++ if (!err) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ dev->sg_src = &dev->src_sg[0]; ++ err = 0; ++exit: ++ return err; ++} ++ ++static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg) ++{ ++ int err; ++ sg_init_one(&dev->dst_sg[0], ++ &dev->ctl_dst_xbuf[0], FH_AES_CTL_MAX_PROCESS_SIZE); ++ err = dma_map_sg(dev->dev, &dev->dst_sg[0], 1, DMA_FROM_DEVICE); ++ if (!err) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ dev->sg_dst = &dev->dst_sg[0]; ++ err = 0; ++exit: ++ return err; ++} ++ ++static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key, ++ uint8_t *iv, unsigned int keylen) ++{ ++ ++ int i; ++ u32 method; ++ u32 temp_key_buf[32]; ++ u32 temp_iv_buf[32]; ++ u32 *p_dst = NULL; ++ u32 key_size = 0; ++ if (dev->iv_flag == true) { ++ /*set iv*/ ++ /*if aes mode ....set 128 bit iv, des set 64bit iv..*/ ++ AES_DBG("set iv reg\n"); ++ if ((dev->control_reg & AES_128_METHOD) ++ || ((dev->control_reg & AES_192_METHOD)) ++ || (dev->control_reg & AES_256_METHOD)) { ++ AES_DBG("aes iv mode...\n"); ++ ++ memcpy((u8 *)&temp_iv_buf[0], iv, 16); ++ p_dst = &temp_iv_buf[0]; ++ for (i = 0; i < 16 / sizeof(u32); i++) ++ aes_biglittle_swap((u8 *)(p_dst + i)); ++ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->initial_vector0, ++ temp_iv_buf, 16); ++ } else { ++ AES_DBG("des iv mode...\n"); ++ ++ memcpy((u8 *)&temp_iv_buf[0], iv, 8); ++ p_dst = &temp_iv_buf[0]; ++ for (i = 0; i < 8 / sizeof(u32); i++) ++ aes_biglittle_swap((u8 *)(p_dst + i)); ++ ++ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->initial_vector0, ++ temp_iv_buf, 8); ++ ++ } ++ } ++ /*set key...*/ ++ method = dev->control_reg & 0x0e; ++ AES_DBG("set key reg\n"); ++ ++ switch (method) { ++ case AES_128_METHOD: ++ AES_DBG("set key aes 128 mode..\n"); ++ key_size = 16; ++ ++ break; ++ case AES_192_METHOD: ++ AES_DBG("set key aes 192 mode..\n"); ++ key_size = 24; ++ break; ++ ++ case AES_256_METHOD: ++ AES_DBG("set key aes 256 mode..\n"); ++ key_size = 32; ++ break; ++ ++ case DES_METHOD: ++ AES_DBG("set key des normal mode..\n"); ++ key_size = 8; ++ break; ++ ++ case TRIPLE_DES_METHOD: ++ AES_DBG("set key des triple mode..\n"); ++ key_size = 24; ++ break; ++ ++ default: ++ AES_DBG("error method!!\n"); ++ break; ++ } ++#ifdef FH_AESV2 ++ if (dev->p_usr_def->mode & CRYPTO_EX_MEM_SET_KEY) { ++ s_efuse_obj.trans_key_start_no = 0; ++ s_efuse_obj.trans_key_size = key_size / 4; ++ efuse_trans_key(&s_efuse_obj, ++ s_efuse_obj.trans_key_start_no, ++ s_efuse_obj.trans_key_size, dev->p_usr_def); ++ } else { ++ s_efuse_obj.old_usr_def.mode &= ~CRYPTO_EX_MEM_SET_KEY; ++ s_efuse_obj.old_usr_def.mode |= CRYPTO_CPU_SET_KEY; ++ memcpy((u8 *)&temp_key_buf[0], key, key_size); ++ p_dst = &temp_key_buf[0]; ++ for (i = 0; i < key_size / sizeof(u32); i++) ++ aes_biglittle_swap((u8 *)(p_dst + i)); ++ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->security_key0, ++ (u8 *)&temp_key_buf[0], ++ key_size); ++ } ++ ++#else ++ memcpy((u8 *)&temp_key_buf[0], key, key_size); ++ p_dst = &temp_key_buf[0]; ++ for (i = 0; i < key_size / sizeof(u32); i++) ++ aes_biglittle_swap((u8 *)(p_dst + i)); ++ ++ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->security_key0, ++ (u8 *)&temp_key_buf[0], ++ key_size); ++ ++#endif ++ ++} ++ ++static void fh_set_dma_indata(struct fh_aes_dev *dev, ++ struct scatterlist *sg) ++{ ++ aes_writel(dev, dma_src_add, sg_dma_address(sg)); ++ AES_DBG("%s :dma trans size is :%x,add is:%x\n", ++ __func__, sg_dma_len(sg), sg_dma_address(sg)); ++ aes_writel(dev, dma_trans_size, sg_dma_len(sg)); ++} ++ ++static void fh_set_dma_outdata(struct fh_aes_dev *dev, ++ struct scatterlist *sg) ++{ ++ aes_writel(dev, dma_dst_add, sg_dma_address(sg)); ++} ++ ++static void fh_unset_indata(struct fh_aes_dev *dev) ++{ ++ dma_unmap_sg(dev->dev, dev->sg_src, 1, DMA_TO_DEVICE); ++} ++ ++static void fh_unset_outdata(struct fh_aes_dev *dev) ++{ ++ dma_unmap_sg(dev->dev, dev->sg_dst, 1, DMA_FROM_DEVICE); ++} ++ ++static void fh_aes_complete(struct fh_aes_dev *dev, int err) ++{ ++ if (dev->req->base.complete) ++ dev->req->base.complete(&dev->req->base, err); ++} ++ ++static void fh_aes_crypt_start(struct fh_aes_dev *dev, unsigned long mode) ++{ ++ ++ struct ablkcipher_request *req = dev->req; ++ u32 control_reg; ++ u32 outfifo_thold = 0; ++ u32 infifo_thold = 0; ++ u32 isr; ++ int err; ++ unsigned long flags; ++ control_reg = 0; ++ spin_lock_irqsave(&dev->lock, flags); ++ if ((mode & CBC_MODE) || (mode & CTR_MODE) || (mode & CFB_MODE) ++ || (mode & OFB_MODE)) { ++ control_reg |= 1 << 7; ++ dev->iv_flag = true; ++ } else ++ dev->iv_flag = false; ++ ++ /*emode & method*/ ++ control_reg |= (unsigned int) mode; ++ dev->control_reg = control_reg; ++ outfifo_thold = 0; ++ infifo_thold = 8; ++ isr = dev->en_isr; ++ ++ AES_DBG("control_reg:0x%x\n", control_reg); ++ aes_writel(dev, encrypt_control, control_reg); ++ /*set key...*/ ++ fh_set_aes_key_reg(dev, dev->ctx->aes_key, req->info, dev->ctx->keylen); ++ err = fh_set_indata(dev, req->src); ++ if (err) ++ goto indata_error; ++ ++ err = fh_set_outdata(dev, req->dst); ++ if (err) ++ goto outdata_error; ++ ++ fh_set_dma_indata(dev, dev->sg_src); ++ fh_set_dma_outdata(dev, dev->sg_dst); ++ ++ /*set fifo..*/ ++ AES_DBG("outfifo thold:%x\n", outfifo_thold); ++ AES_DBG("infifo thold:%x\n", infifo_thold); ++ aes_writel(dev, fifo_threshold, outfifo_thold << 8 | infifo_thold); ++ /*set isr..*/ ++ AES_DBG("intr enable:%x\n", isr); ++ aes_writel(dev, intr_enable, isr); ++ /*enable dma go..*/ ++ aes_writel(dev, dma_control, 1); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return; ++ ++outdata_error: ++ AES_DBG("outdata_error ..\n"); ++ fh_unset_indata(dev); ++ ++indata_error: ++ AES_DBG("indata_error ..\n"); ++ fh_aes_complete(dev, err); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++} ++ ++static void fh_aes_work_cb(struct work_struct *w) ++{ ++ struct fh_aes_dev *dev = container_of(w, struct fh_aes_dev, work); ++ struct crypto_async_request *async_req, *backlog; ++ struct fh_aes_reqctx *reqctx; ++ struct crypto_ablkcipher *p_tfm; ++ struct af_alg_usr_def *p_usr_def; ++ unsigned long flags; ++ AES_DBG("%s\n", __func__); ++ /*get the req need to handle*/ ++ spin_lock_irqsave(&dev->lock, flags); ++ async_req = crypto_dequeue_request(&dev->queue); ++ backlog = crypto_get_backlog(&dev->queue); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ if (!async_req) ++ return; ++ init_completion(&dev->done); ++ dev->req = ablkcipher_request_cast(async_req); ++ p_tfm = crypto_ablkcipher_reqtfm(dev->req); ++ p_usr_def = crypto_ablkcipher_usr_def(p_tfm); ++ dev->p_usr_def = p_usr_def; ++ dev->ctx = crypto_tfm_ctx(dev->req->base.tfm); ++ reqctx = ablkcipher_request_ctx(dev->req); ++ fh_aes_crypt_start(dev, reqctx->mode); ++ wait_for_completion(&dev->done); ++ fh_aes_rx(dev); ++ fh_aes_tx(dev); ++ fh_aes_complete(dev, 0); ++ if (backlog) { ++ if (backlog->complete) ++ backlog->complete(backlog, -EINPROGRESS); ++ } ++ /*call the queue work until empty.*/ ++ if (dev->queue.qlen != 0) ++ queue_work(dev->workqueue, &dev->work); ++} ++ ++/*add chenjn dsp use...*/ ++typedef struct { ++ unsigned int base; ++ void *vbase; ++ unsigned int size; ++} MEM_INFO; ++typedef struct { ++ MEM_INFO mem; ++ unsigned char *remap_base; /**<已用大小*/ ++} RW_MEM_INFO; ++ ++struct tcrypt_result { ++ struct completion completion; ++ int err; ++}; ++ ++int aes_128_ecb_encrypt(char *key_128, RW_MEM_INFO in, ++RW_MEM_INFO out, unsigned int data_len_align16); ++ ++int fh_aes_ctl_mem_init(struct fh_aes_dev *pdata) ++{ ++ unsigned int t1; ++ unsigned int t2; ++ unsigned int t3; ++ unsigned int t4; ++ ++ t1 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE ++ + FH_AES_ALLIGN_SIZE, GFP_KERNEL); ++ if (!t1) ++ goto err1; ++ ++ t2 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE ++ + FH_AES_ALLIGN_SIZE, GFP_KERNEL); ++ if (!t2) ++ goto err2; ++ ++ ++ t3 = ((t1 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1))); ++ t4 = ((t2 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1))); ++ ++ pdata->ctl_raw_src_xbuf = (unsigned char *)t1; ++ pdata->ctl_raw_dst_xbuf = (unsigned char *)t2; ++ pdata->ctl_src_xbuf = (unsigned char *)t3; ++ pdata->ctl_dst_xbuf = (unsigned char *)t4; ++ return 0; ++err2: ++ kfree((void *)t1); ++err1: ++ return -1; ++ ++} ++ ++static int __devinit fh_aes_probe(struct platform_device *pdev) ++{ ++ ++ int i, j, err = -ENODEV; ++ struct fh_aes_dev *pdata; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ struct resource *ioarea; ++ ++ AES_DBG("aes probe get in..\n"); ++ if (pobj_aes_dev) { ++ dev_err(&pdev->dev, "second crypto dev..\n"); ++ return -EEXIST; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "get platform source error..\n"); ++ return -ENODEV; ++ } ++ ++ ioarea = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (!ioarea) { ++ dev_err(&pdev->dev, "aes region already claimed\n"); ++ /*BUG_ON(ioarea);*/ ++ return -EBUSY; ++ } ++ ++ pdata = kzalloc(sizeof(struct fh_aes_dev), GFP_KERNEL); ++ if (!pdata) { ++ err = -ENOMEM; ++ goto err_malloc; ++ } ++ ++ spin_lock_init(&pdata->lock); ++ pdata->regs = ioremap(res->start, resource_size(res)); ++ ++ if (!pdata->regs) { ++ dev_err(&pdev->dev, "aes region already mapped\n"); ++ err = -EINVAL; ++ goto err_iomap; ++ } ++ pdata->irq_no = platform_get_irq(pdev, 0); ++ if (pdata->irq_no < 0) { ++ err = pdata->irq_no; ++ dev_warn(dev, "aes interrupt is not available.\n"); ++ goto err_irq; ++ } ++ /*only enable dma done isr..*/ ++ pdata->en_isr = 1 << 0; ++ err = request_irq(pdata->irq_no, fh_aes_interrupt, 0, ++ dev_name(&pdev->dev), pdev); ++ ++ if (err) { ++ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err); ++ goto err_irq; ++ } ++ /*bind to plat dev..*/ ++ pdata->dev = dev; ++ /*bing to static para..only one aes controller in fh..*/ ++ pobj_aes_dev = pdata; ++ platform_set_drvdata(pdev, pdata); ++ ++ pdata->workqueue = create_singlethread_workqueue(dev_name(&pdev->dev)); ++ if (!pdata->workqueue) { ++ dev_err(&pdev->dev, "aes workqueue init error.\n"); ++ goto err_irq; ++ } ++ INIT_WORK(&pdata->work, fh_aes_work_cb); ++ ++ ++ crypto_init_queue(&pdata->queue, CRYPTO_QUEUE_LEN); ++ for (i = 0; i < ARRAY_SIZE(algs); i++) { ++ INIT_LIST_HEAD(&algs[i].cra_list); ++ err = crypto_register_alg(&algs[i]); ++ ++ if (err) { ++ dev_warn(dev, "register alg error...\n"); ++ goto err_algs; ++ } ++ } ++ ++ err = fh_aes_ctl_mem_init(pdata); ++ if (err) { ++ dev_err(&pdev->dev, "aes malloc mem error..\n"); ++ goto err_algs; ++ } ++ pr_info("aes driver registered\n"); ++ ++#ifdef CONFIG_FH_AES_SELF_TEST ++ ++ fh_aes_self_test_all(); ++#endif ++ ++ return 0; ++err_algs: ++ for (j = 0; j < i; j++) ++ crypto_unregister_alg(&algs[j]); ++ destroy_workqueue(pdata->workqueue); ++ platform_set_drvdata(pdev, NULL); ++ pobj_aes_dev = NULL; ++ free_irq(pdata->irq_no, pdata); ++ ++err_irq: ++ iounmap(pdata->regs); ++ ++err_iomap: ++ kfree(pdata); ++ ++err_malloc: ++ release_mem_region(res->start, resource_size(res)); ++ return err; ++} ++ ++static int __devexit fh_aes_remove(struct platform_device *pdev) ++{ ++ ++ int i; ++ struct fh_aes_dev *pdata = platform_get_drvdata(pdev); ++ struct resource *res; ++ ++ for (i = 0; i < ARRAY_SIZE(algs); i++) ++ crypto_unregister_alg(&algs[i]); ++ ++ destroy_workqueue(pdata->workqueue); ++ platform_set_drvdata(pdev, NULL); ++ pobj_aes_dev = NULL; ++ free_irq(pdata->irq_no, pdata); ++ iounmap(pdata->regs); ++ kfree(pdata->ctl_raw_src_xbuf); ++ kfree(pdata->ctl_raw_dst_xbuf); ++ pdata->ctl_raw_src_xbuf = NULL; ++ pdata->ctl_raw_dst_xbuf = NULL; ++ pdata->ctl_src_xbuf = NULL; ++ pdata->ctl_dst_xbuf = NULL; ++ kfree(pdata); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(res->start, resource_size(res)); ++ ++ return 0; ++} ++ ++static struct platform_driver fh_aes_driver = { ++ .driver = { ++ .name = "fh_aes", ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_aes_probe, ++ .remove = __devexit_p(fh_aes_remove), ++}; ++ ++static int __init fh_aes_init(void) ++{ ++ return platform_driver_register(&fh_aes_driver); ++} ++late_initcall(fh_aes_init); ++ ++static void __exit fh_aes_exit(void) ++{ ++ platform_driver_unregister(&fh_aes_driver); ++} ++module_exit(fh_aes_exit); ++ ++static void tcrypt_complete(struct crypto_async_request *req, int err) ++{ ++ struct tcrypt_result *res = req->data; ++ if (err == -EINPROGRESS) ++ return; ++ complete(&res->completion); ++} ++ ++int aes_128_ecb_encrypt(char *key_128, RW_MEM_INFO in, ++RW_MEM_INFO out, unsigned int data_len_align16) ++{ ++ static char *xbuf; ++ static char *dst_xbuf; ++ static struct crypto_ablkcipher *tfm; ++ static struct ablkcipher_request *req; ++ static int malloc_flag; ++ /*const char *algo = NULL;*/ ++ struct scatterlist sg[8]; ++ struct scatterlist dst_sg[8]; ++ void *data; ++ void *dst_data; ++ struct tcrypt_result wait_result; ++ ++ /*malloc buf...*/ ++ if (malloc_flag != 0) ++ goto work_go; ++ malloc_flag = 1; ++ xbuf = (void *)__get_free_page(GFP_KERNEL); ++ if (!xbuf) { ++ printk("no pages.\n"); ++ return -1; ++ } ++ ++ dst_xbuf = (void *)__get_free_page(GFP_KERNEL); ++ if (!dst_xbuf) { ++ free_page((unsigned long)xbuf); ++ printk("no pages.\n"); ++ return -1; ++ } ++ ++ tfm = crypto_alloc_ablkcipher("ecb-aes-fh", ++ CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, 0); ++ if (IS_ERR(tfm)) { ++ printk("aes_test: failed to alloc cipher!\n"); ++ free_page((unsigned long)xbuf); ++ free_page((unsigned long)dst_xbuf); ++ return -1; ++ } ++ req = ablkcipher_request_alloc(tfm, GFP_KERNEL); ++ if (!req) { ++ printk(KERN_ERR "alg: skcipher: Failed to allocate request " ++ "for\n"); ++ return -1; ++ } ++ ++work_go: ++ init_completion(&wait_result.completion); ++ crypto_ablkcipher_setkey(tfm, (u8 *)key_128, 16); ++ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, ++ tcrypt_complete, &wait_result); ++ data = xbuf; ++ dst_data = dst_xbuf; ++ /*encrypt*/ ++ memcpy(data, in.remap_base, data_len_align16); ++ sg_init_one(&sg[0], data, data_len_align16); ++ sg_init_one(&dst_sg[0], dst_data, data_len_align16); ++ ablkcipher_request_set_crypt(req, sg, dst_sg, data_len_align16, NULL); ++ crypto_ablkcipher_encrypt(req); ++ wait_for_completion(&wait_result.completion); ++ memcpy(out.remap_base, dst_data, data_len_align16); ++ ++ return 0; ++ ++} ++EXPORT_SYMBOL(aes_128_ecb_encrypt); ++ ++ ++MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>"); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Fullhan AES driver support"); +diff --git a/drivers/crypto/fh_aes.h b/drivers/crypto/fh_aes.h +new file mode 100755 +index 00000000..2bed7084 +--- /dev/null ++++ b/drivers/crypto/fh_aes.h +@@ -0,0 +1,122 @@ ++/* ++ * fh_aes.h ++ * ++ * Created on: 3.12.2015 ++ * Author: duobao ++ */ ++ ++#ifndef FH_AES_H_ ++#define FH_AES_H_ ++ ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/scatterlist.h> ++#include <linux/dma-mapping.h> ++#include <linux/io.h> ++#include <linux/crypto.h> ++#include <linux/interrupt.h> ++#include <crypto/algapi.h> ++#include <crypto/aes.h> ++#include <crypto/des.h> ++#include <crypto/ctr.h> ++ ++struct fh_aes_reg { ++ u32 encrypt_control; /*0*/ ++ u32 reserved_4_8; /*4*/ ++ u32 fifo_status; /*8*/ ++ u32 parity_error; /*c*/ ++ u32 security_key0; /*10*/ ++ u32 security_key1; /*14*/ ++ u32 security_key2; /*18*/ ++ u32 security_key3; /*1c*/ ++ u32 security_key4; /*20*/ ++ u32 security_key5; /*24*/ ++ u32 security_key6; /*28*/ ++ u32 security_key7; /*2c*/ ++ u32 initial_vector0; /*30*/ ++ u32 initial_vector1; /*34*/ ++ u32 initial_vector2; /*38*/ ++ u32 initial_vector3; /*3c*/ ++ u32 reserved_40_44; /*40*/ ++ u32 reserved_44_48; /*44*/ ++ u32 dma_src_add; /*48*/ ++ u32 dma_dst_add; /*4c*/ ++ u32 dma_trans_size; /*50*/ ++ u32 dma_control; /*54*/ ++ u32 fifo_threshold; /*58*/ ++ u32 intr_enable; /*5c*/ ++ u32 intr_src; /*60*/ ++ u32 mask_intr_status; /*64*/ ++ u32 intr_clear_status; /*68*/ ++ u32 reserved_6c_70; /*6c*/ ++ u32 revision; /*70*/ ++ u32 feature; /*74*/ ++ u32 reserved_78_7c; /*78*/ ++ u32 reserved_7c_80; /*7c*/ ++ u32 last_initial_vector0; /*80*/ ++ u32 last_initial_vector1; /*84*/ ++ u32 last_initial_vector2; /*88*/ ++ u32 last_initial_vector3; /*8c*/ ++}; ++ ++/*requst ctx.....*/ ++struct fh_aes_reqctx { ++ unsigned long mode; ++}; ++/*aes ctx....*/ ++struct fh_aes_ctx { ++ struct fh_aes_dev *dev; /*bind to aes dev..*/ ++ uint8_t aes_key[AES_MAX_KEY_SIZE]; /*rec key value..*/ ++ int keylen; /*rec key len.*/ ++}; ++ ++struct fh_aes_dev { ++ /*common driver paras..*/ ++ void *regs; ++ struct device *dev; /*bind to the platform dev...*/ ++ struct clk *clk; ++ spinlock_t lock; /*just lock...*/ ++ u32 irq_no; /*board info...*/ ++ u32 en_isr; /*software rec the isr src*/ ++ bool iv_flag; ++ u32 control_reg; ++ /*crypto need below...*/ ++ struct fh_aes_ctx *ctx; /*bind to the aes ctx...*/ ++ struct fh_aes_reqctx *reqctx; /*bind to the req ctx..*/ ++ struct scatterlist *sg_src; /*rec the src data need to be handled*/ ++ struct scatterlist *sg_dst; /*rec the dst data need to be handled*/ ++ struct tasklet_struct tasklet; /*async process the crypto*/ ++ struct ablkcipher_request *req; /*active req...*/ ++ struct crypto_queue queue; ++ unsigned char *ctl_src_xbuf; ++ unsigned char *ctl_dst_xbuf; ++ unsigned char *ctl_raw_src_xbuf; ++ unsigned char *ctl_raw_dst_xbuf; ++ struct scatterlist src_sg[1]; ++ struct scatterlist dst_sg[1]; ++ struct completion done; ++ struct workqueue_struct *workqueue; ++ struct work_struct work; ++ struct af_alg_usr_def *p_usr_def; ++}; ++ ++ ++/*#define FH_AES_SELF_TEST*/ ++/*#define FH_AES_DEBUG*/ ++#ifdef FH_AES_DEBUG ++#define AES_DBG(fmt, args...) printk(fmt, ## args) ++#else ++#define AES_DBG(fmt, args...) do { } while (0) ++#endif ++ ++#define AES_PRINT_RESULT(fmt, args...) printk(fmt, ## args) ++ ++#endif /* fh_AES_H_ */ ++ ++ +diff --git a/drivers/crypto/fh_aes_test.c b/drivers/crypto/fh_aes_test.c +new file mode 100644 +index 00000000..a31a73bd +--- /dev/null ++++ b/drivers/crypto/fh_aes_test.c +@@ -0,0 +1,937 @@ ++/* ++ * fh_aes_test.c ++ * ++ * Created on: May 7, 2015 ++ * Author: yu.zhang ++ */ ++#ifdef CONFIG_FH_AES_SELF_TEST ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/errno.h> ++#include <linux/in.h> ++#include <linux/ioport.h> ++#include <linux/slab.h> ++#include <linux/mm.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++#include <linux/skbuff.h> ++#include <linux/highmem.h> ++#include <linux/proc_fs.h> ++#include <linux/ctype.h> ++#include <linux/version.h> ++#include <linux/spinlock.h> ++#include <linux/dma-mapping.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/bitops.h> ++#include <linux/io.h> ++#include <linux/irqreturn.h> ++#include <asm/irq.h> ++#include <asm/page.h> ++#include <crypto/hash.h> ++#include <linux/err.h> ++#include <linux/module.h> ++#include <linux/scatterlist.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#include <crypto/rng.h> ++#include "fh_aes.h" ++ ++ ++ ++#define XBUFSIZE 128 ++ ++struct tcrypt_result { ++ struct completion completion; ++ int err; ++}; ++ ++static void tcrypt_complete(struct crypto_async_request *req, int err) ++{ ++ struct tcrypt_result *res = req->data; ++ if (err == -EINPROGRESS) ++ return; ++// res->err = err; ++ AES_DBG("crypt all over....\n"); ++ complete(&res->completion); ++ ++} ++ ++static int testmgr_alloc_buf(char *buf[XBUFSIZE]) ++{ ++ int i; ++ for (i = 0; i < XBUFSIZE; i++) { ++ buf[i] = (void *)__get_free_page(GFP_KERNEL); ++ if (!buf[i]) ++ goto err_free_buf; ++ } ++ ++ return 0; ++err_free_buf: ++ while (i-- > 0) ++ free_page((unsigned long)buf[i]); ++ ++ return -ENOMEM; ++} ++ ++static void testmgr_free_buf(char *buf[XBUFSIZE]) ++{ ++ int i; ++ ++ for (i = 0; i < XBUFSIZE; i++) ++ free_page((unsigned long)buf[i]); ++} ++ ++void cesa_data_print(char *string, u8 *data, u32 length, u8 align) ++{ ++ u32 i; ++ ++ if (NULL != string) ++ { ++ printk("%s \n", string); ++ } ++ ++ if (NULL != data) ++ { ++ for(i=0; i<length; i++) ++ { ++ //printk("%02x ", data[i]); ++ printk("0x%02x,", data[i]); ++ if(0 == ((i+1)%align))//(0 == ((i+1) & (align-1))) ++ { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++ } ++} ++ ++static struct tcrypt_result result; ++static const unsigned char aes_plain_text[] = { ++ 0x6b, 0xc1, 0xbe, 0xe2, ++ 0x2e, 0x40, 0x9f, 0x96, ++ 0xe9, 0x3d, 0x7e, 0x11, ++ 0x73, 0x93, 0x17, 0x2a, ++ 0xae, 0x2d, 0x8a, 0x57, ++ 0x1e, 0x03, 0xac, 0x9c, ++ 0x9e, 0xb7, 0x6f, 0xac, ++ 0x45, 0xaf, 0x8e, 0x51, ++ 0x30, 0xc8, 0x1c, 0x46, ++ 0xa3, 0x5c, 0xe4, 0x11, ++ 0xe5, 0xfb, 0xc1, 0x19, ++ 0x1a, 0x0a, 0x52, 0xef, ++ 0xf6, 0x9f, 0x24, 0x45, ++ 0xdf, 0x4f, 0x9b, 0x17, ++ 0xad, 0x2b, 0x41, 0x7b, ++ 0xe6, 0x6c, 0x37, 0x10, ++}; ++ ++static const unsigned char aes_ecb_128_encrypt_text[] = ++{ ++ 0x3a, 0xd7, 0x7b, 0xb4, ++ 0x0d, 0x7a, 0x36, 0x60, ++ 0xa8, 0x9e, 0xca, 0xf3, ++ 0x24, 0x66, 0xef, 0x97, ++ 0xf5, 0xd3, 0xd5, 0x85, ++ 0x03, 0xb9, 0x69, 0x9d, ++ 0xe7, 0x85, 0x89, 0x5a, ++ 0x96, 0xfd, 0xba, 0xaf, ++ 0x43, 0xb1, 0xcd, 0x7f, ++ 0x59, 0x8e, 0xce, 0x23, ++ 0x88, 0x1b, 0x00, 0xe3, ++ 0xed, 0x03, 0x06, 0x88, ++ 0x7b, 0x0c, 0x78, 0x5e, ++ 0x27, 0xe8, 0xad, 0x3f, ++ 0x82, 0x23, 0x20, 0x71, ++ 0x04, 0x72, 0x5d, 0xd4, ++}; ++ ++static const unsigned char aes_cbc_128_encrypt_text[] = { ++ ++ 0x76, 0x49, 0xab, 0xac, ++ 0x81, 0x19, 0xb2, 0x46, ++ 0xce, 0xe9, 0x8e, 0x9b, ++ 0x12, 0xe9, 0x19, 0x7d, ++ 0x50, 0x86, 0xcb, 0x9b, ++ 0x50, 0x72, 0x19, 0xee, ++ 0x95, 0xdb, 0x11, 0x3a, ++ 0x91, 0x76, 0x78, 0xb2, ++ 0x73, 0xbe, 0xd6, 0xb8, ++ 0xe3, 0xc1, 0x74, 0x3b, ++ 0x71, 0x16, 0xe6, 0x9e, ++ 0x22, 0x22, 0x95, 0x16, ++ 0x3f, 0xf1, 0xca, 0xa1, ++ 0x68, 0x1f, 0xac, 0x09, ++ 0x12, 0x0e, 0xca, 0x30, ++ 0x75, 0x86, 0xe1, 0xa7, ++ ++}; ++ ++static const unsigned char aes_ctr_128_encrypt_text[] = ++{ ++ 0x3b, 0x3f, 0xd9, 0x2e, ++ 0xb7, 0x2d, 0xad, 0x20, ++ 0x33, 0x34, 0x49, 0xf8, ++ 0xe8, 0x3c, 0xfb, 0x4a, ++ 0x01, 0x0c, 0x04, 0x19, ++ 0x99, 0xe0, 0x3f, 0x36, ++ 0x44, 0x86, 0x24, 0x48, ++ 0x3e, 0x58, 0x2d, 0x0e, ++ 0xa6, 0x22, 0x93, 0xcf, ++ 0xa6, 0xdf, 0x74, 0x53, ++ 0x5c, 0x35, 0x41, 0x81, ++ 0x16, 0x87, 0x74, 0xdf, ++ 0x2d, 0x55, 0xa5, 0x47, ++ 0x06, 0x27, 0x3c, 0x50, ++ 0xd7, 0xb4, 0xf8, 0xa8, ++ 0xcd, 0xdc, 0x6e, 0xd7, ++}; ++ ++static const unsigned char aes_ofb_128_encrypt_text[] = ++{ ++ 0x3b, 0x3f, 0xd9, 0x2e, ++ 0xb7, 0x2d, 0xad, 0x20, ++ 0x33, 0x34, 0x49, 0xf8, ++ 0xe8, 0x3c, 0xfb, 0x4a, ++ 0x77, 0x89, 0x50, 0x8d, ++ 0x16, 0x91, 0x8f, 0x03, ++ 0xf5, 0x3c, 0x52, 0xda, ++ 0xc5, 0x4e, 0xd8, 0x25, ++ 0x97, 0x40, 0x05, 0x1e, ++ 0x9c, 0x5f, 0xec, 0xf6, ++ 0x43, 0x44, 0xf7, 0xa8, ++ 0x22, 0x60, 0xed, 0xcc, ++ 0x30, 0x4c, 0x65, 0x28, ++ 0xf6, 0x59, 0xc7, 0x78, ++ 0x66, 0xa5, 0x10, 0xd9, ++ 0xc1, 0xd6, 0xae, 0x5e, ++}; ++ ++static const unsigned char aes_cfb_128_encrypt_text[] = ++{ ++ 0x3b, 0x79, 0x42, 0x4c, ++ 0x9c, 0x0d, 0xd4, 0x36, ++ 0xba, 0xce, 0x9e, 0x0e, ++ 0xd4, 0x58, 0x6a, 0x4f, ++}; ++ ++static const unsigned char aes_ecb_192_encrypt_text[] = ++{ ++ 0xbd, 0x33, 0x4f, 0x1d, ++ 0x6e, 0x45, 0xf2, 0x5f, ++ 0xf7, 0x12, 0xa2, 0x14, ++ 0x57, 0x1f, 0xa5, 0xcc, ++ 0x97, 0x41, 0x04, 0x84, ++ 0x6d, 0x0a, 0xd3, 0xad, ++ 0x77, 0x34, 0xec, 0xb3, ++ 0xec, 0xee, 0x4e, 0xef, ++ 0xef, 0x7a, 0xfd, 0x22, ++ 0x70, 0xe2, 0xe6, 0x0a, ++ 0xdc, 0xe0, 0xba, 0x2f, ++ 0xac, 0xe6, 0x44, 0x4e, ++ 0x9a, 0x4b, 0x41, 0xba, ++ 0x73, 0x8d, 0x6c, 0x72, ++ 0xfb, 0x16, 0x69, 0x16, ++ 0x03, 0xc1, 0x8e, 0x0e, ++}; ++ ++static const unsigned char aes_cbc_192_encrypt_text[] = { ++ 0x4f, 0x02, 0x1d, 0xb2, ++ 0x43, 0xbc, 0x63, 0x3d, ++ 0x71, 0x78, 0x18, 0x3a, ++ 0x9f, 0xa0, 0x71, 0xe8, ++ 0xb4, 0xd9, 0xad, 0xa9, ++ 0xad, 0x7d, 0xed, 0xf4, ++ 0xe5, 0xe7, 0x38, 0x76, ++ 0x3f, 0x69, 0x14, 0x5a, ++ 0x57, 0x1b, 0x24, 0x20, ++ 0x12, 0xfb, 0x7a, 0xe0, ++ 0x7f, 0xa9, 0xba, 0xac, ++ 0x3d, 0xf1, 0x02, 0xe0, ++ 0x08, 0xb0, 0xe2, 0x79, ++ 0x88, 0x59, 0x88, 0x81, ++ 0xd9, 0x20, 0xa9, 0xe6, ++ 0x4f, 0x56, 0x15, 0xcd, ++}; ++ ++static const unsigned char aes_ctr_192_encrypt_text[] = ++{ ++ 0xcd, 0xc8, 0x0d, 0x6f, ++ 0xdd, 0xf1, 0x8c, 0xab, ++ 0x34, 0xc2, 0x59, 0x09, ++ 0xc9, 0x9a, 0x41, 0x74, ++ 0x37, 0xd8, 0xa6, 0x39, ++ 0x17, 0x1f, 0xdc, 0xca, ++ 0x63, 0xeb, 0xd1, 0x7c, ++ 0xe2, 0xd7, 0x32, 0x1a, ++ 0x79, 0xa0, 0xc9, 0x6b, ++ 0x53, 0xc7, 0xee, 0xec, ++ 0xd9, 0xed, 0x71, 0x57, ++ 0xc4, 0x44, 0xfc, 0x7a, ++ 0x84, 0x5c, 0x37, 0xb2, ++ 0xf5, 0x11, 0x69, 0x7b, ++ 0x0e, 0x89, 0xd5, 0xed, ++ 0x60, 0xc4, 0xd4, 0x9e, ++}; ++ ++static const unsigned char aes_ofb_192_encrypt_text[] = ++{ ++ 0xcd, 0xc8, 0x0d, 0x6f, ++ 0xdd, 0xf1, 0x8c, 0xab, ++ 0x34, 0xc2, 0x59, 0x09, ++ 0xc9, 0x9a, 0x41, 0x74, ++ 0xfc, 0xc2, 0x8b, 0x8d, ++ 0x4c, 0x63, 0x83, 0x7c, ++ 0x09, 0xe8, 0x17, 0x00, ++ 0xc1, 0x10, 0x04, 0x01, ++ 0x8d, 0x9a, 0x9a, 0xea, ++ 0xc0, 0xf6, 0x59, 0x6f, ++ 0x55, 0x9c, 0x6d, 0x4d, ++ 0xaf, 0x59, 0xa5, 0xf2, ++ 0x6d, 0x9f, 0x20, 0x08, ++ 0x57, 0xca, 0x6c, 0x3e, ++ 0x9c, 0xac, 0x52, 0x4b, ++ 0xd9, 0xac, 0xc9, 0x2a, ++}; ++ ++static const unsigned char aes_cfb_192_encrypt_text[] = ++{ ++ 0xcd, 0xa2, 0x52, 0x1e, ++ 0xf0, 0xa9, 0x05, 0xca, ++ 0x44, 0xcd, 0x05, 0x7c, ++ 0xbf, 0x0d, 0x47, 0xa0, ++}; ++ ++static const unsigned char aes_ecb_256_encrypt_text[] = ++{ ++ 0xf3, 0xee, 0xd1, 0xbd, ++ 0xb5, 0xd2, 0xa0, 0x3c, ++ 0x06, 0x4b, 0x5a, 0x7e, ++ 0x3d, 0xb1, 0x81, 0xf8, ++ 0x59, 0x1c, 0xcb, 0x10, ++ 0xd4, 0x10, 0xed, 0x26, ++ 0xdc, 0x5b, 0xa7, 0x4a, ++ 0x31, 0x36, 0x28, 0x70, ++ 0xb6, 0xed, 0x21, 0xb9, ++ 0x9c, 0xa6, 0xf4, 0xf9, ++ 0xf1, 0x53, 0xe7, 0xb1, ++ 0xbe, 0xaf, 0xed, 0x1d, ++ 0x23, 0x30, 0x4b, 0x7a, ++ 0x39, 0xf9, 0xf3, 0xff, ++ 0x06, 0x7d, 0x8d, 0x8f, ++ 0x9e, 0x24, 0xec, 0xc7, ++}; ++ ++static const unsigned char aes_cbc_256_encrypt_text[] = { ++ 0xf5, 0x8c, 0x4c, 0x04, ++ 0xd6, 0xe5, 0xf1, 0xba, ++ 0x77, 0x9e, 0xab, 0xfb, ++ 0x5f, 0x7b, 0xfb, 0xd6, ++ 0x9c, 0xfc, 0x4e, 0x96, ++ 0x7e, 0xdb, 0x80, 0x8d, ++ 0x67, 0x9f, 0x77, 0x7b, ++ 0xc6, 0x70, 0x2c, 0x7d, ++ 0x39, 0xf2, 0x33, 0x69, ++ 0xa9, 0xd9, 0xba, 0xcf, ++ 0xa5, 0x30, 0xe2, 0x63, ++ 0x04, 0x23, 0x14, 0x61, ++ 0xb2, 0xeb, 0x05, 0xe2, ++ 0xc3, 0x9b, 0xe9, 0xfc, ++ 0xda, 0x6c, 0x19, 0x07, ++ 0x8c, 0x6a, 0x9d, 0x1b, ++}; ++ ++static const unsigned char aes_ctr_256_encrypt_text[] = ++{ ++ 0xdc, 0x7e, 0x84, 0xbf, ++ 0xda, 0x79, 0x16, 0x4b, ++ 0x7e, 0xcd, 0x84, 0x86, ++ 0x98, 0x5d, 0x38, 0x60, ++ 0xd5, 0x77, 0x78, 0x8b, ++ 0x8d, 0x8a, 0x85, 0x74, ++ 0x55, 0x13, 0xa5, 0xd5, ++ 0x0f, 0x82, 0x1f, 0x30, ++ 0xff, 0xe9, 0x6d, 0x5c, ++ 0xf5, 0x4b, 0x23, 0x8d, ++ 0xcc, 0x8d, 0x67, 0x83, ++ 0xa8, 0x7f, 0x3b, 0xea, ++ 0xe9, 0xaf, 0x54, 0x63, ++ 0x44, 0xcb, 0x9c, 0xa4, ++ 0xd1, 0xe5, 0x53, 0xff, ++ 0xc0, 0x6b, 0xc7, 0x3e, ++}; ++ ++static const unsigned char aes_ofb_256_encrypt_text[] = ++{ ++ 0xdc, 0x7e, 0x84, 0xbf, ++ 0xda, 0x79, 0x16, 0x4b, ++ 0x7e, 0xcd, 0x84, 0x86, ++ 0x98, 0x5d, 0x38, 0x60, ++ 0x4f, 0xeb, 0xdc, 0x67, ++ 0x40, 0xd2, 0x0b, 0x3a, ++ 0xc8, 0x8f, 0x6a, 0xd8, ++ 0x2a, 0x4f, 0xb0, 0x8d, ++ 0x71, 0xab, 0x47, 0xa0, ++ 0x86, 0xe8, 0x6e, 0xed, ++ 0xf3, 0x9d, 0x1c, 0x5b, ++ 0xba, 0x97, 0xc4, 0x08, ++ 0x01, 0x26, 0x14, 0x1d, ++ 0x67, 0xf3, 0x7b, 0xe8, ++ 0x53, 0x8f, 0x5a, 0x8b, ++ 0xe7, 0x40, 0xe4, 0x84, ++}; ++ ++static const unsigned char aes_cfb_256_encrypt_text[] = ++{ ++ 0xdc, 0x1f, 0x1a, 0x85, ++ 0x20, 0xa6, 0x4d, 0xb5, ++ 0x5f, 0xcc, 0x8a, 0xc5, ++ 0x54, 0x84, 0x4e, 0x88, ++}; ++ ++static const unsigned char des_ecb_plain_text[] = ++{ ++ 0x80, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x40, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x20, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x10, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x08, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x04, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x02, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x01, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static const unsigned char des_ecb_encrypt_text[] = ++{ ++ 0xca, 0xee, 0x53, 0x4c, ++ 0x52, 0x3e, 0x1e, 0x79, ++ 0xdc, 0x6c, 0x45, 0x73, ++ 0x61, 0xc7, 0xb5, 0xd9, ++ 0x94, 0xc0, 0x83, 0xb0, ++ 0x53, 0xf8, 0xba, 0x52, ++ 0x10, 0x68, 0xe3, 0xa8, ++ 0x88, 0xd2, 0x00, 0x1c, ++ 0x9b, 0x5a, 0xe1, 0x79, ++ 0x4d, 0xfa, 0x4e, 0x12, ++ 0x17, 0x92, 0xe3, 0xf0, ++ 0x79, 0x62, 0x4d, 0xcb, ++ 0x60, 0x36, 0x31, 0xf0, ++ 0xa2, 0xc5, 0x87, 0x4f, ++ 0x24, 0xc7, 0x4a, 0x9a, ++ 0x79, 0x75, 0x4b, 0xc7, ++}; ++ ++static const unsigned char des_cbc_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x68, 0x65, 0x20, 0x74, ++ 0x69, 0x6d, 0x65, 0x20, ++ 0x66, 0x6f, 0x72, 0x20, ++ 0x61, 0x6c, 0x6c, 0x20, ++ ++}; ++ ++static const unsigned char des_cbc_encrypt_text[] = ++{ ++ 0xe5, 0xc7, 0xcd, 0xde, ++ 0x87, 0x2b, 0xf2, 0x7c, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des_ofb_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des_ofb_encrypt_text[] = ++{ ++ 0xf3, 0x09, 0x62, 0x49, ++ 0xc7, 0xf4, 0x6e, 0x51, ++ 0x1e, 0x7e, 0x5e, 0x50, ++ 0xcb, 0xbe, 0xc4, 0x10, ++ 0x33, 0x35, 0xa1, 0x8a, ++ 0xde, 0x4a, 0x91, 0x15, ++}; ++ ++static const unsigned char des_cfb_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des_cfb_encrypt_text[] = ++{ ++ 0xf3, 0x1f, 0xda, 0x07, ++ 0x01, 0x14, 0x62, 0xee, ++ 0x33, 0x79, 0xda, 0x67, ++ 0xd6, 0xd8, 0x94, 0x3b, ++ 0x71, 0xde, 0xe2, 0xf3, ++ 0x50, 0x80, 0xd6, 0x2b, ++}; ++ ++static const unsigned char des3_ecb_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des3_ecb_encrypt_text[] = ++{ ++ 0x31, 0x4f, 0x83, 0x27, ++ 0xfa, 0x7a, 0x09, 0xa8, ++ 0xd5, 0x89, 0x5f, 0xad, ++ 0xe9, 0x8f, 0xae, 0xdf, ++ 0x98, 0xf4, 0x70, 0xeb, ++ 0x35, 0x53, 0xa5, 0xda, ++}; ++ ++static const unsigned char des3_cbc_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des3_cbc_encrypt_text[] = ++{ ++ 0xf3, 0xc0, 0xff, 0x02, ++ 0x6c, 0x02, 0x30, 0x89, ++ 0xc4, 0x3a, 0xdd, 0x8f, ++ 0xd8, 0xcd, 0x5e, 0x43, ++ 0x2b, 0xfd, 0x41, 0xd3, ++ 0x13, 0x0b, 0xcf, 0x40, ++}; ++ ++static const unsigned char des3_ofb_plain_text[] = ++{ ++ 0xe6, 0xf7, 0x72, 0x06, ++ 0x97, 0x32, 0x07, 0x04, ++ 0x3e, 0x93, 0x40, 0x08, ++ 0xc3, 0x89, 0xc0, 0x0f, ++ 0x83, 0x78, 0x84, 0x99, ++ 0xa7, 0xc0, 0x5f, 0x06, ++}; ++ ++static const unsigned char des3_ofb_encrypt_text[] = ++{ ++ 0x46, 0xe6, 0xc2, 0x7a, ++ 0xe4, 0x51, 0x34, 0x71, ++ 0xcc, 0x7c, 0x01, 0x7c, ++ 0xa8, 0x82, 0x2b, 0x28, ++ 0x62, 0xf5, 0x7c, 0x40, ++ 0x2a, 0x8a, 0x8b, 0xaf, ++}; ++ ++static const unsigned char des3_cfb_plain_text[] = ++{ ++ 0x4e, 0x6f, 0x77, 0x20, ++ 0x69, 0x73, 0x20, 0x74, ++ 0x43, 0xe9, 0x34, 0x00, ++ 0x8c, 0x38, 0x9c, 0x0f, ++ 0x68, 0x37, 0x88, 0x49, ++ 0x9a, 0x7c, 0x05, 0xf6, ++}; ++ ++static const unsigned char des3_cfb_encrypt_text[] = ++{ ++ 0xee, 0x9b, 0x04, 0xff, ++ 0xca, 0xce, 0xc8, 0x06, ++ 0x5b, 0xcc, 0x4f, 0x67, ++ 0x8f, 0x00, 0xd7, 0x14, ++ 0x4d, 0xf6, 0x74, 0xfc, ++ 0xd6, 0x98, 0x9f, 0x8f, ++}; ++ ++static int fh_ablkcipher_self_test(const char *alg_name, ++ u8 *src_data, ++ u8 *res_data, ++ u32 len, ++ u8 *key, u32 keylen, ++ u8 *iv ++ ) ++{ ++ struct crypto_ablkcipher *tfm; ++ struct ablkcipher_request *req; ++ const char *algo; ++ ++ struct scatterlist sg[8]; ++ struct scatterlist dst_sg[8]; ++ ++ char *xbuf[XBUFSIZE]; ++ char *dst_xbuf[XBUFSIZE]; ++ ++ void *data; ++ void *dst_data; ++ ++ if (testmgr_alloc_buf(xbuf)) { ++ AES_DBG("no pages.\n"); ++ return -1; ++ } ++ ++ if (testmgr_alloc_buf(dst_xbuf)) { ++ AES_DBG("no pages.\n"); ++ return -1; ++ } ++ ++ AES_DBG("aes self test get in...\n"); ++ AES_DBG(" *_* step 1\n"); ++ tfm = ++ crypto_alloc_ablkcipher(alg_name, ++ CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_ASYNC, 0); ++ if (IS_ERR(tfm)) { ++ AES_DBG("aes_test: failed to alloc cipher!\n"); ++ return -1; ++ } ++ ++ AES_DBG(" *_* step 2\n"); ++ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm)); ++ init_completion(&result.completion); ++ ++ AES_DBG(" *_* step 3\n"); ++ crypto_ablkcipher_setkey(tfm, (u8 *) key, keylen); ++ ++ AES_DBG(" *_* step 4\n"); ++ req = ablkcipher_request_alloc(tfm, GFP_KERNEL); ++ if (!req) { ++ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request " ++ "for %s\n", algo); ++ return -1; ++ } ++ ++ AES_DBG(" *_* step 5\n"); ++ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, ++ tcrypt_complete, &result); ++ ++ AES_DBG(" *_* step 6\n"); ++ data = xbuf[0]; ++ dst_data = dst_xbuf[0]; ++ ++ memcpy(data, src_data, len); ++ memset(dst_data, 0, len); ++ sg_init_one(&sg[0], data, len); ++ sg_init_one(&dst_sg[0], dst_data, len); ++ ++ AES_DBG(" *_* step 7\n"); ++ ablkcipher_request_set_crypt(req, sg, dst_sg, len, (void *)iv); ++ ++ AES_DBG(" *_* step 8\n"); ++ crypto_ablkcipher_encrypt(req); ++ ++ wait_for_completion(&result.completion); ++ ++ if (memcmp(dst_data, res_data, len)) ++ AES_PRINT_RESULT(" encrypt error....\n"); ++ else ++ AES_PRINT_RESULT(" encrypt ok....\n"); ++ ++ memcpy(data, res_data, len); ++ memset(dst_data, 0, len); ++ sg_init_one(&sg[0], data, len); ++ sg_init_one(&dst_sg[0], dst_data, len); ++ AES_DBG(" *_* step 8\n"); ++ ablkcipher_request_set_crypt(req, sg, dst_sg, len, (void *)iv); ++ AES_DBG(" *_* step 9\n"); ++ crypto_ablkcipher_decrypt(req); ++ wait_for_completion(&result.completion); ++ ++ if (memcmp(dst_data, src_data, len)) ++ AES_PRINT_RESULT(" decrypt error....\n"); ++ else ++ AES_PRINT_RESULT(" decrypt ok....\n"); ++ ++ ++ ++ ablkcipher_request_free(req); ++ crypto_free_ablkcipher(tfm); ++ testmgr_free_buf(xbuf); ++ testmgr_free_buf(dst_xbuf); ++ ++ return 0; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++void fh_aes_self_test_all(void) ++{ ++ u32 aes128_key[4] = { ++ 0x16157e2b, ++ 0xa6d2ae28, ++ 0x8815f7ab, ++ 0x3c4fcf09 ++ }; ++ u32 aes_iv[4] = { ++ 0x03020100, ++ 0x07060504, ++ 0x0b0a0908, ++ 0x0f0e0d0c ++ }; ++ u32 aes192_key[] = { ++ 0xf7b0738e, ++ 0x52640eda, ++ 0x2bf310c8, ++ 0xe5799080, ++ 0xd2eaf862, ++ 0x7b6b2c52, ++ }; ++ u32 aes256_key[] = { ++ 0x10eb3d60, ++ 0xbe71ca15, ++ 0xf0ae732b, ++ 0x81777d85, ++ 0x072c351f, ++ 0xd708613b, ++ 0xa310982d, ++ 0xf4df1409, ++ }; ++ ++ u32 des_iv[] = { ++ 0x78563412, ++ 0xefcdab90, ++ }; ++ ++ u32 des_key[] = { ++ 0x67452301, ++ 0xefcdab89, ++ }; ++ ++ u32 des3_key[] = { ++ 0x67452301, ++ 0xefcdab89, ++ 0x89674523, ++ 0x01efcdab, ++ 0xab896745, ++ 0x2301efcd, ++ }; ++ ++ pr_info("aes ecb128 self test go...\n"); ++ fh_ablkcipher_self_test("ecb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ecb_128_encrypt_text, ++ 64, ++ (u8 *)aes128_key, 16, ++ NULL); ++ ++ pr_info("aes cbc128 self test go...\n"); ++ fh_ablkcipher_self_test("cbc-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cbc_128_encrypt_text, ++ 64, ++ (u8 *)aes128_key, 16, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ctr128 self test go...\n"); ++ fh_ablkcipher_self_test("ctr-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ctr_128_encrypt_text, ++ 64, ++ (u8 *)aes128_key, 16, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ofb128 self test go...\n"); ++ fh_ablkcipher_self_test("ofb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ofb_128_encrypt_text, ++ 64, ++ (u8 *)aes128_key, 16, ++ (u8 *)aes_iv); ++ ++ pr_info("aes cfb128 self test go...\n"); ++ fh_ablkcipher_self_test("cfb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cfb_128_encrypt_text, ++ 16, ++ (u8 *)aes128_key, 16, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ecb192 self test go...\n"); ++ fh_ablkcipher_self_test("ecb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ecb_192_encrypt_text, ++ 64, ++ (u8 *)aes192_key, 24, ++ NULL); ++ ++ pr_info("aes cbc192 self test go...\n"); ++ fh_ablkcipher_self_test("cbc-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cbc_192_encrypt_text, ++ 64, ++ (u8 *)aes192_key, 24, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ctr192 self test go...\n"); ++ fh_ablkcipher_self_test("ctr-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ctr_192_encrypt_text, ++ 64, ++ (u8 *)aes192_key, 24, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ofb192 self test go...\n"); ++ fh_ablkcipher_self_test("ofb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ofb_192_encrypt_text, ++ 64, ++ (u8 *)aes192_key, 24, ++ (u8 *)aes_iv); ++ ++ pr_info("aes cfb192 self test go...\n"); ++ fh_ablkcipher_self_test("cfb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cfb_192_encrypt_text, ++ 16, ++ (u8 *)aes192_key, 24, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ecb256 self test go...\n"); ++ fh_ablkcipher_self_test("ecb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ecb_256_encrypt_text, ++ 64, ++ (u8 *)aes256_key, 32, ++ NULL); ++ ++ pr_info("aes cbc256 self test go...\n"); ++ fh_ablkcipher_self_test("cbc-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cbc_256_encrypt_text, ++ 64, ++ (u8 *)aes256_key, 32, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ctr256 self test go...\n"); ++ fh_ablkcipher_self_test("ctr-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ctr_256_encrypt_text, ++ 64, ++ (u8 *)aes256_key, 32, ++ (u8 *)aes_iv); ++ ++ pr_info("aes ofb256 self test go...\n"); ++ fh_ablkcipher_self_test("ofb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_ofb_256_encrypt_text, ++ 64, ++ (u8 *)aes256_key, 32, ++ (u8 *)aes_iv); ++ ++ pr_info("aes cfb256 self test go...\n"); ++ fh_ablkcipher_self_test("cfb-aes-fh", ++ (u8 *)aes_plain_text, ++ (u8 *)aes_cfb_256_encrypt_text, ++ 16, ++ (u8 *)aes256_key, 32, ++ (u8 *)aes_iv); ++ ++ pr_info("des ecb self test go...\n"); ++ fh_ablkcipher_self_test("ecb-des-fh", ++ (u8 *)des_ecb_plain_text, ++ (u8 *)des_ecb_encrypt_text, ++ 64, ++ (u8 *)des_key, 8, ++ NULL); ++ ++ pr_info("des cbc self test go...\n"); ++ fh_ablkcipher_self_test("cbc-des-fh", ++ (u8 *)des_cbc_plain_text, ++ (u8 *)des_cbc_encrypt_text, ++ 24, ++ (u8 *)des_key, 8, ++ (u8 *)des_iv); ++ ++ pr_info("des ofb self test go...\n"); ++ fh_ablkcipher_self_test("ofb-des-fh", ++ (u8 *)des_ofb_plain_text, ++ (u8 *)des_ofb_encrypt_text, ++ 24, ++ (u8 *)des_key, 8, ++ (u8 *)des_iv); ++ ++ pr_info("des cfb self test go...\n"); ++ fh_ablkcipher_self_test("cfb-des-fh", ++ (u8 *)des_cfb_plain_text, ++ (u8 *)des_cfb_encrypt_text, ++ 24, ++ (u8 *)des_key, 8, ++ (u8 *)des_iv); ++ ++ ++ pr_info("des3 ecb self test go...\n"); ++ fh_ablkcipher_self_test("ecb-des3-fh", ++ (u8 *)des3_ecb_plain_text, ++ (u8 *)des3_ecb_encrypt_text, ++ 24, ++ (u8 *)des3_key, 24, ++ NULL); ++ ++ pr_info("des3 cbc self test go...\n"); ++ fh_ablkcipher_self_test("cbc-des3-fh", ++ (u8 *)des3_cbc_plain_text, ++ (u8 *)des3_cbc_encrypt_text, ++ 24, ++ (u8 *)des3_key, 24, ++ (u8 *)des_iv); ++ ++ pr_info("des3 ofb self test go...\n"); ++ fh_ablkcipher_self_test("ofb-des3-fh", ++ (u8 *)des3_ofb_plain_text, ++ (u8 *)des3_ofb_encrypt_text, ++ 24, ++ (u8 *)des3_key, 24, ++ (u8 *)des_iv); ++ ++ pr_info("des3 cfb self test go...\n"); ++ fh_ablkcipher_self_test("cfb-des3-fh", ++ (u8 *)des3_cfb_plain_text, ++ (u8 *)des3_cfb_encrypt_text, ++ 24, ++ (u8 *)des3_key, 24, ++ (u8 *)des_iv); ++} ++ ++#endif +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index 25cf327c..76f36670 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -89,6 +89,25 @@ config DW_DMAC + Support the Synopsys DesignWare AHB DMA controller. This + can be integrated in chips such as the Atmel AT32ap7000. + ++config FH_DMAC ++ tristate "FH DesignWare AHB DMA support" ++ depends on HAVE_CLK ++ select DMA_ENGINE ++ ++ help ++ Support the Synopsys DesignWare AHB DMA controller. This ++ can be integrated in chips such as the FullHan. ++ ++if FH_DMAC ++ ++config FH_DMAC_MISC ++ bool "FH DMAC Misc Device Enable" ++ default y ++ help ++ FH DMAC Misc Device Enable ++ ++endif ++ + config AT_HDMAC + tristate "Atmel AHB DMA support" + depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 +@@ -271,5 +290,7 @@ config DMATEST + help + Simple DMA test client. Say N unless you're debugging a + DMA Device driver. +- + endif ++ ++ ++ +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index 836095ab..252d297a 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -25,3 +25,4 @@ obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o + obj-$(CONFIG_PL330_DMA) += pl330.o + obj-$(CONFIG_PCH_DMA) += pch_dma.o + obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o ++obj-$(CONFIG_FH_DMAC) += fh_dmac.o +\ No newline at end of file +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index 8bcb15fb..ce1de9b4 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -45,6 +45,9 @@ + * See Documentation/dmaengine.txt for more details + */ + ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/dma-mapping.h> + #include <linux/init.h> + #include <linux/module.h> + #include <linux/mm.h> +@@ -61,9 +64,9 @@ + #include <linux/slab.h> + + static DEFINE_MUTEX(dma_list_mutex); ++static DEFINE_IDR(dma_idr); + static LIST_HEAD(dma_device_list); + static long dmaengine_ref_count; +-static struct idr dma_idr; + + /* --- sysfs implementation --- */ + +@@ -170,7 +173,8 @@ static struct class dma_devclass = { + #define dma_device_satisfies_mask(device, mask) \ + __dma_device_satisfies_mask((device), &(mask)) + static int +-__dma_device_satisfies_mask(struct dma_device *device, dma_cap_mask_t *want) ++__dma_device_satisfies_mask(struct dma_device *device, ++ const dma_cap_mask_t *want) + { + dma_cap_mask_t has; + +@@ -260,10 +264,13 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) + do { + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); + if (time_after_eq(jiffies, dma_sync_wait_timeout)) { +- printk(KERN_ERR "dma_sync_wait_timeout!\n"); ++ pr_err("%s: timeout!\n", __func__); + return DMA_ERROR; + } +- } while (status == DMA_IN_PROGRESS); ++ if (status != DMA_IN_PROGRESS) ++ break; ++ cpu_relax(); ++ } while (1); + + return status; + } +@@ -311,7 +318,7 @@ static int __init dma_channel_table_init(void) + } + + if (err) { +- pr_err("dmaengine: initialization failure\n"); ++ pr_err("initialization failure\n"); + for_each_dma_cap_mask(cap, dma_cap_mask_all) + if (channel_table[cap]) + free_percpu(channel_table[cap]); +@@ -331,6 +338,20 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) + } + EXPORT_SYMBOL(dma_find_channel); + ++/* ++ * net_dma_find_channel - find a channel for net_dma ++ * net_dma has alignment requirements ++ */ ++struct dma_chan *net_dma_find_channel(void) ++{ ++ struct dma_chan *chan = dma_find_channel(DMA_MEMCPY); ++ if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1)) ++ return NULL; ++ ++ return chan; ++} ++EXPORT_SYMBOL(net_dma_find_channel); ++ + /** + * dma_issue_pending_all - flush all pending operations across all channels + */ +@@ -442,7 +463,8 @@ static void dma_channel_rebalance(void) + } + } + +-static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_device *dev, ++static struct dma_chan *private_candidate(const dma_cap_mask_t *mask, ++ struct dma_device *dev, + dma_filter_fn fn, void *fn_param) + { + struct dma_chan *chan; +@@ -484,7 +506,8 @@ static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_devic + * @fn: optional callback to disposition available channels + * @fn_param: opaque parameter to pass to dma_filter_fn + */ +-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param) ++struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, ++ dma_filter_fn fn, void *fn_param) + { + struct dma_device *device, *_d; + struct dma_chan *chan = NULL; +@@ -505,12 +528,12 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v + err = dma_chan_get(chan); + + if (err == -ENODEV) { +- pr_debug("%s: %s module removed\n", __func__, +- dma_chan_name(chan)); ++ pr_debug("%s: %s module removed\n", ++ __func__, dma_chan_name(chan)); + list_del_rcu(&device->global_node); + } else if (err) +- pr_err("dmaengine: failed to get %s: (%d)\n", +- dma_chan_name(chan), err); ++ pr_debug("%s: failed to get %s: (%d)\n", ++ __func__, dma_chan_name(chan), err); + else + break; + if (--device->privatecnt == 0) +@@ -520,13 +543,34 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v + } + mutex_unlock(&dma_list_mutex); + +- pr_debug("%s: %s (%s)\n", __func__, chan ? "success" : "fail", ++ pr_debug("%s: %s (%s)\n", ++ __func__, ++ chan ? "success" : "fail", + chan ? dma_chan_name(chan) : NULL); + + return chan; + } + EXPORT_SYMBOL_GPL(__dma_request_channel); ++#if 0 ++/** ++ * dma_request_slave_channel - try to allocate an exclusive slave channel ++ * @dev: pointer to client device structure ++ * @name: slave channel name ++ */ ++struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name) ++{ ++ /* If device-tree is present get slave info from here */ ++ if (dev->of_node) ++ return of_dma_request_slave_channel(dev->of_node, name); ++ ++ /* If device was enumerated by ACPI get slave info from here */ ++ if (ACPI_HANDLE(dev)) ++ return acpi_dma_request_slave_chan_by_name(dev, name); + ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(dma_request_slave_channel); ++#endif + void dma_release_channel(struct dma_chan *chan) + { + mutex_lock(&dma_list_mutex); +@@ -563,8 +607,8 @@ void dmaengine_get(void) + list_del_rcu(&device->global_node); + break; + } else if (err) +- pr_err("dmaengine: failed to get %s: (%d)\n", +- dma_chan_name(chan), err); ++ pr_debug("%s: failed to get %s: (%d)\n", ++ __func__, dma_chan_name(chan), err); + } + } + +@@ -647,19 +691,19 @@ static bool device_has_all_tx_types(struct dma_device *device) + static int get_dma_id(struct dma_device *device) + { + int rc; ++ int dma_id; + +- idr_retry: +- if (!idr_pre_get(&dma_idr, GFP_KERNEL)) +- return -ENOMEM; + mutex_lock(&dma_list_mutex); +- rc = idr_get_new(&dma_idr, NULL, &device->dev_id); +- mutex_unlock(&dma_list_mutex); +- if (rc == -EAGAIN) +- goto idr_retry; +- else if (rc != 0) +- return rc; + +- return 0; ++ if (!idr_pre_get(&dma_idr, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ rc = idr_get_new(&dma_idr, NULL, &dma_id); ++ if (rc >= 0) ++ device->dev_id = dma_id; ++ ++ mutex_unlock(&dma_list_mutex); ++ return rc < 0 ? rc : 0; + } + + /** +@@ -692,12 +736,12 @@ int dma_async_device_register(struct dma_device *device) + !device->device_prep_dma_interrupt); + BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) && + !device->device_prep_dma_sg); +- BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && +- !device->device_prep_slave_sg); + BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) && + !device->device_prep_dma_cyclic); + BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && + !device->device_control); ++ BUG_ON(dma_has_cap(DMA_INTERLEAVE, device->cap_mask) && ++ !device->device_prep_interleaved_dma); + + BUG_ON(!device->device_alloc_chan_resources); + BUG_ON(!device->device_free_chan_resources); +@@ -1000,7 +1044,7 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) + while (tx->cookie == -EBUSY) { + if (time_after_eq(jiffies, dma_sync_wait_timeout)) { + pr_err("%s timeout waiting for descriptor submission\n", +- __func__); ++ __func__); + return DMA_ERROR; + } + cpu_relax(); +@@ -1049,8 +1093,6 @@ EXPORT_SYMBOL_GPL(dma_run_dependencies); + + static int __init dma_bus_init(void) + { +- idr_init(&dma_idr); +- mutex_init(&dma_list_mutex); + return class_register(&dma_devclass); + } + arch_initcall(dma_bus_init); +diff --git a/drivers/dma/dmaengine.h b/drivers/dma/dmaengine.h +new file mode 100644 +index 00000000..17f983a4 +--- /dev/null ++++ b/drivers/dma/dmaengine.h +@@ -0,0 +1,89 @@ ++/* ++ * The contents of this file are private to DMA engine drivers, and is not ++ * part of the API to be used by DMA engine users. ++ */ ++#ifndef DMAENGINE_H ++#define DMAENGINE_H ++ ++#include <linux/bug.h> ++#include <linux/dmaengine.h> ++ ++/** ++ * dma_cookie_init - initialize the cookies for a DMA channel ++ * @chan: dma channel to initialize ++ */ ++static inline void dma_cookie_init(struct dma_chan *chan) ++{ ++ chan->cookie = DMA_MIN_COOKIE; ++ chan->completed_cookie = DMA_MIN_COOKIE; ++} ++ ++/** ++ * dma_cookie_assign - assign a DMA engine cookie to the descriptor ++ * @tx: descriptor needing cookie ++ * ++ * Assign a unique non-zero per-channel cookie to the descriptor. ++ * Note: caller is expected to hold a lock to prevent concurrency. ++ */ ++static inline dma_cookie_t dma_cookie_assign(struct dma_async_tx_descriptor *tx) ++{ ++ struct dma_chan *chan = tx->chan; ++ dma_cookie_t cookie; ++ ++ cookie = chan->cookie + 1; ++ if (cookie < DMA_MIN_COOKIE) ++ cookie = DMA_MIN_COOKIE; ++ tx->cookie = chan->cookie = cookie; ++ ++ return cookie; ++} ++ ++/** ++ * dma_cookie_complete - complete a descriptor ++ * @tx: descriptor to complete ++ * ++ * Mark this descriptor complete by updating the channels completed ++ * cookie marker. Zero the descriptors cookie to prevent accidental ++ * repeated completions. ++ * ++ * Note: caller is expected to hold a lock to prevent concurrency. ++ */ ++static inline void dma_cookie_complete(struct dma_async_tx_descriptor *tx) ++{ ++ BUG_ON(tx->cookie < DMA_MIN_COOKIE); ++ tx->chan->completed_cookie = tx->cookie; ++ tx->cookie = 0; ++} ++ ++/** ++ * dma_cookie_status - report cookie status ++ * @chan: dma channel ++ * @cookie: cookie we are interested in ++ * @state: dma_tx_state structure to return last/used cookies ++ * ++ * Report the status of the cookie, filling in the state structure if ++ * non-NULL. No locking is required. ++ */ ++static inline enum dma_status dma_cookie_status(struct dma_chan *chan, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ dma_cookie_t used, complete; ++ ++ used = chan->cookie; ++ complete = chan->completed_cookie; ++ barrier(); ++ if (state) { ++ state->last = complete; ++ state->used = used; ++ state->residue = 0; ++ } ++ return dma_async_is_complete(cookie, complete, used); ++} ++ ++static inline void dma_set_residue(struct dma_tx_state *state, u32 residue) ++{ ++ if (state) ++ state->residue = residue; ++} ++ ++#endif +diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h +deleted file mode 100644 +index c3419518..00000000 +--- a/drivers/dma/dw_dmac_regs.h ++++ /dev/null +@@ -1,235 +0,0 @@ +-/* +- * Driver for the Synopsys DesignWare AHB DMA Controller +- * +- * Copyright (C) 2005-2007 Atmel Corporation +- * Copyright (C) 2010-2011 ST Microelectronics +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +- +-#include <linux/dw_dmac.h> +- +-#define DW_DMA_MAX_NR_CHANNELS 8 +- +-/* +- * Redefine this macro to handle differences between 32- and 64-bit +- * addressing, big vs. little endian, etc. +- */ +-#define DW_REG(name) u32 name; u32 __pad_##name +- +-/* Hardware register definitions. */ +-struct dw_dma_chan_regs { +- DW_REG(SAR); /* Source Address Register */ +- DW_REG(DAR); /* Destination Address Register */ +- DW_REG(LLP); /* Linked List Pointer */ +- u32 CTL_LO; /* Control Register Low */ +- u32 CTL_HI; /* Control Register High */ +- DW_REG(SSTAT); +- DW_REG(DSTAT); +- DW_REG(SSTATAR); +- DW_REG(DSTATAR); +- u32 CFG_LO; /* Configuration Register Low */ +- u32 CFG_HI; /* Configuration Register High */ +- DW_REG(SGR); +- DW_REG(DSR); +-}; +- +-struct dw_dma_irq_regs { +- DW_REG(XFER); +- DW_REG(BLOCK); +- DW_REG(SRC_TRAN); +- DW_REG(DST_TRAN); +- DW_REG(ERROR); +-}; +- +-struct dw_dma_regs { +- /* per-channel registers */ +- struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS]; +- +- /* irq handling */ +- struct dw_dma_irq_regs RAW; /* r */ +- struct dw_dma_irq_regs STATUS; /* r (raw & mask) */ +- struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */ +- struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ +- +- DW_REG(STATUS_INT); /* r */ +- +- /* software handshaking */ +- DW_REG(REQ_SRC); +- DW_REG(REQ_DST); +- DW_REG(SGL_REQ_SRC); +- DW_REG(SGL_REQ_DST); +- DW_REG(LAST_SRC); +- DW_REG(LAST_DST); +- +- /* miscellaneous */ +- DW_REG(CFG); +- DW_REG(CH_EN); +- DW_REG(ID); +- DW_REG(TEST); +- +- /* optional encoded params, 0x3c8..0x3 */ +-}; +- +-/* Bitfields in CTL_LO */ +-#define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ +-#define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ +-#define DWC_CTLL_SRC_WIDTH(n) ((n)<<4) +-#define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ +-#define DWC_CTLL_DST_DEC (1<<7) +-#define DWC_CTLL_DST_FIX (2<<7) +-#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */ +-#define DWC_CTLL_SRC_DEC (1<<9) +-#define DWC_CTLL_SRC_FIX (2<<9) +-#define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ +-#define DWC_CTLL_SRC_MSIZE(n) ((n)<<14) +-#define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ +-#define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ +-#define DWC_CTLL_FC(n) ((n) << 20) +-#define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ +-#define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ +-#define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ +-#define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ +-/* plus 4 transfer types for peripheral-as-flow-controller */ +-#define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */ +-#define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */ +-#define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ +-#define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ +- +-/* Bitfields in CTL_HI */ +-#define DWC_CTLH_DONE 0x00001000 +-#define DWC_CTLH_BLOCK_TS_MASK 0x00000fff +- +-/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */ +-#define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ +-#define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ +-#define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ +-#define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ +-#define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ +-#define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ +-#define DWC_CFGL_MAX_BURST(x) ((x) << 20) +-#define DWC_CFGL_RELOAD_SAR (1 << 30) +-#define DWC_CFGL_RELOAD_DAR (1 << 31) +- +-/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/dw_dmac.h> */ +-#define DWC_CFGH_DS_UPD_EN (1 << 5) +-#define DWC_CFGH_SS_UPD_EN (1 << 6) +- +-/* Bitfields in SGR */ +-#define DWC_SGR_SGI(x) ((x) << 0) +-#define DWC_SGR_SGC(x) ((x) << 20) +- +-/* Bitfields in DSR */ +-#define DWC_DSR_DSI(x) ((x) << 0) +-#define DWC_DSR_DSC(x) ((x) << 20) +- +-/* Bitfields in CFG */ +-#define DW_CFG_DMA_EN (1 << 0) +- +-#define DW_REGLEN 0x400 +- +-enum dw_dmac_flags { +- DW_DMA_IS_CYCLIC = 0, +-}; +- +-struct dw_dma_chan { +- struct dma_chan chan; +- void __iomem *ch_regs; +- u8 mask; +- u8 priority; +- bool paused; +- +- spinlock_t lock; +- +- /* these other elements are all protected by lock */ +- unsigned long flags; +- dma_cookie_t completed; +- struct list_head active_list; +- struct list_head queue; +- struct list_head free_list; +- struct dw_cyclic_desc *cdesc; +- +- unsigned int descs_allocated; +-}; +- +-static inline struct dw_dma_chan_regs __iomem * +-__dwc_regs(struct dw_dma_chan *dwc) +-{ +- return dwc->ch_regs; +-} +- +-#define channel_readl(dwc, name) \ +- readl(&(__dwc_regs(dwc)->name)) +-#define channel_writel(dwc, name, val) \ +- writel((val), &(__dwc_regs(dwc)->name)) +- +-static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) +-{ +- return container_of(chan, struct dw_dma_chan, chan); +-} +- +-struct dw_dma { +- struct dma_device dma; +- void __iomem *regs; +- struct tasklet_struct tasklet; +- struct clk *clk; +- +- u8 all_chan_mask; +- +- struct dw_dma_chan chan[0]; +-}; +- +-static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) +-{ +- return dw->regs; +-} +- +-#define dma_readl(dw, name) \ +- readl(&(__dw_regs(dw)->name)) +-#define dma_writel(dw, name, val) \ +- writel((val), &(__dw_regs(dw)->name)) +- +-#define channel_set_bit(dw, reg, mask) \ +- dma_writel(dw, reg, ((mask) << 8) | (mask)) +-#define channel_clear_bit(dw, reg, mask) \ +- dma_writel(dw, reg, ((mask) << 8) | 0) +- +-static inline struct dw_dma *to_dw_dma(struct dma_device *ddev) +-{ +- return container_of(ddev, struct dw_dma, dma); +-} +- +-/* LLI == Linked List Item; a.k.a. DMA block descriptor */ +-struct dw_lli { +- /* values that are not changed by hardware */ +- dma_addr_t sar; +- dma_addr_t dar; +- dma_addr_t llp; /* chain to next lli */ +- u32 ctllo; +- /* values that may get written back: */ +- u32 ctlhi; +- /* sstat and dstat can snapshot peripheral register state. +- * silicon config may discard either or both... +- */ +- u32 sstat; +- u32 dstat; +-}; +- +-struct dw_desc { +- /* FIRST values the hardware uses */ +- struct dw_lli lli; +- +- /* THEN values for driver housekeeping */ +- struct list_head desc_node; +- struct list_head tx_list; +- struct dma_async_tx_descriptor txd; +- size_t len; +-}; +- +-static inline struct dw_desc * +-txd_to_dw_desc(struct dma_async_tx_descriptor *txd) +-{ +- return container_of(txd, struct dw_desc, txd); +-} +diff --git a/drivers/dma/fh_dmac.c b/drivers/dma/fh_dmac.c +new file mode 100644 +index 00000000..e3f1d5b0 +--- /dev/null ++++ b/drivers/dma/fh_dmac.c +@@ -0,0 +1,1869 @@ ++/* ++ * Core driver for the Synopsys DesignWare DMA Controller ++ * ++ * Copyright (C) 2007-2008 Atmel Corporation ++ * Copyright (C) 2010-2011 ST Microelectronics ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/bitops.h> ++#include <linux/clk.h> ++#include <linux/delay.h> ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <linux/dmapool.h> ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/of.h> ++#include <linux/mm.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/dmaengine.h> ++#include "dmaengine.h" ++#include <mach/fh_dmac_regs.h> ++ ++/* ++ * This supports the Synopsys "DesignWare AHB Central DMA Controller", ++ * (FH_ahb_dmac) which is used with various AMBA 2.0 systems (not all ++ * of which use ARM any more). See the "Databook" from Synopsys for ++ * information beyond what licensees probably provide. ++ * ++ * The driver has currently been tested only with the Atmel AT32AP7000, ++ * which does not support descriptor writeback. ++ */ ++ ++static inline unsigned int fhc_get_dms(struct fh_dma_slave *slave) ++{ ++ return slave ? slave->dst_master : 0; ++} ++ ++static inline unsigned int fhc_get_sms(struct fh_dma_slave *slave) ++{ ++ return slave ? slave->src_master : 1; ++} ++ ++static inline void fhc_set_masters(struct fh_dma_chan *fhc) ++{ ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ struct fh_dma_slave *dms = fhc->chan.private; ++ unsigned char mmax = fhd->nr_masters - 1; ++ ++ if (fhc->request_line == ~0) { ++ fhc->src_master = min_t(unsigned char, mmax, fhc_get_sms(dms)); ++ fhc->dst_master = min_t(unsigned char, mmax, fhc_get_dms(dms)); ++ } ++} ++ ++#define FHC_DEFAULT_CTLLO(_chan) ({ \ ++ struct fh_dma_chan *_fhc = to_fh_dma_chan(_chan); \ ++ struct dma_slave_config *_sconfig = &_fhc->dma_sconfig; \ ++ bool _is_slave = is_slave_direction(_fhc->direction); \ ++ u8 _smsize = _is_slave ? _sconfig->src_maxburst : \ ++ FH_DMA_MSIZE_16; \ ++ u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ ++ FH_DMA_MSIZE_16; \ ++ \ ++ (FHC_CTLL_DST_MSIZE(_dmsize) \ ++ | FHC_CTLL_SRC_MSIZE(_smsize) \ ++ | FHC_CTLL_LLP_D_EN \ ++ | FHC_CTLL_LLP_S_EN \ ++ | FHC_CTLL_DMS(_fhc->dst_master) \ ++ | FHC_CTLL_SMS(_fhc->src_master)); \ ++ }) ++ ++#define FHC_DEFAULT_CTLLO_OLD(private) ({ \ ++ struct fh_dma_slave *__slave = (private); \ ++ int dms = __slave ? __slave->dst_master : 0; \ ++ int sms = __slave ? __slave->src_master : 1; \ ++ u8 smsize = __slave ? __slave->src_msize : FH_DMA_MSIZE_16; \ ++ u8 dmsize = __slave ? __slave->dst_msize : FH_DMA_MSIZE_16; \ ++ \ ++ (FHC_CTLL_DST_MSIZE(dmsize) \ ++ | FHC_CTLL_SRC_MSIZE(smsize) \ ++ | FHC_CTLL_LLP_D_EN \ ++ | FHC_CTLL_LLP_S_EN \ ++ | FHC_CTLL_DMS(dms) \ ++ | FHC_CTLL_SMS(sms)); \ ++ }) ++ ++/* ++ * Number of descriptors to allocate for each channel. This should be ++ * made configurable somehow; preferably, the clients (at least the ++ * ones using slave transfers) should be able to give us a hint. ++ */ ++#define NR_DESCS_PER_CHANNEL 4096 ++ ++/*----------------------------------------------------------------------*/ ++ ++static struct device *chan2dev(struct dma_chan *chan) ++{ ++ return &chan->dev->device; ++} ++static struct device *chan2parent(struct dma_chan *chan) ++{ ++ return chan->dev->device.parent; ++} ++ ++static struct fh_desc *fhc_first_active(struct fh_dma_chan *fhc) ++{ ++ return to_fh_desc(fhc->active_list.next); ++} ++ ++static struct fh_desc *fhc_desc_get(struct fh_dma_chan *fhc) ++{ ++ struct fh_desc *desc, *_desc; ++ struct fh_desc *ret = NULL; ++ unsigned int i = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ list_for_each_entry_safe(desc, _desc, &fhc->free_list, desc_node) { ++ i++; ++ if (async_tx_test_ack(&desc->txd)) { ++ list_del(&desc->desc_node); ++ ret = desc; ++ break; ++ } ++ dev_dbg(chan2dev(&fhc->chan), "desc %p not ACKed\n", desc); ++ } ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ dev_vdbg(chan2dev(&fhc->chan), "scanned %u descriptors on freelist\n", i); ++ ++ return ret; ++} ++ ++/* ++ * Move a descriptor, including any children, to the free list. ++ * `desc' must not be on any lists. ++ */ ++static void fhc_desc_put(struct fh_dma_chan *fhc, struct fh_desc *desc) ++{ ++ unsigned long flags; ++ ++ if (desc) { ++ struct fh_desc *child; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ list_for_each_entry(child, &desc->tx_list, desc_node) ++ dev_vdbg(chan2dev(&fhc->chan), ++ "moving child desc %p to freelist\n", ++ child); ++ list_splice_init(&desc->tx_list, &fhc->free_list); ++ dev_vdbg(chan2dev(&fhc->chan), "moving desc %p to freelist\n", desc); ++ list_add(&desc->desc_node, &fhc->free_list); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ } ++} ++ ++static void fhc_initialize(struct fh_dma_chan *fhc) ++{ ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ struct fh_dma_slave *dms = fhc->chan.private; ++ u32 cfghi = FHC_CFGH_FIFO_MODE; ++ u32 cfglo = FHC_CFGL_CH_PRIOR(fhc->priority); ++ struct fh_dma_extra *ext_para = &fhc->ext_para; ++ ++ if (fhc->initialized == true) ++ return; ++ ++ if (dms) { ++ cfghi = dms->cfg_hi; ++ cfglo |= dms->cfg_lo & ~FHC_CFGL_CH_PRIOR_MASK; ++ } else { ++ if (fhc->direction == DMA_MEM_TO_DEV) { ++ cfghi = FHC_CFGH_DST_PER(fhc->request_line); ++ if (ext_para->protctl_flag == PROTCTL_ENABLE) { ++ cfghi &= ~FHC_PROTCTL_MASK; ++ cfghi |= FHC_PROTCTL(ext_para->protctl_data); ++ } ++ } else if (fhc->direction == DMA_DEV_TO_MEM) { ++ cfghi = FHC_CFGH_SRC_PER(fhc->request_line); ++ if (ext_para->protctl_flag == PROTCTL_ENABLE) { ++ cfghi &= ~FHC_PROTCTL_MASK; ++ cfghi |= FHC_PROTCTL(ext_para->protctl_data); ++ } ++ } else if (fhc->direction == DMA_MEM_TO_MEM) { ++ cfghi &= ~FHC_PROTCTL_MASK; ++ cfghi |= FHC_PROTCTL(2); ++ } ++ } ++ channel_writel(fhc, CFG_LO, cfglo); ++ channel_writel(fhc, CFG_HI, cfghi); ++ ++ /* Enable interrupts */ ++ channel_set_bit(fhd, MASK.XFER, fhc->mask); ++ channel_set_bit(fhd, MASK.BLOCK, fhc->mask); ++ channel_set_bit(fhd, MASK.ERROR, fhc->mask); ++ ++ fhc->initialized = true; ++} ++ ++/*----------------------------------------------------------------------*/ ++ ++static inline unsigned int fhc_fast_fls(unsigned long long v) ++{ ++ /* ++ * We can be a lot more clever here, but this should take care ++ * of the most common optimization. ++ */ ++ if (!(v & 7)) ++ return 3; ++ else if (!(v & 3)) ++ return 2; ++ else if (!(v & 1)) ++ return 1; ++ return 0; ++} ++ ++static inline void fhc_dump_chan_regs(struct fh_dma_chan *fhc) ++{ ++ dev_err(chan2dev(&fhc->chan), ++ " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", ++ channel_readl(fhc, SAR), ++ channel_readl(fhc, DAR), ++ channel_readl(fhc, LLP), ++ channel_readl(fhc, CTL_HI), ++ channel_readl(fhc, CTL_LO)); ++} ++ ++static inline void fhc_chan_disable(struct fh_dma *fhd, struct fh_dma_chan *fhc) ++{ ++ channel_clear_bit(fhd, CH_EN, fhc->mask); ++ while (dma_readl(fhd, CH_EN) & fhc->mask) ++ cpu_relax(); ++} ++ ++/*----------------------------------------------------------------------*/ ++ ++/* Perform single block transfer */ ++static inline void fhc_do_single_block(struct fh_dma_chan *fhc, ++ struct fh_desc *desc) ++{ ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ u32 ctllo; ++ ++ /* Software emulation of LLP mode relies on interrupts to continue ++ * multi block transfer. */ ++ ctllo = desc->lli.ctllo | FHC_CTLL_INT_EN; ++ ++ channel_writel(fhc, SAR, desc->lli.sar); ++ channel_writel(fhc, DAR, desc->lli.dar); ++ channel_writel(fhc, CTL_LO, ctllo); ++ channel_writel(fhc, CTL_HI, desc->lli.ctlhi); ++ channel_set_bit(fhd, CH_EN, fhc->mask); ++ ++ /* Move pointer to next descriptor */ ++ fhc->tx_node_active = fhc->tx_node_active->next; ++} ++ ++/* Called with fhc->lock held and bh disabled */ ++static void fhc_dostart(struct fh_dma_chan *fhc, struct fh_desc *first) ++{ ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ unsigned long was_soft_llp; ++ ++ /* ASSERT: channel is idle */ ++ if (dma_readl(fhd, CH_EN) & fhc->mask) { ++ dev_err(chan2dev(&fhc->chan), ++ "BUG: Attempted to start non-idle channel\n"); ++ fhc_dump_chan_regs(fhc); ++ ++ /* The tasklet will hopefully advance the queue... */ ++ return; ++ } ++ ++ if (fhc->nollp) { ++ was_soft_llp = test_and_set_bit(FH_DMA_IS_SOFT_LLP, ++ &fhc->flags); ++ if (was_soft_llp) { ++ dev_err(chan2dev(&fhc->chan), ++ "BUG: Attempted to start new LLP transfer " ++ "inside ongoing one\n"); ++ return; ++ } ++ ++ fhc_initialize(fhc); ++ ++ fhc->residue = first->total_len; ++ fhc->tx_node_active = &first->tx_list; ++ ++ /* Submit first block */ ++ fhc_do_single_block(fhc, first); ++ ++ return; ++ } ++ ++ fhc_initialize(fhc); ++ ++ channel_writel(fhc, LLP, first->txd.phys); ++ channel_writel(fhc, CTL_LO, ++ FHC_CTLL_LLP_D_EN | FHC_CTLL_LLP_S_EN); ++ channel_writel(fhc, CTL_HI, 0); ++ channel_set_bit(fhd, CH_EN, fhc->mask); ++} ++ ++/*----------------------------------------------------------------------*/ ++ ++static void ++fhc_descriptor_complete(struct fh_dma_chan *fhc, struct fh_desc *desc, ++ bool callback_required) ++{ ++ dma_async_tx_callback callback = NULL; ++ void *param = NULL; ++ struct dma_async_tx_descriptor *txd = &desc->txd; ++ struct fh_desc *child; ++ unsigned long flags; ++ ++ dev_vdbg(chan2dev(&fhc->chan), "descriptor %u complete\n", txd->cookie); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ dma_cookie_complete(txd); ++ if (callback_required) { ++ callback = txd->callback; ++ param = txd->callback_param; ++ } ++ ++ /* async_tx_ack */ ++ list_for_each_entry(child, &desc->tx_list, desc_node) ++ async_tx_ack(&child->txd); ++ async_tx_ack(&desc->txd); ++ ++ list_splice_init(&desc->tx_list, &fhc->free_list); ++ list_move(&desc->desc_node, &fhc->free_list); ++ ++ if (!is_slave_direction(fhc->direction)) { ++ struct device *parent = chan2parent(&fhc->chan); ++ if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { ++ if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE) ++ dma_unmap_single(parent, desc->lli.dar, ++ desc->total_len, DMA_FROM_DEVICE); ++ else ++ dma_unmap_page(parent, desc->lli.dar, ++ desc->total_len, DMA_FROM_DEVICE); ++ } ++ if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) { ++ if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE) ++ dma_unmap_single(parent, desc->lli.sar, ++ desc->total_len, DMA_TO_DEVICE); ++ else ++ dma_unmap_page(parent, desc->lli.sar, ++ desc->total_len, DMA_TO_DEVICE); ++ } ++ } ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ if (callback) ++ callback(param); ++} ++ ++static void fhc_complete_all(struct fh_dma *fhd, struct fh_dma_chan *fhc) ++{ ++ struct fh_desc *desc, *_desc; ++ LIST_HEAD(list); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ if (dma_readl(fhd, CH_EN) & fhc->mask) { ++ dev_err(chan2dev(&fhc->chan), ++ "BUG: XFER bit set, but channel not idle!\n"); ++ ++ /* Try to continue after resetting the channel... */ ++ fhc_chan_disable(fhd, fhc); ++ } ++ ++ /* ++ * Submit queued descriptors ASAP, i.e. before we go through ++ * the completed ones. ++ */ ++ list_splice_init(&fhc->active_list, &list); ++ if (!list_empty(&fhc->queue)) { ++ list_move(fhc->queue.next, &fhc->active_list); ++ fhc_dostart(fhc, fhc_first_active(fhc)); ++ } ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ list_for_each_entry_safe(desc, _desc, &list, desc_node) ++ fhc_descriptor_complete(fhc, desc, true); ++} ++ ++/* Returns how many bytes were already received from source */ ++static inline u32 fhc_get_sent(struct fh_dma_chan *fhc) ++{ ++ u32 ctlhi = channel_readl(fhc, CTL_HI); ++ u32 ctllo = channel_readl(fhc, CTL_LO); ++ ++ return (ctlhi & FHC_CTLH_BLOCK_TS_MASK) * (1 << (ctllo >> 4 & 7)); ++} ++ ++static void fhc_scan_descriptors(struct fh_dma *fhd, struct fh_dma_chan *fhc) ++{ ++ dma_addr_t llp; ++ struct fh_desc *desc, *_desc; ++ struct fh_desc *child; ++ u32 status_xfer; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ /* ++ * Clear block interrupt flag before scanning so that we don't ++ * miss any, and read LLP before RAW_XFER to ensure it is ++ * valid if we decide to scan the list. ++ */ ++ dma_writel(fhd, CLEAR.BLOCK, fhc->mask); ++ llp = channel_readl(fhc, LLP); ++ status_xfer = dma_readl(fhd, RAW.XFER); ++ ++ if (status_xfer & fhc->mask) { ++ /* Everything we've submitted is done */ ++ dma_writel(fhd, CLEAR.XFER, fhc->mask); ++ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags)) { ++ struct list_head *head, *active = fhc->tx_node_active; ++ ++ /* ++ * We are inside first active descriptor. ++ * Otherwise something is really wrong. ++ */ ++ desc = fhc_first_active(fhc); ++ ++ head = &desc->tx_list; ++ if (active != head) { ++ /* Update desc to reflect last sent one */ ++ if (active != head->next) ++ desc = to_fh_desc(active->prev); ++ ++ fhc->residue -= desc->len; ++ ++ child = to_fh_desc(active); ++ ++ /* Submit next block */ ++ fhc_do_single_block(fhc, child); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ ++ /* We are done here */ ++ clear_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags); ++ } ++ fhc->residue = 0; ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ fhc_complete_all(fhd, fhc); ++ return; ++ } ++ ++ if (list_empty(&fhc->active_list)) { ++ fhc->residue = 0; ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ ++ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags)) { ++ dev_vdbg(chan2dev(&fhc->chan), "%s: soft LLP mode\n", __func__); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ ++ dev_vdbg(chan2dev(&fhc->chan), "%s: llp=0x%llx\n", __func__, ++ (unsigned long long)llp); ++ ++ list_for_each_entry_safe(desc, _desc, &fhc->active_list, desc_node) { ++ /* Initial residue value */ ++ fhc->residue = desc->total_len; ++ ++ /* Check first descriptors addr */ ++ if (desc->txd.phys == llp) { ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ ++ /* Check first descriptors llp */ ++ if (desc->lli.llp == llp) { ++ /* This one is currently in progress */ ++ fhc->residue -= fhc_get_sent(fhc); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ ++ fhc->residue -= desc->len; ++ list_for_each_entry(child, &desc->tx_list, desc_node) { ++ if (child->lli.llp == llp) { ++ /* Currently in progress */ ++ fhc->residue -= fhc_get_sent(fhc); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return; ++ } ++ fhc->residue -= child->len; ++ } ++ ++ /* ++ * No descriptors so far seem to be in progress, i.e. ++ * this one must be done. ++ */ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ fhc_descriptor_complete(fhc, desc, true); ++ spin_lock_irqsave(&fhc->lock, flags); ++ } ++ ++ dev_err(chan2dev(&fhc->chan), ++ "BUG: All descriptors done, but channel not idle!\n"); ++ ++ /* Try to continue after resetting the channel... */ ++ fhc_chan_disable(fhd, fhc); ++ ++ if (!list_empty(&fhc->queue)) { ++ list_move(fhc->queue.next, &fhc->active_list); ++ fhc_dostart(fhc, fhc_first_active(fhc)); ++ } ++ spin_unlock_irqrestore(&fhc->lock, flags); ++} ++ ++static inline void fhc_dump_lli(struct fh_dma_chan *fhc, struct fh_lli *lli) ++{ ++ dev_crit(chan2dev(&fhc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", ++ lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo); ++ ++} ++ ++static void fhc_handle_error(struct fh_dma *fhd, struct fh_dma_chan *fhc) ++{ ++ struct fh_desc *bad_desc; ++ struct fh_desc *child; ++ unsigned long flags; ++ ++ fhc_scan_descriptors(fhd, fhc); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ /* ++ * The descriptor currently at the head of the active list is ++ * borked. Since we don't have any way to report errors, we'll ++ * just have to scream loudly and try to carry on. ++ */ ++ bad_desc = fhc_first_active(fhc); ++ list_del_init(&bad_desc->desc_node); ++ list_move(fhc->queue.next, fhc->active_list.prev); ++ ++ /* Clear the error flag and try to restart the controller */ ++ dma_writel(fhd, CLEAR.ERROR, fhc->mask); ++ if (!list_empty(&fhc->active_list)) ++ fhc_dostart(fhc, fhc_first_active(fhc)); ++ ++ /* ++ * WARN may seem harsh, but since this only happens ++ * when someone submits a bad physical address in a ++ * descriptor, we should consider ourselves lucky that the ++ * controller flagged an error instead of scribbling over ++ * random memory locations. ++ */ ++ dev_WARN(chan2dev(&fhc->chan), "Bad descriptor submitted for DMA!\n" ++ " cookie: %d\n", bad_desc->txd.cookie); ++ fhc_dump_lli(fhc, &bad_desc->lli); ++ list_for_each_entry(child, &bad_desc->tx_list, desc_node) ++ fhc_dump_lli(fhc, &child->lli); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ /* Pretend the descriptor completed successfully */ ++ fhc_descriptor_complete(fhc, bad_desc, true); ++} ++ ++/* --------------------- Cyclic DMA API extensions -------------------- */ ++ ++inline dma_addr_t fh_dma_get_src_addr(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ return channel_readl(fhc, SAR); ++} ++EXPORT_SYMBOL(fh_dma_get_src_addr); ++ ++inline dma_addr_t fh_dma_get_dst_addr(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ return channel_readl(fhc, DAR); ++} ++EXPORT_SYMBOL(fh_dma_get_dst_addr); ++ ++/* Called with fhc->lock held and all DMAC interrupts disabled */ ++static void fhc_handle_cyclic(struct fh_dma *fhd, struct fh_dma_chan *fhc, ++ u32 status_err, u32 status_xfer, u32 status_block) ++{ ++ unsigned long flags; ++ ++ if (status_block & fhc->mask) { ++ void (*callback) (void *param); ++ void *callback_param; ++ ++ dev_vdbg(chan2dev(&fhc->chan), "new cyclic period llp 0x%08x\n", ++ channel_readl(fhc, LLP)); ++ dma_writel(fhd, CLEAR.BLOCK, fhc->mask); ++ ++ callback = fhc->cdesc->period_callback; ++ callback_param = fhc->cdesc->period_callback_param; ++ ++ if (callback) ++ callback(callback_param); ++ } ++ ++ /* ++ * Error and transfer complete are highly unlikely, and will most ++ * likely be due to a configuration error by the user. ++ */ ++ if (unlikely(status_err & fhc->mask) || ++ unlikely(status_xfer & fhc->mask)) { ++ int i; ++ ++ dev_err(chan2dev(&fhc->chan), "cyclic DMA unexpected %s " ++ "interrupt, stopping DMA transfer\n", ++ status_xfer ? "xfer" : "error"); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ fhc_dump_chan_regs(fhc); ++ ++ fhc_chan_disable(fhd, fhc); ++ ++ /* Make sure DMA does not restart by loading a new list */ ++ channel_writel(fhc, LLP, 0); ++ channel_writel(fhc, CTL_LO, 0); ++ channel_writel(fhc, CTL_HI, 0); ++ ++ dma_writel(fhd, CLEAR.ERROR, fhc->mask); ++ dma_writel(fhd, CLEAR.XFER, fhc->mask); ++ dma_writel(fhd, CLEAR.BLOCK, fhc->mask); ++ ++ for (i = 0; i < fhc->cdesc->periods; i++) ++ fhc_dump_lli(fhc, &fhc->cdesc->desc[i]->lli); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ } ++} ++ ++/* ------------------------------------------------------------------------- */ ++ ++static void fh_dma_tasklet(unsigned long data) ++{ ++ struct fh_dma *fhd = (struct fh_dma *)data; ++ struct fh_dma_chan *fhc; ++ u32 status_xfer; ++ u32 status_err; ++ u32 status_block; ++ int i; ++ ++ status_xfer = dma_readl(fhd, RAW.XFER); ++ status_block = dma_readl(fhd, RAW.BLOCK); ++ status_err = dma_readl(fhd, RAW.ERROR); ++ ++ dev_vdbg(fhd->dma.dev, "%s: status_err=%x\n", __func__, status_err); ++ ++ for (i = 0; i < fhd->dma.chancnt; i++) { ++ fhc = &fhd->chan[i]; ++ if (test_bit(FH_DMA_IS_CYCLIC, &fhc->flags)) ++ fhc_handle_cyclic(fhd, fhc, status_err, ++ status_xfer, status_block); ++ else if (status_err & (1 << i)) ++ fhc_handle_error(fhd, fhc); ++ else if (status_xfer & (1 << i)) ++ fhc_scan_descriptors(fhd, fhc); ++ } ++ ++ /* ++ * Re-enable interrupts. ++ */ ++ channel_set_bit(fhd, MASK.XFER, fhd->all_chan_mask); ++ channel_set_bit(fhd, MASK.BLOCK, fhd->all_chan_mask); ++ channel_set_bit(fhd, MASK.ERROR, fhd->all_chan_mask); ++} ++ ++static irqreturn_t fh_dma_interrupt(int irq, void *dev_id) ++{ ++ struct fh_dma *fhd = dev_id; ++ u32 status; ++ ++ dev_vdbg(fhd->dma.dev, "%s: status=0x%x\n", __func__, ++ dma_readl(fhd, STATUS_INT)); ++ ++ /* ++ * Just disable the interrupts. We'll turn them back on in the ++ * softirq handler. ++ */ ++ channel_clear_bit(fhd, MASK.XFER, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.ERROR, fhd->all_chan_mask); ++ ++ status = dma_readl(fhd, STATUS_INT); ++ if (status) { ++ dev_err(fhd->dma.dev, ++ "BUG: Unexpected interrupts pending: 0x%x\n", ++ status); ++ ++ /* Try to recover */ ++ channel_clear_bit(fhd, MASK.XFER, (1 << 8) - 1); ++ channel_clear_bit(fhd, MASK.BLOCK, (1 << 8) - 1); ++ channel_clear_bit(fhd, MASK.SRC_TRAN, (1 << 8) - 1); ++ channel_clear_bit(fhd, MASK.DST_TRAN, (1 << 8) - 1); ++ channel_clear_bit(fhd, MASK.ERROR, (1 << 8) - 1); ++ } ++ ++ tasklet_schedule(&fhd->tasklet); ++ ++ return IRQ_HANDLED; ++} ++ ++/*----------------------------------------------------------------------*/ ++ ++static dma_cookie_t fhc_tx_submit(struct dma_async_tx_descriptor *tx) ++{ ++ struct fh_desc *desc = txd_to_fh_desc(tx); ++ struct fh_dma_chan *fhc = to_fh_dma_chan(tx->chan); ++ dma_cookie_t cookie; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ cookie = dma_cookie_assign(tx); ++ ++ /* ++ * REVISIT: We should attempt to chain as many descriptors as ++ * possible, perhaps even appending to those already submitted ++ * for DMA. But this is hard to do in a race-free manner. ++ */ ++ if (list_empty(&fhc->active_list)) { ++ dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__, ++ desc->txd.cookie); ++ list_add_tail(&desc->desc_node, &fhc->active_list); ++ fhc_dostart(fhc, fhc_first_active(fhc)); ++ } else { ++ dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, ++ desc->txd.cookie); ++ ++ list_add_tail(&desc->desc_node, &fhc->queue); ++ } ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ return cookie; ++} ++ ++static struct dma_async_tx_descriptor * ++fhc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(chan->device); ++ struct fh_desc *desc; ++ struct fh_desc *first; ++ struct fh_desc *prev; ++ size_t xfer_count; ++ size_t offset; ++ unsigned int src_width; ++ unsigned int dst_width; ++ unsigned int data_width; ++ u32 ctllo; ++ ++ dev_vdbg(chan2dev(chan), ++ "%s: d0x%llx s0x%llx l0x%zx f0x%lx\n", __func__, ++ (unsigned long long)dest, (unsigned long long)src, ++ len, flags); ++ ++ if (unlikely(!len)) { ++ dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__); ++ return NULL; ++ } ++ ++ fhc->direction = DMA_MEM_TO_MEM; ++ ++ data_width = min_t(unsigned int, fhd->data_width[fhc->src_master], ++ fhd->data_width[fhc->dst_master]); ++ ++ src_width = dst_width = min_t(unsigned int, data_width, ++ fhc_fast_fls(src | dest | len)); ++ ++ ctllo = FHC_DEFAULT_CTLLO(chan) ++ | FHC_CTLL_DST_WIDTH(dst_width) ++ | FHC_CTLL_SRC_WIDTH(src_width) ++ | FHC_CTLL_DST_INC ++ | FHC_CTLL_SRC_INC ++ | FHC_CTLL_FC_M2M; ++ prev = first = NULL; ++ ++ for (offset = 0; offset < len; offset += xfer_count << src_width) { ++ xfer_count = min_t(size_t, (len - offset) >> src_width, ++ fhc->block_size); ++ ++ desc = fhc_desc_get(fhc); ++ if (!desc) ++ goto err_desc_get; ++ ++ desc->lli.sar = src + offset; ++ desc->lli.dar = dest + offset; ++ desc->lli.ctllo = ctllo; ++ desc->lli.ctlhi = xfer_count; ++ desc->len = xfer_count << src_width; ++ ++ if (!first) { ++ first = desc; ++ } else { ++ prev->lli.llp = desc->txd.phys; ++ list_add_tail(&desc->desc_node, ++ &first->tx_list); ++ } ++ prev = desc; ++ } ++ ++ if (flags & DMA_PREP_INTERRUPT) ++ /* Trigger interrupt after last block */ ++ prev->lli.ctllo |= FHC_CTLL_INT_EN; ++ ++ prev->lli.llp = 0; ++ first->txd.flags = flags; ++ first->total_len = len; ++ ++ return &first->txd; ++ ++err_desc_get: ++ fhc_desc_put(fhc, first); ++ return NULL; ++} ++ ++static struct dma_async_tx_descriptor * ++fhc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ /*struct fh_dma *fhd = to_fh_dma(chan->device);*/ ++ struct dma_slave_config *sconfig = &fhc->dma_sconfig; ++ struct fh_desc *prev; ++ struct fh_desc *first; ++ u32 ctllo; ++ dma_addr_t reg; ++ unsigned int reg_width; ++ unsigned int mem_width; ++ unsigned int data_width; ++ unsigned int i; ++ struct scatterlist *sg; ++ size_t total_len = 0; ++ struct fh_dma_extra *ext_para = (struct fh_dma_extra *)context; ++ dev_vdbg(chan2dev(chan), "%s\n", __func__); ++ ++ if (unlikely(!is_slave_direction(direction) || !sg_len)) ++ return NULL; ++ ++ fhc->direction = direction; ++ ++ prev = first = NULL; ++ if (ext_para) ++ memcpy(&fhc->ext_para, ext_para, sizeof(struct fh_dma_extra)); ++ ++ switch (direction) { ++ case DMA_MEM_TO_DEV: ++ reg_width = __fls(sconfig->dst_addr_width); ++ reg = sconfig->dst_addr; ++ if(!ext_para){ ++ ctllo = (FHC_DEFAULT_CTLLO(chan) ++ | FHC_CTLL_DST_WIDTH(reg_width) ++ | FHC_CTLL_DST_FIX ++ | FHC_CTLL_SRC_INC); ++ } ++ else{ ++ ctllo = (FHC_DEFAULT_CTLLO(chan) | FHC_CTLL_DST_WIDTH(reg_width)); ++ ctllo |= ext_para->sinc << 9; ++ ctllo |= ext_para->dinc << 7; ++ ctllo &= ~(FHC_CTLL_SMS(3)); ++ ctllo &= ~(FHC_CTLL_DMS(3)); ++ ctllo |= FHC_CTLL_SMS(ext_para->src_master); ++ ctllo |= FHC_CTLL_DMS(ext_para->dst_master); ++ } ++ ++ ctllo |= sconfig->device_fc ? FHC_CTLL_FC(FH_DMA_FC_P_M2P) : ++ FHC_CTLL_FC(FH_DMA_FC_D_M2P); ++ ++ /*data_width = fhd->data_width[fhc->src_master];*/ ++ data_width = __fls(sconfig->src_addr_width); ++ for_each_sg(sgl, sg, sg_len, i) { ++ struct fh_desc *desc; ++ u32 len, dlen, mem; ++ ++ mem = sg_dma_address(sg); ++ len = sg_dma_len(sg); ++ ++ mem_width = min_t(unsigned int, ++ data_width, fhc_fast_fls(mem | len)); ++ ++slave_sg_todev_fill_desc: ++ desc = fhc_desc_get(fhc); ++ if (!desc) { ++ dev_err(chan2dev(chan), ++ "not enough descriptors available\n"); ++ goto err_desc_get; ++ } ++ ++ desc->lli.sar = mem; ++ desc->lli.dar = reg; ++ desc->lli.ctllo = ctllo | FHC_CTLL_SRC_WIDTH(mem_width); ++ if ((len >> mem_width) > fhc->block_size) { ++ dlen = fhc->block_size << mem_width; ++ mem += dlen; ++ len -= dlen; ++ } else { ++ dlen = len; ++ len = 0; ++ } ++ ++ desc->lli.ctlhi = dlen >> mem_width; ++ desc->len = dlen; ++ ++ if (!first) { ++ first = desc; ++ } else { ++ prev->lli.llp = desc->txd.phys; ++ list_add_tail(&desc->desc_node, ++ &first->tx_list); ++ } ++ prev = desc; ++ total_len += dlen; ++ ++ if (len) ++ goto slave_sg_todev_fill_desc; ++ } ++ break; ++ case DMA_DEV_TO_MEM: ++ reg_width = __fls(sconfig->src_addr_width); ++ reg = sconfig->src_addr; ++ ++ if(!ext_para){ ++ ctllo = (FHC_DEFAULT_CTLLO(chan) ++ | FHC_CTLL_SRC_WIDTH(reg_width) ++ | FHC_CTLL_DST_INC ++ | FHC_CTLL_SRC_FIX); ++ } ++ else{ ++ ctllo = (FHC_DEFAULT_CTLLO(chan) | FHC_CTLL_SRC_WIDTH(reg_width)); ++ ctllo |= ext_para->sinc << 9; ++ ctllo |= ext_para->dinc << 7; ++ ctllo &= ~(FHC_CTLL_SMS(3)); ++ ctllo &= ~(FHC_CTLL_DMS(3)); ++ ctllo |= FHC_CTLL_SMS(ext_para->src_master); ++ ctllo |= FHC_CTLL_DMS(ext_para->dst_master); ++ } ++ ++ ++ ctllo |= sconfig->device_fc ? FHC_CTLL_FC(FH_DMA_FC_P_P2M) : ++ FHC_CTLL_FC(FH_DMA_FC_D_P2M); ++ ++ /*data_width = fhd->data_width[fhc->dst_master];*/ ++ data_width = __fls(sconfig->dst_addr_width); ++ for_each_sg(sgl, sg, sg_len, i) { ++ struct fh_desc *desc; ++ u32 len, dlen, mem; ++ ++ mem = sg_dma_address(sg); ++ len = sg_dma_len(sg); ++ ++ mem_width = min_t(unsigned int, ++ data_width, fhc_fast_fls(mem | len)); ++ ++slave_sg_fromdev_fill_desc: ++ desc = fhc_desc_get(fhc); ++ if (!desc) { ++ dev_err(chan2dev(chan), ++ "not enough descriptors available\n"); ++ goto err_desc_get; ++ } ++ ++ desc->lli.sar = reg; ++ desc->lli.dar = mem; ++ desc->lli.ctllo = ctllo | FHC_CTLL_DST_WIDTH(mem_width); ++ if ((len >> reg_width) > fhc->block_size) { ++ dlen = fhc->block_size << reg_width; ++ mem += dlen; ++ len -= dlen; ++ } else { ++ dlen = len; ++ len = 0; ++ } ++ desc->lli.ctlhi = dlen >> reg_width; ++ desc->len = dlen; ++ ++ if (!first) { ++ first = desc; ++ } else { ++ prev->lli.llp = desc->txd.phys; ++ list_add_tail(&desc->desc_node, ++ &first->tx_list); ++ } ++ prev = desc; ++ total_len += dlen; ++ ++ if (len) ++ goto slave_sg_fromdev_fill_desc; ++ } ++ break; ++ default: ++ return NULL; ++ } ++ ++ if (flags & DMA_PREP_INTERRUPT) ++ /* Trigger interrupt after last block */ ++ prev->lli.ctllo |= FHC_CTLL_INT_EN; ++ ++ prev->lli.llp = 0; ++ first->total_len = total_len; ++ ++ return &first->txd; ++ ++err_desc_get: ++ fhc_desc_put(fhc, first); ++ return NULL; ++} ++ ++/* ++ * Fix sconfig's burst size according to fh_dmac. We need to convert them as: ++ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. ++ * ++ * NOTE: burst size 2 is not supported by controller. ++ * ++ * This can be done by finding least significant bit set: n & (n - 1) ++ */ ++static inline void convert_burst(u32 *maxburst) ++{ ++ if (*maxburst > 1) ++ *maxburst = fls(*maxburst) - 2; ++ else ++ *maxburst = 0; ++} ++ ++static int ++set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ ++ /* Check if chan will be configured for slave transfers */ ++ if (!is_slave_direction(sconfig->direction)) ++ return -EINVAL; ++ ++ memcpy(&fhc->dma_sconfig, sconfig, sizeof(*sconfig)); ++ fhc->direction = sconfig->direction; ++ ++ /* Take the request line from slave_id member */ ++ if (fhc->request_line == ~0) ++ fhc->request_line = sconfig->slave_id; ++ ++ convert_burst(&fhc->dma_sconfig.src_maxburst); ++ convert_burst(&fhc->dma_sconfig.dst_maxburst); ++ ++ return 0; ++} ++ ++static inline void fhc_chan_pause(struct fh_dma_chan *fhc) ++{ ++ u32 cfglo = channel_readl(fhc, CFG_LO); ++ unsigned int count = 20; /* timeout iterations */ ++ ++ channel_writel(fhc, CFG_LO, cfglo | FHC_CFGL_CH_SUSP); ++ while (!(channel_readl(fhc, CFG_LO) & FHC_CFGL_FIFO_EMPTY) && count--) ++ udelay(2); ++ ++ fhc->paused = true; ++} ++ ++static inline void fhc_chan_resume(struct fh_dma_chan *fhc) ++{ ++ u32 cfglo = channel_readl(fhc, CFG_LO); ++ ++ channel_writel(fhc, CFG_LO, cfglo & ~FHC_CFGL_CH_SUSP); ++ ++ fhc->paused = false; ++} ++ ++static int fhc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ++ unsigned long arg) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(chan->device); ++ struct fh_desc *desc, *_desc; ++ unsigned long flags; ++ LIST_HEAD(list); ++ ++ if (cmd == DMA_PAUSE) { ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ fhc_chan_pause(fhc); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ } else if (cmd == DMA_RESUME) { ++ if (!fhc->paused) ++ return 0; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ fhc_chan_resume(fhc); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ } else if (cmd == DMA_TERMINATE_ALL) { ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ clear_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags); ++ ++ fhc_chan_disable(fhd, fhc); ++ ++ fhc_chan_resume(fhc); ++ ++ /* active_list entries will end up before queued entries */ ++ list_splice_init(&fhc->queue, &list); ++ list_splice_init(&fhc->active_list, &list); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ /* Flush all pending and queued descriptors */ ++ list_for_each_entry_safe(desc, _desc, &list, desc_node) ++ fhc_descriptor_complete(fhc, desc, false); ++ } else if (cmd == DMA_SLAVE_CONFIG) { ++ return set_runtime_config(chan, (struct dma_slave_config *)arg); ++ } else { ++ return -ENXIO; ++ } ++ ++ return 0; ++} ++ ++static inline u32 fhc_get_residue(struct fh_dma_chan *fhc) ++{ ++ unsigned long flags; ++ u32 residue; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ residue = fhc->residue; ++ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags) && residue) ++ residue -= fhc_get_sent(fhc); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return residue; ++} ++ ++static enum dma_status ++fhc_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ enum dma_status ret; ++ ++ ret = dma_cookie_status(chan, cookie, txstate); ++ if (ret != DMA_SUCCESS) { ++ fhc_scan_descriptors(to_fh_dma(chan->device), fhc); ++ ++ ret = dma_cookie_status(chan, cookie, txstate); ++ } ++ ++ if (ret != DMA_SUCCESS) ++ dma_set_residue(txstate, fhc_get_residue(fhc)); ++ ++ if (fhc->paused) ++ return DMA_PAUSED; ++ ++ return ret; ++} ++ ++static void fhc_issue_pending(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ ++ if (!list_empty(&fhc->queue)) ++ fhc_scan_descriptors(to_fh_dma(chan->device), fhc); ++} ++ ++static int fhc_alloc_chan_resources(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(chan->device); ++ struct fh_desc *desc; ++ int i; ++ unsigned long flags; ++ ++ dev_vdbg(chan2dev(chan), "%s\n", __func__); ++ ++ /* ASSERT: channel is idle */ ++ if (dma_readl(fhd, CH_EN) & fhc->mask) { ++ dev_dbg(chan2dev(chan), "DMA channel not idle?\n"); ++ return -EIO; ++ } ++ ++ dma_cookie_init(chan); ++ ++ /* ++ * NOTE: some controllers may have additional features that we ++ * need to initialize here, like "scatter-gather" (which ++ * doesn't mean what you think it means), and status writeback. ++ */ ++ ++ fhc_set_masters(fhc); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ i = fhc->descs_allocated; ++ while (fhc->descs_allocated < NR_DESCS_PER_CHANNEL) { ++ dma_addr_t phys; ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ desc = dma_pool_alloc(fhd->desc_pool, GFP_ATOMIC, &phys); ++ if (!desc) ++ goto err_desc_alloc; ++ ++ memset(desc, 0, sizeof(struct fh_desc)); ++ ++ INIT_LIST_HEAD(&desc->tx_list); ++ dma_async_tx_descriptor_init(&desc->txd, chan); ++ desc->txd.tx_submit = fhc_tx_submit; ++ desc->txd.flags = DMA_CTRL_ACK; ++ desc->txd.phys = phys; ++ ++ fhc_desc_put(fhc, desc); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ i = ++fhc->descs_allocated; ++ } ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); ++ ++ return i; ++ ++err_desc_alloc: ++ dev_info(chan2dev(chan), "only allocated %d descriptors\n", i); ++ ++ return i; ++} ++ ++static void fhc_free_chan_resources(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(chan->device); ++ struct fh_desc *desc, *_desc; ++ unsigned long flags; ++ LIST_HEAD(list); ++ ++ dev_dbg(chan2dev(chan), "%s: descs allocated=%u\n", __func__, ++ fhc->descs_allocated); ++ ++ /* ASSERT: channel is idle */ ++ BUG_ON(!list_empty(&fhc->active_list)); ++ BUG_ON(!list_empty(&fhc->queue)); ++ BUG_ON(dma_readl(to_fh_dma(chan->device), CH_EN) & fhc->mask); ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ list_splice_init(&fhc->free_list, &list); ++ fhc->descs_allocated = 0; ++ fhc->initialized = false; ++ fhc->request_line = ~0; ++ ++ /* Disable interrupts */ ++ channel_clear_bit(fhd, MASK.XFER, fhc->mask); ++ channel_clear_bit(fhd, MASK.BLOCK, fhc->mask); ++ channel_clear_bit(fhd, MASK.ERROR, fhc->mask); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ list_for_each_entry_safe(desc, _desc, &list, desc_node) { ++ dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); ++ dma_pool_free(fhd->desc_pool, desc, desc->txd.phys); ++ } ++ ++ dev_vdbg(chan2dev(chan), "%s: done\n", __func__); ++} ++ ++ ++/* --------------------- Cyclic DMA API extensions -------------------- */ ++ ++/** ++ * fh_dma_cyclic_start - start the cyclic DMA transfer ++ * @chan: the DMA channel to start ++ * ++ * Must be called with soft interrupts disabled. Returns zero on success or ++ * -errno on failure. ++ */ ++int fh_dma_cyclic_start(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ unsigned long flags; ++ ++ if (!test_bit(FH_DMA_IS_CYCLIC, &fhc->flags)) { ++ dev_err(chan2dev(&fhc->chan), "missing prep for cyclic DMA\n"); ++ return -ENODEV; ++ } ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ /* Assert channel is idle */ ++ if (dma_readl(fhd, CH_EN) & fhc->mask) { ++ dev_err(chan2dev(&fhc->chan), ++ "BUG: Attempted to start non-idle channel\n"); ++ fhc_dump_chan_regs(fhc); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ return -EBUSY; ++ } ++ ++ dma_writel(fhd, CLEAR.ERROR, fhc->mask); ++ dma_writel(fhd, CLEAR.XFER, fhc->mask); ++ dma_writel(fhd, CLEAR.BLOCK, fhc->mask); ++ ++ fhc_initialize(fhc); ++ ++ /* Setup DMAC channel registers */ ++ channel_writel(fhc, LLP, fhc->cdesc->desc[0]->txd.phys); ++ channel_writel(fhc, CTL_LO, FHC_CTLL_LLP_D_EN | FHC_CTLL_LLP_S_EN); ++ channel_writel(fhc, CTL_HI, 0); ++ ++ channel_set_bit(fhd, CH_EN, fhc->mask); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL(fh_dma_cyclic_start); ++ ++/** ++ * fh_dma_cyclic_stop - stop the cyclic DMA transfer ++ * @chan: the DMA channel to stop ++ * ++ * Must be called with soft interrupts disabled. ++ */ ++void fh_dma_cyclic_stop(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ fhc_chan_disable(fhd, fhc); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++} ++EXPORT_SYMBOL(fh_dma_cyclic_stop); ++ ++/** ++ * fh_dma_cyclic_prep - prepare the cyclic DMA transfer ++ * @chan: the DMA channel to prepare ++ * @buf_addr: physical DMA address where the buffer starts ++ * @buf_len: total number of bytes for the entire buffer ++ * @period_len: number of bytes for each period ++ * @direction: transfer direction, to or from device ++ * ++ * Must be called before trying to start the transfer. Returns a valid struct ++ * fh_cyclic_desc if successful or an ERR_PTR(-errno) if not successful. ++ */ ++struct fh_cyclic_desc *fh_dma_cyclic_prep(struct dma_chan *chan, ++ dma_addr_t buf_addr, size_t buf_len, size_t period_len, ++ enum dma_transfer_direction direction) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma_slave *fhs = chan->private; ++ struct fh_cyclic_desc *cdesc; ++ struct fh_cyclic_desc *retval = NULL; ++ struct fh_desc *desc; ++ struct fh_desc *last = NULL; ++ unsigned long was_cyclic; ++ unsigned int reg_width; ++ unsigned int periods; ++ unsigned int i; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ if (fhc->nollp) { ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ dev_dbg(chan2dev(&fhc->chan), ++ "channel doesn't support LLP transfers\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (!list_empty(&fhc->queue) || !list_empty(&fhc->active_list)) { ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ dev_dbg(chan2dev(&fhc->chan), ++ "queue and/or active list are not empty\n"); ++ return ERR_PTR(-EBUSY); ++ } ++ ++ was_cyclic = test_and_set_bit(FH_DMA_IS_CYCLIC, &fhc->flags); ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ if (was_cyclic) { ++ dev_dbg(chan2dev(&fhc->chan), ++ "channel already prepared for cyclic DMA\n"); ++ return ERR_PTR(-EBUSY); ++ } ++ ++ retval = ERR_PTR(-EINVAL); ++ ++ reg_width = fhs->reg_width; ++ ++ if (unlikely(!is_slave_direction(direction))) ++ goto out_err; ++ ++ fhc->direction = direction; ++ ++ periods = buf_len / period_len; ++ ++ /* Check for too big/unaligned periods and unaligned DMA buffer. */ ++ if (period_len > (fhc->block_size << reg_width)) ++ goto out_err; ++ if (unlikely(period_len & ((1 << reg_width) - 1))) ++ goto out_err; ++ if (unlikely(buf_addr & ((1 << reg_width) - 1))) ++ goto out_err; ++ ++ retval = ERR_PTR(-ENOMEM); ++ ++ if (periods > NR_DESCS_PER_CHANNEL) ++ goto out_err; ++ ++ cdesc = kzalloc(sizeof(struct fh_cyclic_desc), GFP_KERNEL); ++ if (!cdesc) ++ goto out_err; ++ ++ cdesc->desc = kzalloc(sizeof(struct fh_desc *) * periods, GFP_KERNEL); ++ if (!cdesc->desc) ++ goto out_err_alloc; ++ ++ for (i = 0; i < periods; i++) { ++ desc = fhc_desc_get(fhc); ++ if (!desc) ++ goto out_err_desc_get; ++ ++ switch (direction) { ++ case DMA_MEM_TO_DEV: ++ desc->lli.dar = fhs->tx_reg; ++ desc->lli.sar = buf_addr + (period_len * i); ++ desc->lli.ctllo = (FHC_DEFAULT_CTLLO_OLD(chan->private) ++ | FHC_CTLL_DST_WIDTH(reg_width) ++ | FHC_CTLL_SRC_WIDTH(reg_width) ++ | FHC_CTLL_DST_FIX ++ | FHC_CTLL_SRC_INC ++ | FHC_CTLL_FC(fhs->fc) ++ | FHC_CTLL_INT_EN); ++ ++ break; ++ case DMA_DEV_TO_MEM: ++ desc->lli.dar = buf_addr + (period_len * i); ++ desc->lli.sar = fhs->rx_reg; ++ desc->lli.ctllo = (FHC_DEFAULT_CTLLO_OLD(chan->private) ++ | FHC_CTLL_SRC_WIDTH(reg_width) ++ | FHC_CTLL_DST_WIDTH(reg_width) ++ | FHC_CTLL_DST_INC ++ | FHC_CTLL_SRC_FIX ++ | FHC_CTLL_FC(fhs->fc) ++ | FHC_CTLL_INT_EN); ++ ++ ++ break; ++ default: ++ break; ++ } ++ ++ desc->lli.ctlhi = (period_len >> reg_width); ++ cdesc->desc[i] = desc; ++ ++ if (last) ++ { ++ last->lli.llp = desc->txd.phys; ++ dma_sync_single_for_device(chan2parent(chan), ++ last->txd.phys, ++ sizeof(last->lli), ++ DMA_TO_DEVICE); ++ } ++ ++ last = desc; ++ } ++ ++ /* Let's make a cyclic list */ ++ last->lli.llp = cdesc->desc[0]->txd.phys; ++ dma_sync_single_for_device(chan2parent(chan), last->txd.phys, ++ sizeof(last->lli), DMA_TO_DEVICE); ++ ++ dev_dbg(chan2dev(&fhc->chan), "cyclic prepared buf 0x%llx len %zu " ++ "period %zu periods %d\n", (unsigned long long)buf_addr, ++ buf_len, period_len, periods); ++ ++ cdesc->periods = periods; ++ fhc->cdesc = cdesc; ++ ++ return cdesc; ++ ++out_err_desc_get: ++ while (i--) ++ fhc_desc_put(fhc, cdesc->desc[i]); ++out_err_alloc: ++ kfree(cdesc); ++out_err: ++ clear_bit(FH_DMA_IS_CYCLIC, &fhc->flags); ++ return (struct fh_cyclic_desc *)retval; ++} ++EXPORT_SYMBOL(fh_dma_cyclic_prep); ++ ++/** ++ * fh_dma_cyclic_free - free a prepared cyclic DMA transfer ++ * @chan: the DMA channel to free ++ */ ++void fh_dma_cyclic_free(struct dma_chan *chan) ++{ ++ struct fh_dma_chan *fhc = to_fh_dma_chan(chan); ++ struct fh_dma *fhd = to_fh_dma(fhc->chan.device); ++ struct fh_cyclic_desc *cdesc = fhc->cdesc; ++ int i; ++ unsigned long flags; ++ ++ dev_dbg(chan2dev(&fhc->chan), "%s\n", __func__); ++ ++ if (!cdesc) ++ return; ++ ++ spin_lock_irqsave(&fhc->lock, flags); ++ ++ fhc_chan_disable(fhd, fhc); ++ ++ dma_writel(fhd, CLEAR.ERROR, fhc->mask); ++ dma_writel(fhd, CLEAR.XFER, fhc->mask); ++ dma_writel(fhd, CLEAR.BLOCK, fhc->mask); ++ ++ spin_unlock_irqrestore(&fhc->lock, flags); ++ ++ for (i = 0; i < cdesc->periods; i++) ++ fhc_desc_put(fhc, cdesc->desc[i]); ++ ++ kfree(cdesc->desc); ++ kfree(cdesc); ++ ++ clear_bit(FH_DMA_IS_CYCLIC, &fhc->flags); ++} ++EXPORT_SYMBOL(fh_dma_cyclic_free); ++ ++/*----------------------------------------------------------------------*/ ++ ++static void fh_dma_off(struct fh_dma *fhd) ++{ ++ int i; ++ ++ dma_writel(fhd, CFG, 0); ++ ++ channel_clear_bit(fhd, MASK.XFER, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.SRC_TRAN, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.DST_TRAN, fhd->all_chan_mask); ++ channel_clear_bit(fhd, MASK.ERROR, fhd->all_chan_mask); ++ ++ while (dma_readl(fhd, CFG) & FH_CFG_DMA_EN) ++ cpu_relax(); ++ ++ for (i = 0; i < fhd->dma.chancnt; i++) ++ fhd->chan[i].initialized = false; ++} ++ ++static int fh_dma_probe(struct platform_device *pdev) ++{ ++ struct fh_dma_platform_data *pdata; ++ struct resource *io; ++ struct fh_dma *fhd; ++ size_t size; ++ void __iomem *regs; ++ bool autocfg; ++ unsigned int fh_params; ++ unsigned int nr_channels; ++ unsigned int max_blk_size = 0; ++ int irq; ++ int err; ++ int i; ++ ++ io = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!io) ++ return -EINVAL; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ if (!request_mem_region(io->start, FH_REGLEN, pdev->dev.driver->name)) ++ return -EBUSY; ++ ++ regs = ioremap(io->start, FH_REGLEN); ++ if (!regs) { ++ err = -ENOMEM; ++ goto err_release_r; ++ } ++ ++ /* Apply default dma_mask if needed */ ++ if (!pdev->dev.dma_mask) { ++ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; ++ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ } ++ ++ fh_params = dma_read_byaddr(regs, FH_PARAMS); ++ autocfg = fh_params >> FH_PARAMS_EN & 0x1; ++ ++ dev_dbg(&pdev->dev, "FH_PARAMS: 0x%08x\n", fh_params); ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ ++ if (!pdata && autocfg) { ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ ++ /* Fill platform data with the default values */ ++ pdata->is_private = true; ++ pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; ++ pdata->chan_priority = CHAN_PRIORITY_ASCENDING; ++ } else if (!pdata || pdata->nr_channels > FH_DMA_MAX_NR_CHANNELS) ++ return -EINVAL; ++ ++ if (autocfg) ++ nr_channels = (fh_params >> FH_PARAMS_NR_CHAN & 0x7) + 1; ++ else ++ nr_channels = pdata->nr_channels; ++ ++ size = sizeof(struct fh_dma) + nr_channels * sizeof(struct fh_dma_chan); ++ fhd = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); ++ if (!fhd) ++ return -ENOMEM; ++ ++ fhd->clk = clk_get(&pdev->dev, "dmac0_hclk_gate"); ++ if (IS_ERR(fhd->clk)) ++ printk(KERN_INFO "cannot get dmac0_hclk\n"); ++ else ++ clk_enable(fhd->clk); ++ ++ fhd->regs = regs; ++ ++ /* Get hardware configuration parameters */ ++ if (autocfg) { ++ max_blk_size = dma_readl(fhd, MAX_BLK_SIZE); ++ ++ fhd->nr_masters = (fh_params >> FH_PARAMS_NR_MASTER & 3) + 1; ++ for (i = 0; i < fhd->nr_masters; i++) { ++ fhd->data_width[i] = ++ (fh_params >> FH_PARAMS_DATA_WIDTH(i) & 3) + 2; ++ } ++ } else { ++ fhd->nr_masters = pdata->nr_masters; ++ memcpy(fhd->data_width, pdata->data_width, 4); ++ } ++ ++ /* Calculate all channel mask before DMA setup */ ++ fhd->all_chan_mask = (1 << nr_channels) - 1; ++ ++ /* Force dma off, just in case */ ++ fh_dma_off(fhd); ++ ++ /* Disable BLOCK interrupts as well */ ++ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask); ++ ++ err = devm_request_irq(&pdev->dev, irq, fh_dma_interrupt, 0, ++ dev_name(&pdev->dev), fhd); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, fhd); ++ ++ /* Create a pool of consistent memory blocks for hardware descriptors */ ++ fhd->desc_pool = dmam_pool_create("fh_dmac_desc_pool", &pdev->dev, ++ sizeof(struct fh_desc), 4, 0); ++ if (!fhd->desc_pool) { ++ dev_err(&pdev->dev, "No memory for descriptors dma pool\n"); ++ return -ENOMEM; ++ } ++ ++ tasklet_init(&fhd->tasklet, fh_dma_tasklet, (unsigned long)fhd); ++ ++ INIT_LIST_HEAD(&fhd->dma.channels); ++ for (i = 0; i < nr_channels; i++) { ++ struct fh_dma_chan *fhc = &fhd->chan[i]; ++ int r = nr_channels - i - 1; ++ ++ fhc->chan.device = &fhd->dma; ++ dma_cookie_init(&fhc->chan); ++ if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING) ++ list_add_tail(&fhc->chan.device_node, ++ &fhd->dma.channels); ++ else ++ list_add(&fhc->chan.device_node, &fhd->dma.channels); ++ ++ /* 7 is highest priority & 0 is lowest. */ ++ if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) ++ fhc->priority = r; ++ else ++ fhc->priority = i; ++ ++ fhc->ch_regs = &__fh_regs(fhd)->CHAN[i]; ++ spin_lock_init(&fhc->lock); ++ fhc->mask = 1 << i; ++ ++ INIT_LIST_HEAD(&fhc->active_list); ++ INIT_LIST_HEAD(&fhc->queue); ++ INIT_LIST_HEAD(&fhc->free_list); ++ ++ channel_clear_bit(fhd, CH_EN, fhc->mask); ++ ++ fhc->direction = DMA_TRANS_NONE; ++ fhc->request_line = ~0; ++ ++ /* Hardware configuration */ ++ if (autocfg) { ++ unsigned int fhc_params; ++ ++ fhc_params = dma_read_byaddr(regs + r * sizeof(u32), ++ FHC_PARAMS); ++ ++ dev_dbg(&pdev->dev, "FHC_PARAMS[%d]: 0x%08x\n", i, ++ fhc_params); ++ ++ /* Decode maximum block size for given channel. The ++ * stored 4 bit value represents blocks from 0x00 for 3 ++ * up to 0x0a for 4095. */ ++ fhc->block_size = ++ (4 << ((max_blk_size >> 4 * i) & 0xf)) - 1; ++ fhc->nollp = ++ (fhc_params >> FHC_PARAMS_MBLK_EN & 0x1) == 0; ++ } else { ++ fhc->block_size = pdata->block_size; ++ ++ /* Check if channel supports multi block transfer */ ++ channel_writel(fhc, LLP, 0xfffffffc); ++ fhc->nollp = ++ (channel_readl(fhc, LLP) & 0xfffffffc) == 0; ++ channel_writel(fhc, LLP, 0); ++ } ++ } ++ ++ /* Clear all interrupts on all channels. */ ++ dma_writel(fhd, CLEAR.XFER, fhd->all_chan_mask); ++ dma_writel(fhd, CLEAR.BLOCK, fhd->all_chan_mask); ++ dma_writel(fhd, CLEAR.SRC_TRAN, fhd->all_chan_mask); ++ dma_writel(fhd, CLEAR.DST_TRAN, fhd->all_chan_mask); ++ dma_writel(fhd, CLEAR.ERROR, fhd->all_chan_mask); ++ ++ dma_cap_set(DMA_MEMCPY, fhd->dma.cap_mask); ++ dma_cap_set(DMA_SLAVE, fhd->dma.cap_mask); ++ if (pdata->is_private) ++ dma_cap_set(DMA_PRIVATE, fhd->dma.cap_mask); ++ fhd->dma.dev = &pdev->dev; ++ fhd->dma.device_alloc_chan_resources = fhc_alloc_chan_resources; ++ fhd->dma.device_free_chan_resources = fhc_free_chan_resources; ++ ++ fhd->dma.device_prep_dma_memcpy = fhc_prep_dma_memcpy; ++ ++ fhd->dma.device_prep_slave_sg = fhc_prep_slave_sg; ++ fhd->dma.device_control = fhc_control; ++ ++ fhd->dma.device_tx_status = fhc_tx_status; ++ fhd->dma.device_issue_pending = fhc_issue_pending; ++ ++ dma_writel(fhd, CFG, FH_CFG_DMA_EN); ++ ++ err = dma_async_device_register(&fhd->dma); ++ ++ if(err) ++ pr_err("dma register failed, ret %d\n", err); ++ ++ dev_info(&pdev->dev, "FH DMA Controller, %d channels\n", ++ nr_channels); ++ ++ return 0; ++ ++err_release_r: ++ release_resource(io); ++ return err; ++} ++ ++static int fh_dma_remove(struct platform_device *pdev) ++{ ++ struct fh_dma *fhd = platform_get_drvdata(pdev); ++ struct fh_dma_chan *fhc, *_fhc; ++ ++ fh_dma_off(fhd); ++ dma_async_device_unregister(&fhd->dma); ++ ++ tasklet_kill(&fhd->tasklet); ++ ++ list_for_each_entry_safe(fhc, _fhc, &fhd->dma.channels, ++ chan.device_node) { ++ list_del(&fhc->chan.device_node); ++ channel_clear_bit(fhd, CH_EN, fhc->mask); ++ } ++ ++ return 0; ++} ++ ++static void fh_dma_shutdown(struct platform_device *pdev) ++{ ++ struct fh_dma *fhd = platform_get_drvdata(pdev); ++ ++ fh_dma_off(fhd); ++ clk_disable(fhd->clk); ++} ++ ++static int fh_dma_suspend_noirq(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_dma *fhd = platform_get_drvdata(pdev); ++ ++ fh_dma_off(fhd); ++ clk_disable(fhd->clk); ++ ++ return 0; ++} ++ ++static int fh_dma_resume_noirq(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_dma *fhd = platform_get_drvdata(pdev); ++ ++ clk_enable(fhd->clk); ++ dma_writel(fhd, CFG, FH_CFG_DMA_EN); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops fh_dma_dev_pm_ops = { ++ .suspend_noirq = fh_dma_suspend_noirq, ++ .resume_noirq = fh_dma_resume_noirq, ++ .freeze_noirq = fh_dma_suspend_noirq, ++ .thaw_noirq = fh_dma_resume_noirq, ++ .restore_noirq = fh_dma_resume_noirq, ++ .poweroff_noirq = fh_dma_suspend_noirq, ++}; ++ ++static struct platform_driver fh_dma_driver = { ++ .probe = fh_dma_probe, ++ .remove = fh_dma_remove, ++ .shutdown = fh_dma_shutdown, ++ .driver = { ++ .name = "fh_dmac", ++ .pm = &fh_dma_dev_pm_ops, ++ }, ++}; ++ ++static int __init fh_dma_init(void) ++{ ++ return platform_driver_register(&fh_dma_driver); ++} ++subsys_initcall(fh_dma_init); ++ ++static void __exit fh_dma_exit(void) ++{ ++ platform_driver_unregister(&fh_dma_driver); ++} ++module_exit(fh_dma_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("FH DMA Controller driver"); +diff --git a/drivers/dma/fh_dmac_regs.h b/drivers/dma/fh_dmac_regs.h +new file mode 100644 +index 00000000..8ca1589f +--- /dev/null ++++ b/drivers/dma/fh_dmac_regs.h +@@ -0,0 +1,236 @@ ++/* ++ * Driver for the Synopsys DesignWare AHB DMA Controller ++ * ++ * Copyright (C) 2005-2007 Atmel Corporation ++ * Copyright (C) 2010-2011 ST Microelectronics ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <mach/fh_dmac.h> ++ ++#define FH_DMA_MAX_NR_CHANNELS 8 ++ ++/* ++ * Redefine this macro to handle differences between 32- and 64-bit ++ * addressing, big vs. little endian, etc. ++ */ ++#define FH_REG(name) u32 name; u32 __pad_##name ++ ++/* Hardware register definitions. */ ++struct fh_dma_chan_regs { ++ FH_REG(SAR); /* Source Address Register */ ++ FH_REG(DAR); /* Destination Address Register */ ++ FH_REG(LLP); /* Linked List Pointer */ ++ u32 CTL_LO; /* Control Register Low */ ++ u32 CTL_HI; /* Control Register High */ ++ FH_REG(SSTAT); ++ FH_REG(DSTAT); ++ FH_REG(SSTATAR); ++ FH_REG(DSTATAR); ++ u32 CFG_LO; /* Configuration Register Low */ ++ u32 CFG_HI; /* Configuration Register High */ ++ FH_REG(SGR); ++ FH_REG(DSR); ++}; ++ ++struct fh_dma_irq_regs { ++ FH_REG(XFER); ++ FH_REG(BLOCK); ++ FH_REG(SRC_TRAN); ++ FH_REG(DST_TRAN); ++ FH_REG(ERROR); ++}; ++ ++struct fh_dma_regs { ++ /* per-channel registers */ ++ struct fh_dma_chan_regs CHAN[FH_DMA_MAX_NR_CHANNELS]; ++ ++ /* irq handling */ ++ struct fh_dma_irq_regs RAW; /* r */ ++ struct fh_dma_irq_regs STATUS; /* r (raw & mask) */ ++ struct fh_dma_irq_regs MASK; /* rw (set = irq enabled) */ ++ struct fh_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ ++ ++ FH_REG(STATUS_INT); /* r */ ++ ++ /* software handshaking */ ++ FH_REG(REQ_SRC); ++ FH_REG(REQ_DST); ++ FH_REG(SGL_REQ_SRC); ++ FH_REG(SGL_REQ_DST); ++ FH_REG(LAST_SRC); ++ FH_REG(LAST_DST); ++ ++ /* miscellaneous */ ++ FH_REG(CFG); ++ FH_REG(CH_EN); ++ FH_REG(ID); ++ FH_REG(TEST); ++ ++ /* optional encoded params, 0x3c8..0x3 */ ++}; ++ ++/* Bitfields in CTL_LO */ ++#define FHC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ ++#define FHC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ ++#define FHC_CTLL_SRC_WIDTH(n) ((n)<<4) ++#define FHC_CTLL_DST_INC (0<<7) /* DAR update/not */ ++#define FHC_CTLL_DST_DEC (1<<7) ++#define FHC_CTLL_DST_FIX (2<<7) ++#define FHC_CTLL_SRC_INC (0<<9) /* SAR update/not */ ++#define FHC_CTLL_SRC_DEC (1<<9) ++#define FHC_CTLL_SRC_FIX (2<<9) ++#define FHC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ ++#define FHC_CTLL_SRC_MSIZE(n) ((n)<<14) ++#define FHC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ ++#define FHC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ ++#define FHC_CTLL_FC(n) ((n) << 20) ++#define FHC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ ++#define FHC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ ++#define FHC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ ++#define FHC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ ++/* plus 4 transfer types for peripheral-as-flow-controller */ ++#define FHC_CTLL_DMS(n) ((n)<<23) /* dst master select */ ++#define FHC_CTLL_SMS(n) ((n)<<25) /* src master select */ ++#define FHC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ ++#define FHC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ ++ ++/* Bitfields in CTL_HI */ ++#define FHC_CTLH_DONE 0x00001000 ++#define FHC_CTLH_BLOCK_TS_MASK 0x00000fff ++ ++/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/FH_dmac.h> */ ++#define FHC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ ++#define FHC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ ++#define FHC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ ++#define FHC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ ++#define FHC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ ++#define FHC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ ++#define FHC_CFGL_MAX_BURST(x) ((x) << 20) ++#define FHC_CFGL_RELOAD_SAR (1 << 30) ++#define FHC_CFGL_RELOAD_DAR (1 << 31) ++ ++/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/FH_dmac.h> */ ++#define FHC_CFGH_DS_UPD_EN (1 << 5) ++#define FHC_CFGH_SS_UPD_EN (1 << 6) ++ ++/* Bitfields in SGR */ ++#define FHC_SGR_SGI(x) ((x) << 0) ++#define FHC_SGR_SGC(x) ((x) << 20) ++ ++/* Bitfields in DSR */ ++#define FHC_DSR_DSI(x) ((x) << 0) ++#define FHC_DSR_DSC(x) ((x) << 20) ++ ++/* Bitfields in CFG */ ++#define FH_CFG_DMA_EN (1 << 0) ++ ++#define FH_REGLEN 0x400 ++ ++enum fh_dmac_flags { ++ FH_DMA_IS_CYCLIC = 0, ++}; ++ ++struct fh_dma_chan { ++ struct dma_chan chan; ++ void __iomem *ch_regs; ++ u8 mask; ++ u8 priority; ++ bool paused; ++ bool initialized; ++ spinlock_t lock; ++ ++ /* these other elements are all protected by lock */ ++ unsigned long flags; ++ dma_cookie_t completed; ++ struct list_head active_list; ++ struct list_head queue; ++ struct list_head free_list; ++ struct fh_cyclic_desc *cdesc; ++ ++ unsigned int descs_allocated; ++ ++}; ++ ++static inline struct fh_dma_chan_regs __iomem * ++__fhc_regs(struct fh_dma_chan *fhc) ++{ ++ return fhc->ch_regs; ++} ++ ++#define channel_readl(fhc, name) \ ++ readl(&(__fhc_regs(fhc)->name)) ++#define channel_writel(fhc, name, val) \ ++ writel((val), &(__fhc_regs(fhc)->name)) ++ ++static inline struct fh_dma_chan *to_fh_dma_chan(struct dma_chan *chan) ++{ ++ return container_of(chan, struct fh_dma_chan, chan); ++} ++ ++struct fh_dma { ++ struct dma_device dma; ++ void __iomem *regs; ++ struct tasklet_struct tasklet; ++ struct clk *clk; ++ ++ u8 all_chan_mask; ++ ++ struct fh_dma_chan chan[0]; ++}; ++ ++static inline struct fh_dma_regs __iomem *__fh_regs(struct fh_dma *fh) ++{ ++ return fh->regs; ++} ++ ++#define dma_readl(fh, name) \ ++ readl(&(__fh_regs(fh)->name)) ++#define dma_writel(fh, name, val) \ ++ writel((val), &(__fh_regs(fh)->name)) ++ ++#define channel_set_bit(fh, reg, mask) \ ++ dma_writel(fh, reg, ((mask) << 8) | (mask)) ++#define channel_clear_bit(fh, reg, mask) \ ++ dma_writel(fh, reg, ((mask) << 8) | 0) ++ ++static inline struct fh_dma *to_fh_dma(struct dma_device *ddev) ++{ ++ return container_of(ddev, struct fh_dma, dma); ++} ++ ++/* LLI == Linked List Item; a.k.a. DMA block descriptor */ ++struct fh_lli { ++ /* values that are not changed by hardware */ ++ u32 sar; ++ u32 dar; ++ u32 llp; /* chain to next lli */ ++ u32 ctllo; ++ /* values that may get written back: */ ++ u32 ctlhi; ++ /* sstat and dstat can snapshot peripheral register state. ++ * silicon config may discard either or both... ++ */ ++ u32 sstat; ++ u32 dstat; ++}; ++ ++struct fh_desc { ++ /* FIRST values the hardware uses */ ++ struct fh_lli lli; ++ ++ /* THEN values for driver housekeeping */ ++ struct list_head desc_node; ++ struct list_head tx_list; ++ struct dma_async_tx_descriptor txd; ++ size_t len; ++}; ++ ++static inline struct fh_desc * ++txd_to_fh_desc(struct dma_async_tx_descriptor *txd) ++{ ++ return container_of(txd, struct fh_desc, txd); ++} +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 2967002a..3780557d 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -85,6 +85,11 @@ config GPIO_IT8761E + tristate "IT8761E GPIO support" + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. ++ ++config GPIO_FH ++ tristate "FH GPIO support" ++ help ++ Say yes here to support GPIO functionality of FH. + + config GPIO_EXYNOS4 + def_bool y +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index b605f8ec..3562c0f9 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -34,6 +34,7 @@ obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o + obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o + obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o + obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o ++obj-$(CONFIG_GPIO_FH) += fh_gpio.o + obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o + obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o + obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o +diff --git a/drivers/gpio/fh_gpio.c b/drivers/gpio/fh_gpio.c +new file mode 100644 +index 00000000..11e8eb9c +--- /dev/null ++++ b/drivers/gpio/fh_gpio.c +@@ -0,0 +1,543 @@ ++#include <linux/kernel.h> ++#include <linux/spinlock.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/gpio.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++#include <asm-generic/gpio.h> ++#include <mach/gpio.h> ++ ++struct fh_gpio_chip *fh_gpio0, *fh_gpio1; ++ ++static inline void __iomem* gpio_to_base(unsigned int gpio) ++{ ++ if (gpio >= fh_gpio1->chip.base && gpio < (fh_gpio1->chip.base + fh_gpio1->chip.ngpio)) ++ { ++ return fh_gpio1->base; ++ } ++ else if (gpio < (fh_gpio0->chip.base + fh_gpio0->chip.ngpio)) { ++ return fh_gpio0->base; ++ } else { ++ pr_err("ERROR: incorrect GPIO num\n"); ++ return NULL; ++ } ++} ++ ++static int _set_gpio_irq_type(unsigned int gpio, unsigned int type) ++{ ++ u32 int_type, int_polarity; ++ u32 bit = gpio % 32; ++ void __iomem *base; ++ base = gpio_to_base(gpio); ++ ++ switch (type & IRQF_TRIGGER_MASK) { ++ case IRQ_TYPE_EDGE_BOTH: ++ int_type = GPIO_INT_TYPE_EDGE; ++ /* toggle trigger */ ++ if (FH_GPIO_GetValue((u32)base, bit)) ++ int_polarity = GPIO_INT_POL_LOW; ++ else ++ int_polarity = GPIO_INT_POL_HIGH; ++ break; ++ case IRQ_TYPE_EDGE_RISING: ++ int_type = GPIO_INT_TYPE_EDGE; ++ int_polarity = GPIO_INT_POL_HIGH; ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ int_type = GPIO_INT_TYPE_EDGE; ++ int_polarity = GPIO_INT_POL_LOW; ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ int_type = GPIO_INT_TYPE_LEVEL; ++ int_polarity = GPIO_INT_POL_HIGH; ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ int_type = GPIO_INT_TYPE_LEVEL; ++ int_polarity = GPIO_INT_POL_LOW; ++ break; ++ case IRQ_TYPE_NONE: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++ FH_GPIO_SetInterruptType((u32)base, bit, int_type); ++ FH_GPIO_SetInterruptPolarity((u32)base, bit, int_polarity); ++ return 0; ++} ++ ++int fh_set_gpio_irq(struct gpio_irq_info * info) ++{ ++ void __iomem* base; ++ base = gpio_to_base(info->irq_gpio); ++ ++ return _set_gpio_irq_type(info->irq_gpio, info->irq_type); ++} ++EXPORT_SYMBOL(fh_set_gpio_irq); ++ ++void fh_irq_enable(unsigned int gpio) ++{ ++ void __iomem* base; ++ int gpio_num = gpio % 32; ++ base = gpio_to_base(gpio); ++ ++ FH_GPIO_EnableInterrupt((u32)base, gpio_num, TRUE); ++} ++EXPORT_SYMBOL(fh_irq_enable); ++ ++void fh_irq_disable(unsigned int gpio) ++{ ++ void __iomem* base; ++ int gpio_num = gpio % 32; ++ base = gpio_to_base(gpio); ++ ++ FH_GPIO_EnableInterrupt((u32)base, gpio_num, FALSE); ++} ++EXPORT_SYMBOL(fh_irq_disable); ++ ++void fh_clear_gpio_irq(int gpio_id) ++{ ++ void __iomem* base; ++ int gpio_num = gpio_id % 32; ++ base = gpio_to_base(gpio_id); ++ ++ FH_GPIO_ClearInterrupt((u32)base, gpio_num); ++} ++EXPORT_SYMBOL(fh_clear_gpio_irq); ++ ++ ++static inline void __iomem* irq_to_controller(struct irq_data* d) ++{ ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ ++ if (likely(d->irq >= NR_INTERNAL_IRQS)) ++ return fh_gpio->base; ++ pr_err("irq num: %d is not a gpio irq!\n", d->irq); ++ return 0; ++} ++ ++static void gpio_irq_ack(struct irq_data* d) ++{ ++ void __iomem* base; ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ base = irq_to_controller(d); ++ ++ FH_GPIO_ClearInterrupt((u32)base, d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base); ++} ++ ++static void gpio_irq_enable(struct irq_data *d) ++{ ++ void __iomem* base; ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ base = irq_to_controller(d); ++ ++ FH_GPIO_EnableInterrupt((u32)base, d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base, TRUE); ++} ++ ++static void gpio_irq_disable(struct irq_data *d) ++{ ++ void __iomem* base; ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ base = irq_to_controller(d); ++ ++ FH_GPIO_EnableInterrupt((u32)base, d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base, FALSE); ++} ++ ++static void gpio_irq_mask(struct irq_data *d) ++{ ++ void __iomem* base; ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ base = irq_to_controller(d); ++ ++ FH_GPIO_EnableInterruptMask((u32)base, d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base, TRUE); ++} ++ ++static void gpio_irq_unmask(struct irq_data *d) ++{ ++ void __iomem* base; ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ base = irq_to_controller(d); ++ ++ FH_GPIO_EnableInterruptMask((u32)base, d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base, FALSE); ++} ++ ++static int gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ void __iomem* base; ++ base = irq_to_controller(d); ++ ++ return _set_gpio_irq_type(d->irq - NR_INTERNAL_IRQS, type); ++} ++ ++#ifdef CONFIG_PM ++ ++static int gpio_irq_set_wake(struct irq_data *d, unsigned value) ++{ ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); ++ ++ if (unlikely(d->irq >= NR_IRQS)) ++ return -EINVAL; ++ ++ if (value) ++ fh_gpio->gpio_wakeups |= (1 << (d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base)); ++ else ++ fh_gpio->gpio_wakeups &= ~(1 << (d->irq - NR_INTERNAL_IRQS - fh_gpio->chip.base)); ++ ++ return 0; ++} ++ ++void fh_gpio_irq_suspend(void) ++{ ++ fh_gpio0->gpio_backups = FH_GPIO_GetEnableInterrupts((u32)fh_gpio0->base); ++ fh_gpio1->gpio_backups = FH_GPIO_GetEnableInterrupts((u32)fh_gpio1->base); ++ ++ FH_GPIO_SetEnableInterrupts((u32)fh_gpio0->base, fh_gpio0->gpio_wakeups); ++ FH_GPIO_SetEnableInterrupts((u32)fh_gpio1->base, fh_gpio1->gpio_wakeups); ++} ++ ++void fh_gpio_irq_resume(void) ++{ ++ FH_GPIO_SetEnableInterrupts((u32)fh_gpio0->base, fh_gpio0->gpio_backups); ++ FH_GPIO_SetEnableInterrupts((u32)fh_gpio1->base, fh_gpio1->gpio_backups); ++} ++ ++#else ++#define gpio_irq_set_wake NULL ++#endif ++ ++static struct irq_chip gpio_irqchip = { ++ .name = "FH_GPIO_INTC", ++ .irq_ack = gpio_irq_ack, ++ .irq_enable = gpio_irq_enable, ++ .irq_disable = gpio_irq_disable, ++ .irq_mask = gpio_irq_mask, ++ .irq_unmask = gpio_irq_unmask, ++ .irq_set_type = gpio_irq_type, ++ .irq_set_wake = gpio_irq_set_wake, ++}; ++ ++static void gpio_toggle_trigger(unsigned int gpio, unsigned int offs) ++{ ++ u32 int_polarity; ++ ++ void __iomem* base = gpio_to_base(gpio); ++ if (FH_GPIO_GetValue((u32)base, offs)) ++ int_polarity = GPIO_INT_POL_LOW; ++ else ++ int_polarity = GPIO_INT_POL_HIGH; ++ ++ printk(">>>>> do trigger gpio=%d, set polarity=%x\n", gpio, int_polarity); ++ FH_GPIO_SetInterruptPolarity((u32)base, offs, int_polarity); ++} ++ ++static inline u32 irq_get_trigger_type(unsigned int irq) ++{ ++ struct irq_data *d = irq_get_irq_data(irq); ++ return d ? irqd_get_trigger_type(d) : 0; ++} ++ ++static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ struct irq_data *irqdata = irq_desc_get_irq_data(desc); ++ struct irq_chip *irqchip = irq_data_get_irq_chip(irqdata); ++ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(irqdata); ++ u32 irq_status; ++ int gpio_num, gpio; ++ ++ irq_status = FH_GPIO_GetInterruptStatus((u32)fh_gpio->base); ++ ++ if (unlikely(irq_status == 0)) { ++ pr_err("gpio irq status is zero.\n"); ++ return; ++ } ++ ++ /* temporarily mask (level sensitive) parent IRQ */ ++ irqchip->irq_mask(irqdata); ++ ++ gpio_num = fls(irq_status) - 1; ++ ++ FH_GPIO_ClearInterrupt((u32)fh_gpio->base, gpio_num); ++ ++ gpio = gpio_num + fh_gpio->chip.base; ++ ++ generic_handle_irq(gpio_to_irq(gpio)); ++ ++ if ((irq_get_trigger_type(gpio_to_irq(gpio)) & IRQ_TYPE_SENSE_MASK) ++ == IRQ_TYPE_EDGE_BOTH) ++ gpio_toggle_trigger(gpio, gpio_num); ++ ++ irqchip->irq_unmask(irqdata); ++ /* now it may re-trigger */ ++} ++ ++/* ++ * This lock class tells lockdep that GPIO irqs are in a different ++ * category than their parents, so it won't report false recursion. ++ */ ++static struct lock_class_key gpio_lock_class; ++ ++static void fh_gpio_irq_init(struct platform_device *pdev) ++{ ++ int i, gpio_irq; ++ struct fh_gpio_chip *plat_data; ++ ++ plat_data = pdev->dev.platform_data; ++ ++ for (i = 0; i < 32; i++) { ++ gpio_irq = i + NR_INTERNAL_IRQS + 32 * pdev->id; ++ irq_set_lockdep_class(gpio_irq, &gpio_lock_class); ++ irq_set_chip_and_handler(gpio_irq, &gpio_irqchip, handle_simple_irq); ++ set_irq_flags(gpio_irq, IRQF_VALID); ++ irq_set_chip_data(gpio_irq, plat_data); ++ } ++ ++ irq_set_chip_data(plat_data->irq, plat_data); ++ irq_set_chained_handler(plat_data->irq, gpio_irq_handler); ++ enable_irq_wake(plat_data->irq); ++} ++ ++static int chip_to_irq(struct gpio_chip *c, unsigned offset) ++{ ++ struct fh_gpio_chip* chip; ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ return offset + NR_INTERNAL_IRQS + chip->chip.base; ++} ++ ++static int chip_gpio_get(struct gpio_chip *c, unsigned offset) ++{ ++ u32 bit = offset % 32; ++ struct fh_gpio_chip* chip; ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ ++ if(offset / 32) ++ return FH_GPIOB_GetValue((u32)chip->base, bit); ++ else ++ return FH_GPIO_GetValue((u32)chip->base, bit); ++} ++ ++static void chip_gpio_set(struct gpio_chip *c, unsigned offset, int val) ++{ ++ u32 bit = offset % 32; ++ struct fh_gpio_chip* chip; ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ if(offset / 32) ++ FH_GPIOB_SetValue((u32)chip->base, bit, val); ++ else ++ FH_GPIO_SetValue((u32)chip->base, bit, val); ++} ++ ++static int chip_direction_input(struct gpio_chip *c, unsigned offset) ++{ ++ u32 bit = offset % 32; ++ unsigned long flags; ++ struct fh_gpio_chip* chip; ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ spin_lock_irqsave(&chip->lock, flags); ++ if(offset / 32) ++ FH_GPIOB_SetDirection((u32)chip->base, bit, GPIO_DIR_INPUT); ++ else ++ FH_GPIO_SetDirection((u32)chip->base, bit, GPIO_DIR_INPUT); ++ spin_unlock_irqrestore(&chip->lock, flags); ++ ++ return 0; ++} ++ ++static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) ++{ ++ u32 bit = offset % 32; ++ unsigned long flags; ++ struct fh_gpio_chip* chip; ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ ++ spin_lock_irqsave(&chip->lock, flags); ++ if(offset / 32) ++ { ++ FH_GPIOB_SetDirection((u32)chip->base, bit, GPIO_DIR_OUTPUT); ++ FH_GPIOB_SetValue((u32)chip->base, bit, val); ++ } ++ else ++ { ++ FH_GPIO_SetDirection((u32)chip->base, bit, GPIO_DIR_OUTPUT); ++ FH_GPIO_SetValue((u32)chip->base, bit, val); ++ } ++ spin_unlock_irqrestore(&chip->lock, flags); ++ ++ return 0; ++} ++ ++static int chip_gpio_set_debounce(struct gpio_chip *c, unsigned offset, ++ unsigned debounce) ++{ ++ u32 bit = offset % 32; ++ unsigned long flags; ++ char db_clk_name[16] = {0}; ++ struct clk *gpio_clk = NULL; ++ int ret = 0; ++ struct fh_gpio_chip *chip; ++ bool enabled = !!debounce; ++ unsigned int clk_rate = 0; ++ ++ sprintf(db_clk_name, "gpio%d_dbclk", (offset / 32)); ++ gpio_clk = clk_get(NULL, db_clk_name); ++ if (IS_ERR(gpio_clk)) ++ return PTR_ERR(gpio_clk); ++ ++ clk_rate = 1000000UL / debounce; ++ ++ ret = clk_set_rate(gpio_clk, clk_rate); ++ if (ret) { ++ pr_err("Set GPIO Debounce Clk fail\n"); ++ return ret; ++ } ++ ++ ret = clk_enable(gpio_clk); ++ if (ret) { ++ pr_err("Set GPIO Debounce Clk fail\n"); ++ return ret; ++ } ++ ++ chip = container_of(c, struct fh_gpio_chip, chip); ++ spin_lock_irqsave(&chip->lock, flags); ++ FH_GPIO_EnableDebounce((u32)chip->base, bit, enabled); ++ spin_unlock_irqrestore(&chip->lock, flags); ++ ++ return 0; ++} ++ ++void fh_gpio_set(int gpio_id, int value) ++{ ++ __gpio_set_value(gpio_id, value); ++} ++EXPORT_SYMBOL(fh_gpio_set); ++ ++int fh_gpio_get(int gpio_id, int* value) ++{ ++ *value = __gpio_get_value(gpio_id); ++ return 0; ++} ++EXPORT_SYMBOL(fh_gpio_get); ++ ++int fh_gpio_reset(int gpio_id) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(fh_gpio_reset); ++ ++static int __devinit fh_gpio_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int err = -EIO; ++ struct fh_gpio_chip *plat_data; ++ ++ /* There are two ways to get the GPIO base address; one is by ++ * fetching it from MSR_LBAR_GPIO, the other is by reading the ++ * PCI BAR info. The latter method is easier (especially across ++ * different architectures), so we'll stick with that for now. If ++ * it turns out to be unreliable in the face of crappy BIOSes, we ++ * can always go back to using MSRs.. */ ++ ++ plat_data = pdev->dev.platform_data; ++ plat_data->chip.get = chip_gpio_get; ++ plat_data->chip.set = chip_gpio_set; ++ plat_data->chip.direction_input = chip_direction_input; ++ plat_data->chip.direction_output = chip_direction_output; ++ plat_data->chip.to_irq = chip_to_irq; ++ plat_data->chip.set_debounce = chip_gpio_set_debounce; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "can't fetch device resource info\n"); ++ goto done; ++ } ++ ++ if (!request_mem_region(res->start, resource_size(res), pdev->name)) { ++ dev_err(&pdev->dev, "can't request region\n"); ++ goto done; ++ } ++ ++ /* set up the driver-specific struct */ ++ plat_data->base = ioremap(res->start, resource_size(res)); ++ ++ if(pdev->id) ++ fh_gpio1 = plat_data; ++ else ++ fh_gpio0 = plat_data; ++ ++ plat_data->pdev = pdev; ++ spin_lock_init(&plat_data->lock); ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ pr_err("%s: ERROR: getting resource failed" ++ "cannot get IORESOURCE_MEM\n", __func__); ++ goto release_region; ++ } ++ plat_data->irq = res->start; ++ ++ /* finally, register with the generic GPIO API */ ++ err = gpiochip_add(&plat_data->chip); ++ if (err) { ++ pr_err("GPIO support load fail.\n"); ++ goto release_region; ++ } ++ ++ fh_gpio_irq_init(pdev); ++ pr_debug("GPIO support successfully loaded.\n\tBase Addr: 0x%p\n", ++ plat_data->base); ++ ++ return 0; ++ ++release_region: ++ release_region(res->start, resource_size(res)); ++done: ++ return err; ++} ++ ++static int __devexit fh_gpio_remove(struct platform_device *pdev) ++{ ++ struct resource *r; ++ int err; ++ struct fh_gpio_chip *plat_data; ++ ++ plat_data = pdev->dev.platform_data; ++ err = gpiochip_remove(&plat_data->chip); ++ if (err) { ++ dev_err(&pdev->dev, "unable to remove gpio_chip\n"); ++ return err; ++ } ++ ++ iounmap(plat_data->base); ++ ++ r = platform_get_resource(pdev, IORESOURCE_IO, 0); ++ release_region(r->start, resource_size(r)); ++ return 0; ++} ++ ++static struct platform_driver fh_gpio_driver = { ++ .driver = { ++ .name = GPIO_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_gpio_probe, ++ .remove = __devexit_p(fh_gpio_remove), ++}; ++ ++static int __init fh_gpio_init(void) ++{ ++ return platform_driver_register(&fh_gpio_driver); ++} ++ ++static void __exit fh_gpio_exit(void) ++{ ++ platform_driver_unregister(&fh_gpio_driver); ++} ++ ++module_init(fh_gpio_init); ++module_exit(fh_gpio_exit); ++ ++MODULE_AUTHOR("QIN"); ++MODULE_DESCRIPTION("FH GPIO Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform: FH"); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 646068e5..82347f92 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -298,7 +298,18 @@ config I2C_AT91 + documented way to issue repeated START conditions, as needed + to support combined I2C messages. Use the i2c-gpio driver + unless your system can cope with those limitations. ++ ++config I2C_FH_INTERRUPT ++ tristate "FH I2C Driver with Interrupt" ++ help ++ This supports the use of the I2C interface on Fullhan ++ processors. ++ ++ Only master mode is supported. + ++ This driver can also be built as a module. If so, the module ++ will be called ++ + config I2C_AU1550 + tristate "Au1550/Au1200 SMBus interface" + depends on SOC_AU1550 || SOC_AU1200 +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index e6cf294d..93dbee32 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -82,5 +82,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o + obj-$(CONFIG_I2C_STUB) += i2c-stub.o + obj-$(CONFIG_SCx200_ACB) += scx200_acb.o + obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o ++obj-$(CONFIG_I2C_FH_INTERRUPT) += i2c_fh_interrupt.o + + ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG +diff --git a/drivers/i2c/busses/i2c_fh_interrupt.c b/drivers/i2c/busses/i2c_fh_interrupt.c +new file mode 100644 +index 00000000..fa3daa47 +--- /dev/null ++++ b/drivers/i2c/busses/i2c_fh_interrupt.c +@@ -0,0 +1,938 @@ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/i2c.h> ++#include <linux/clk.h> ++#include <linux/errno.h> ++#include <linux/sched.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/slab.h> ++#include <mach/i2c.h> ++//#define FH_I2C_DEBUG ++ ++#ifdef FH_I2C_DEBUG ++#define PRINT_DBG(fmt, args...) printk(fmt, ## args) ++#else ++#define PRINT_DBG(fmt, args...) do { } while (0) ++#endif ++ ++/* ++ * Registers offset ++ */ ++#define DW_IC_CON 0x0 ++#define DW_IC_TAR 0x4 ++#define DW_IC_DATA_CMD 0x10 ++#define DW_IC_SS_SCL_HCNT 0x14 ++#define DW_IC_SS_SCL_LCNT 0x18 ++#define DW_IC_FS_SCL_HCNT 0x1c ++#define DW_IC_FS_SCL_LCNT 0x20 ++#define DW_IC_INTR_STAT 0x2c ++#define DW_IC_INTR_MASK 0x30 ++#define DW_IC_RAW_INTR_STAT 0x34 ++#define DW_IC_RX_TL 0x38 ++#define DW_IC_TX_TL 0x3c ++#define DW_IC_CLR_INTR 0x40 ++#define DW_IC_CLR_RX_UNDER 0x44 ++#define DW_IC_CLR_RX_OVER 0x48 ++#define DW_IC_CLR_TX_OVER 0x4c ++#define DW_IC_CLR_RD_REQ 0x50 ++#define DW_IC_CLR_TX_ABRT 0x54 ++#define DW_IC_CLR_RX_DONE 0x58 ++#define DW_IC_CLR_ACTIVITY 0x5c ++#define DW_IC_CLR_STOP_DET 0x60 ++#define DW_IC_CLR_START_DET 0x64 ++#define DW_IC_CLR_GEN_CALL 0x68 ++#define DW_IC_ENABLE 0x6c ++#define DW_IC_STATUS 0x70 ++#define DW_IC_TXFLR 0x74 ++#define DW_IC_RXFLR 0x78 ++#define DW_IC_COMP_PARAM_1 0xf4 ++#define DW_IC_TX_ABRT_SOURCE 0x80 ++ ++#define DW_IC_CON_MASTER 0x1 ++#define DW_IC_CON_SPEED_STD 0x2 ++#define DW_IC_CON_SPEED_FAST 0x4 ++#define DW_IC_CON_10BITADDR_MASTER 0x10 ++#define DW_IC_CON_RESTART_EN 0x20 ++#define DW_IC_CON_SLAVE_DISABLE 0x40 ++ ++#define DW_IC_INTR_RX_UNDER 0x001 ++#define DW_IC_INTR_RX_OVER 0x002 ++#define DW_IC_INTR_RX_FULL 0x004 ++#define DW_IC_INTR_TX_OVER 0x008 ++#define DW_IC_INTR_TX_EMPTY 0x010 ++#define DW_IC_INTR_RD_REQ 0x020 ++#define DW_IC_INTR_TX_ABRT 0x040 ++#define DW_IC_INTR_RX_DONE 0x080 ++#define DW_IC_INTR_ACTIVITY 0x100 ++#define DW_IC_INTR_STOP_DET 0x200 ++#define DW_IC_INTR_START_DET 0x400 ++#define DW_IC_INTR_GEN_CALL 0x800 ++ ++#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ ++ DW_IC_INTR_TX_EMPTY | \ ++ DW_IC_INTR_TX_ABRT | \ ++ DW_IC_INTR_STOP_DET) ++ ++#define DW_IC_STATUS_ACTIVITY 0x1 ++#define DW_IC_STATUS_MASTER_ACTIVITY 0x20 ++ ++#define DW_IC_ERR_TX_ABRT 0x1 ++ ++/* ++ * status codes ++ */ ++#define STATUS_IDLE 0x0 ++#define STATUS_WRITE_IN_PROGRESS 0x1 ++#define STATUS_READ_IN_PROGRESS 0x2 ++ ++#define TIMEOUT 20 /* ms */ ++ ++/* ++ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register ++ * ++ * only expected abort codes are listed here ++ * refer to the datasheet for the full list ++ */ ++#define ABRT_7B_ADDR_NOACK 0 ++#define ABRT_10ADDR1_NOACK 1 ++#define ABRT_10ADDR2_NOACK 2 ++#define ABRT_TXDATA_NOACK 3 ++#define ABRT_GCALL_NOACK 4 ++#define ABRT_GCALL_READ 5 ++#define ABRT_SBYTE_ACKDET 7 ++#define ABRT_SBYTE_NORSTRT 9 ++#define ABRT_10B_RD_NORSTRT 10 ++#define ABRT_MASTER_DIS 11 ++#define ARB_LOST 12 ++ ++#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) ++#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) ++#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) ++#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) ++#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) ++#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) ++#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) ++#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) ++#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) ++#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) ++#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) ++ ++#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ ++ DW_IC_TX_ABRT_10ADDR1_NOACK | \ ++ DW_IC_TX_ABRT_10ADDR2_NOACK | \ ++ DW_IC_TX_ABRT_TXDATA_NOACK | \ ++ DW_IC_TX_ABRT_GCALL_NOACK) ++ ++static char *abort_sources[] = { ++ [ABRT_7B_ADDR_NOACK] = ++ "slave address not acknowledged (7bit mode)", ++ [ABRT_10ADDR1_NOACK] = ++ "first address byte not acknowledged (10bit mode)", ++ [ABRT_10ADDR2_NOACK] = ++ "second address byte not acknowledged (10bit mode)", ++ [ABRT_TXDATA_NOACK] = ++ "data not acknowledged", ++ [ABRT_GCALL_NOACK] = ++ "no acknowledgement for a general call", ++ [ABRT_GCALL_READ] = ++ "read after general call", ++ [ABRT_SBYTE_ACKDET] = ++ "start byte acknowledged", ++ [ABRT_SBYTE_NORSTRT] = ++ "trying to send start byte when restart is disabled", ++ [ABRT_10B_RD_NORSTRT] = ++ "trying to read when restart is disabled (10bit mode)", ++ [ABRT_MASTER_DIS] = ++ "trying to use disabled adapter", ++ [ARB_LOST] = ++ "lost arbitration", ++}; ++ ++/** ++ * struct fh_i2c_dev - private i2c-designware data ++ * @dev: driver model device node ++ * @base: IO registers pointer ++ * @cmd_complete: tx completion indicator ++ * @lock: protect this struct and IO registers ++ * @clk: input reference clock ++ * @cmd_err: run time hadware error code ++ * @msgs: points to an array of messages currently being transferred ++ * @msgs_num: the number of elements in msgs ++ * @msg_write_idx: the element index of the current tx message in the msgs ++ * array ++ * @tx_buf_len: the length of the current tx buffer ++ * @tx_buf: the current tx buffer ++ * @msg_read_idx: the element index of the current rx message in the msgs ++ * array ++ * @rx_buf_len: the length of the current rx buffer ++ * @rx_buf: the current rx buffer ++ * @msg_err: error status of the current transfer ++ * @status: i2c master status, one of STATUS_* ++ * @abort_source: copy of the TX_ABRT_SOURCE register ++ * @irq: interrupt number for the i2c master ++ * @adapter: i2c subsystem adapter node ++ * @tx_fifo_depth: depth of the hardware tx fifo ++ * @rx_fifo_depth: depth of the hardware rx fifo ++ */ ++struct fh_i2c_dev { ++ struct device *dev; ++ void __iomem *base; ++ struct completion cmd_complete; ++ struct mutex lock; ++ struct clk *clk; ++ int cmd_err; ++ struct i2c_msg *msgs; ++ int msgs_num; ++ int msg_write_idx; ++ u32 tx_buf_len; ++ u8 *tx_buf; ++ int msg_read_idx; ++ u32 rx_buf_len; ++ u8 *rx_buf; ++ int msg_err; ++ unsigned int status; ++ u32 abort_source; ++ int irq; ++ struct i2c_adapter adapter; ++ unsigned int tx_fifo_depth; ++ unsigned int rx_fifo_depth; ++}; ++ ++ ++static int i2c_fh_wait_master_not_active(struct fh_i2c_dev *dev) ++{ ++ int timeout = 200; //2000 us ++ ++ while (I2c_IsActiveMst( dev->base)) ++ { ++ if (timeout <= 0) ++ { ++ dev_warn(dev->dev, "timeout waiting for master not active\n"); ++ return -ETIMEDOUT; ++ } ++ timeout--; ++ udelay(10); ++ } ++ ++ return 0; ++} ++ ++static u32 ++i2c_fh_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) ++{ ++ /* ++ * DesignWare I2C core doesn't seem to have solid strategy to meet ++ * the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec ++ * will result in violation of the tHD;STA spec. ++ */ ++ if (cond) ++ /* ++ * Conditional expression: ++ * ++ * IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH ++ * ++ * This is based on the DW manuals, and represents an ideal ++ * configuration. The resulting I2C bus speed will be ++ * faster than any of the others. ++ * ++ * If your hardware is free from tHD;STA issue, try this one. ++ */ ++ return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; ++ else ++ /* ++ * Conditional expression: ++ * ++ * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf) ++ * ++ * This is just experimental rule; the tHD;STA period turned ++ * out to be proportinal to (_HCNT + 3). With this setting, ++ * we could meet both tHIGH and tHD;STA timing specs. ++ * ++ * If unsure, you'd better to take this alternative. ++ * ++ * The reason why we need to take into account "tf" here, ++ * is the same as described in i2c_fh_scl_lcnt(). ++ */ ++ return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; ++} ++ ++static u32 i2c_fh_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) ++{ ++ /* ++ * Conditional expression: ++ * ++ * IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf) ++ * ++ * DW I2C core starts counting the SCL CNTs for the LOW period ++ * of the SCL clock (tLOW) as soon as it pulls the SCL line. ++ * In order to meet the tLOW timing spec, we need to take into ++ * account the fall time of SCL signal (tf). Default tf value ++ * should be 0.3 us, for safety. ++ */ ++ return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; ++} ++ ++/** ++ * i2c_fh_init() - initialize the designware i2c master hardware ++ * @dev: device private data ++ * ++ * This functions configures and enables the I2C master. ++ * This function is called during I2C init function, and in case of timeout at ++ * run time. ++ */ ++static void i2c_fh_init(struct fh_i2c_dev *dev) ++{ ++ u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; ++ u32 ic_con, hcnt, lcnt; ++ ++ /* Disable the adapter */ ++ i2c_fh_wait_master_not_active(dev); ++ I2c_DisEnable((unsigned int)dev->base); ++ ++ /* set standard and fast speed deviders for high/low periods */ ++ ++ /* Standard-mode */ ++ ++ hcnt = i2c_fh_scl_hcnt(input_clock_khz, ++ 40, /* tHD;STA = tHIGH = 4.0 us */ ++ 3, /* tf = 0.3 us */ ++ 0, /* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ ++ lcnt = i2c_fh_scl_lcnt(input_clock_khz, ++ 47, /* tLOW = 4.7 us */ ++ 3, /* tf = 0.3 us */ ++ 0); /* No offset */ ++ I2c_SetSsHcnt( dev->base ,hcnt); ++ I2c_SetSsLcnt( dev->base ,lcnt); ++ pr_info("\tClock: %dkhz, Standard-mode HCNT:LCNT = %d:%d\n", input_clock_khz, hcnt, lcnt); ++ ++ /* Fast-mode */ ++ hcnt = i2c_fh_scl_hcnt(input_clock_khz, ++ 6, /* tHD;STA = tHIGH = 0.6 us */ ++ 3, /* tf = 0.3 us */ ++ 0, /* 0: DW default, 1: Ideal */ ++ 0); /* No offset */ ++ lcnt = i2c_fh_scl_lcnt(input_clock_khz, ++ 13, /* tLOW = 1.3 us */ ++ 3, /* tf = 0.3 us */ ++ 0); /* No offset */ ++ I2c_SetFsHcnt( dev->base ,hcnt); ++ I2c_SetFsLcnt( dev->base ,lcnt); ++ //dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); ++ ++ /* Configure Tx/Rx FIFO threshold levels */ ++ ++ I2c_SetTxRxTl(dev->base ,dev->tx_fifo_depth - 1,0); ++ /* configure the i2c master */ ++ ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | ++ DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;/* DW_IC_CON_SPEED_STD */; ++ I2c_SetCon(dev->base,ic_con); ++ ++} ++ ++/* ++ * Waiting for bus not busy ++ */ ++static int i2c_fh_wait_bus_not_busy(struct fh_i2c_dev *dev) ++{ ++ int timeout = TIMEOUT; ++ ++ while (I2c_IsActiveMst( dev->base)) { ++ if (timeout <= 0) { ++ dev_warn(dev->dev, "timeout waiting for bus ready\n"); ++ return -ETIMEDOUT; ++ } ++ timeout--; ++ msleep(1); ++ } ++ ++ return 0; ++} ++ ++static void i2c_fh_xfer_init(struct fh_i2c_dev *dev) ++{ ++ struct i2c_msg *msgs = dev->msgs; ++ u32 ic_con; ++ ++ /* Disable the adapter */ ++ i2c_fh_wait_master_not_active(dev); ++ I2c_DisEnable((unsigned int)dev->base); ++ ++ /* set the slave (target) address */ ++ I2c_SetDeviceId(dev->base,msgs[dev->msg_write_idx].addr); ++ ++ /* if the slave address is ten bit address, enable 10BITADDR */ ++ ic_con = I2c_GetCon(dev->base); ++ if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) ++ ic_con |= DW_IC_CON_10BITADDR_MASTER; ++ else ++ ic_con &= ~DW_IC_CON_10BITADDR_MASTER; ++ I2c_SetCon(dev->base,ic_con); ++ ++ /* Enable the adapter */ ++ I2c_Enable(dev->base); ++ ++ /* Enable interrupts */ ++ I2c_SetIntrMask(dev->base,DW_IC_INTR_DEFAULT_MASK); ++ ++} ++ ++/* ++ * Initiate (and continue) low level master read/write transaction. ++ * This function is only called from i2c_fh_isr, and pumping i2c_msg ++ * messages into the tx buffer. Even if the size of i2c_msg data is ++ * longer than the size of the tx buffer, it handles everything. ++ */ ++static void ++i2c_fh_xfer_msg(struct fh_i2c_dev *dev) ++{ ++ struct i2c_msg *msgs = dev->msgs; ++ u32 intr_mask, cmd; ++ int tx_limit, rx_limit; ++ u32 addr = msgs[dev->msg_write_idx].addr; ++ u32 buf_len = dev->tx_buf_len; ++ u8 *buf = dev->tx_buf;; ++ ++ PRINT_DBG("i2c_fh_xfer_msg start, dev->msgs_num: %d\n", dev->msgs_num); ++ ++ intr_mask = DW_IC_INTR_DEFAULT_MASK; ++ ++ for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) ++ { ++ /* ++ * if target address has changed, we need to ++ * reprogram the target address in the i2c ++ * adapter when we are done with this transfer ++ */ ++ if (msgs[dev->msg_write_idx].addr != addr) { ++ dev_err(dev->dev, ++ "%s: invalid target address\n", __func__); ++ dev->msg_err = -EINVAL; ++ break; ++ } ++ ++ if (msgs[dev->msg_write_idx].len == 0) { ++ dev_err(dev->dev, ++ "%s: invalid message length\n", __func__); ++ dev->msg_err = -EINVAL; ++ break; ++ } ++ ++ if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) ++ { ++ /* new i2c_msg */ ++ buf = msgs[dev->msg_write_idx].buf; ++ buf_len = msgs[dev->msg_write_idx].len; ++ ++ PRINT_DBG("new msg: len: %d, buf: 0x%x\n", buf_len, buf[0]); ++ } ++ ++ tx_limit = dev->tx_fifo_depth - I2c_GetTxTl(dev->base ); ++ rx_limit = dev->rx_fifo_depth - I2c_GetRxTl(dev->base ); ++ ++ while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) ++ { ++ if (msgs[dev->msg_write_idx].flags & I2C_M_RD) ++ { ++ cmd = 0x100; ++ rx_limit--; ++ } ++ else ++ { ++ cmd = *buf++; ++ } ++ ++ tx_limit--; buf_len--; ++ ++ if (!buf_len && ++ ((dev->msg_write_idx == dev->msgs_num - 1) || ++ (msgs[dev->msg_write_idx].flags & ++ I2C_M_SPERATE_MSG))) { ++ /* 2015-11-8 ar0130 bug fixed */ ++ /* 20*1000 about 2 *0.1 ms ++ * (for i2c send one byte @ 100KHz) ++ * fixme: define MACRO get timeout value; */ ++ unsigned int _timeout = 20000; ++ while (I2C_GetTransmitFifoLevel(dev->base) && ++ _timeout--) ++ ; ++ cmd |= 0x200; ++ } ++ I2c_Write(dev->base, cmd); ++ } ++ PRINT_DBG("\n"); ++ ++ dev->tx_buf = buf; ++ dev->tx_buf_len = buf_len; ++ ++ if (buf_len > 0) ++ { ++ /* more bytes to be written */ ++ dev->status |= STATUS_WRITE_IN_PROGRESS; ++ break; ++ } ++ else ++ { ++ dev->status &= ~STATUS_WRITE_IN_PROGRESS; ++ } ++ } ++ ++ /* ++ * If i2c_msg index search is completed, we don't need TX_EMPTY ++ * interrupt any more. ++ */ ++ ++ if (dev->msg_write_idx == dev->msgs_num) ++ intr_mask &= ~DW_IC_INTR_TX_EMPTY; ++ ++ if (dev->msg_err) ++ intr_mask = 0; ++ ++ I2c_SetIntrMask(dev->base,intr_mask); ++ ++} ++ ++static void ++i2c_fh_read(struct fh_i2c_dev *dev) ++{ ++ struct i2c_msg *msgs = dev->msgs; ++ int rx_valid; ++ ++ for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) ++ { ++ u32 len; ++ u8 *buf; ++ ++ if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) ++ continue; ++ ++ if (!(dev->status & STATUS_READ_IN_PROGRESS)) ++ { ++ len = msgs[dev->msg_read_idx].len; ++ buf = msgs[dev->msg_read_idx].buf; ++ } ++ else ++ { ++ PRINT_DBG("STATUS_READ_IN_PROGRESS\n"); ++ len = dev->rx_buf_len; ++ buf = dev->rx_buf; ++ } ++ ++ rx_valid = I2c_GetRxFLR(dev->base); ++ ++ if(rx_valid == 0) ++ { ++ PRINT_DBG("rx_valid == 0\n"); ++ } ++ ++ for (; len > 0 && rx_valid > 0; len--, rx_valid--) ++ { ++ *buf++ = I2c_Read(dev->base); ++ } ++ ++ PRINT_DBG("i2c_fh_read, len: %d, buf[0]: 0x%x\n", msgs[dev->msg_read_idx].len, msgs[dev->msg_read_idx].buf[0]); ++ ++ if (len > 0) ++ { ++ PRINT_DBG("len > 0\n"); ++ dev->status |= STATUS_READ_IN_PROGRESS; ++ dev->rx_buf_len = len; ++ dev->rx_buf = buf; ++ return; ++ } else ++ dev->status &= ~STATUS_READ_IN_PROGRESS; ++ } ++} ++ ++static int i2c_fh_handle_tx_abort(struct fh_i2c_dev *dev) ++{ ++ unsigned long abort_source = dev->abort_source; ++ int i; ++ ++ if (abort_source & DW_IC_TX_ABRT_NOACK) { ++ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) ++ { ++ PRINT_DBG( ++ "%s: %s\n", __func__, abort_sources[i]); ++ } ++ return -EREMOTEIO; ++ } ++ ++ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) ++ dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); ++ ++ if (abort_source & DW_IC_TX_ARB_LOST) ++ return -EAGAIN; ++ else if (abort_source & DW_IC_TX_ABRT_GCALL_READ) ++ return -EINVAL; /* wrong msgs[] data */ ++ else ++ return -EIO; ++} ++ ++/* ++ * Prepare controller for a transaction and call i2c_fh_xfer_msg ++ */ ++static int ++i2c_fh_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ++{ ++ struct fh_i2c_dev *dev = i2c_get_adapdata(adap); ++ int ret; ++ ++ PRINT_DBG("-------i2c, %s: msgs: %d\n", __func__, num); ++ ++ mutex_lock(&dev->lock); ++ ++ INIT_COMPLETION(dev->cmd_complete); ++ dev->msgs = msgs; ++ dev->msgs_num = num; ++ dev->cmd_err = 0; ++ dev->msg_write_idx = 0; ++ dev->msg_read_idx = 0; ++ dev->msg_err = 0; ++ dev->status = STATUS_IDLE; ++ dev->abort_source = 0; ++ ++ ret = i2c_fh_wait_bus_not_busy(dev); ++ if (ret < 0) ++ { ++ goto done; ++ } ++ ++ /* start the transfers */ ++ i2c_fh_xfer_init(dev); ++ ++ /* wait for tx to complete */ ++ ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); ++ if (ret == 0) { ++ dev_err(dev->dev, "controller timed out\n"); ++ i2c_fh_init(dev); ++ ret = -ETIMEDOUT; ++ goto done; ++ } else if (ret < 0) ++ goto done; ++ ++ if (dev->msg_err) ++ { ++ PRINT_DBG("dev->msg_err\n"); ++ ret = dev->msg_err; ++ goto done; ++ } ++ ++ /* no error */ ++ if (likely(!dev->cmd_err)) { ++ /* Disable the adapter */ ++ i2c_fh_wait_master_not_active(dev); ++ I2c_DisEnable(dev->base); ++ ret = num; ++ goto done; ++ } ++ ++ /* We have an error */ ++ if (dev->cmd_err == DW_IC_ERR_TX_ABRT) ++ { ++ PRINT_DBG("dev->cmd_err == DW_IC_ERR_TX_ABRT\n"); ++ ret = i2c_fh_handle_tx_abort(dev); ++ goto done; ++ } ++ ++ ret = -EIO; ++ ++done: ++ PRINT_DBG("buf: 0x%x\n", dev->msgs[num - 1].buf[0]); ++ mutex_unlock(&dev->lock); ++ ++ return ret; ++} ++ ++static u32 i2c_fh_func(struct i2c_adapter *adap) ++{ ++ return I2C_FUNC_I2C | ++ I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA | ++ I2C_FUNC_SMBUS_I2C_BLOCK; ++} ++ ++static u32 i2c_fh_read_clear_intrbits(struct fh_i2c_dev *dev) ++{ ++ u32 stat; ++ ++ /* ++ * The IC_INTR_STAT register just indicates "enabled" interrupts. ++ * Ths unmasked raw version of interrupt status bits are available ++ * in the IC_RAW_INTR_STAT register. ++ * ++ * That is, ++ * stat = readl(IC_INTR_STAT); ++ * equals to, ++ * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); ++ * ++ * The raw version might be useful for debugging purposes. ++ */ ++ stat = readl(dev->base + DW_IC_INTR_STAT); ++ ++ /* ++ * Do not use the IC_CLR_INTR register to clear interrupts, or ++ * you'll miss some interrupts, triggered during the period from ++ * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). ++ * ++ * Instead, use the separately-prepared IC_CLR_* registers. ++ */ ++ if (stat & DW_IC_INTR_RX_UNDER) ++ I2c_ClrIntr(dev->base,DW_IC_CLR_RX_UNDER); ++ if (stat & DW_IC_INTR_RX_OVER) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_RX_OVER); ++ if (stat & DW_IC_INTR_TX_OVER) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_TX_OVER); ++ if (stat & DW_IC_INTR_RD_REQ) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_RD_REQ); ++ if (stat & DW_IC_INTR_TX_ABRT) { ++ /* ++ * The IC_TX_ABRT_SOURCE register is cleared whenever ++ * the IC_CLR_TX_ABRT is read. Preserve it beforehand. ++ */ ++ dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE); ++ I2c_ClrIntr(dev->base , DW_IC_CLR_TX_ABRT); ++ } ++ if (stat & DW_IC_INTR_RX_DONE) ++ I2c_ClrIntr(dev->base ,DW_IC_CLR_RX_DONE); ++ if (stat & DW_IC_INTR_ACTIVITY) ++ I2c_ClrIntr(dev->base ,DW_IC_CLR_ACTIVITY); ++ if (stat & DW_IC_INTR_STOP_DET) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_STOP_DET); ++ if (stat & DW_IC_INTR_START_DET) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_START_DET); ++ if (stat & DW_IC_INTR_GEN_CALL) ++ I2c_ClrIntr(dev->base , DW_IC_CLR_GEN_CALL); ++ ++ return stat; ++} ++ ++/* ++ * Interrupt service routine. This gets called whenever an I2C interrupt ++ * occurs. ++ */ ++static irqreturn_t i2c_fh_isr(int this_irq, void *dev_id) ++{ ++ struct fh_i2c_dev *dev = dev_id; ++ u32 stat; ++ ++ stat = i2c_fh_read_clear_intrbits(dev); ++ PRINT_DBG("-----------i2c, %s: stat=0x%x\n", __func__, stat); ++ ++ if (stat & DW_IC_INTR_TX_ABRT) ++ { ++ PRINT_DBG("DW_IC_INTR_TX_ABRT\n"); ++ dev->cmd_err |= DW_IC_ERR_TX_ABRT; ++ dev->status = STATUS_IDLE; ++ ++ /* ++ * Anytime TX_ABRT is set, the contents of the tx/rx ++ * buffers are flushed. Make sure to skip them. ++ */ ++ I2c_SetIntrMask( dev->base,DW_IC_INTR_NONE); ++ goto tx_aborted; ++ } ++ ++ if (stat & DW_IC_INTR_RX_FULL) ++ { ++ PRINT_DBG("i2c_fh_read\n"); ++ i2c_fh_read(dev); ++ } ++ ++ if (stat & DW_IC_INTR_TX_EMPTY) ++ { ++ PRINT_DBG("i2c_fh_xfer_msg\n"); ++ i2c_fh_xfer_msg(dev); ++ } ++ ++ /* ++ * No need to modify or disable the interrupt mask here. ++ * i2c_fh_xfer_msg() will take care of it according to ++ * the current transmit status. ++ */ ++ ++tx_aborted: ++ if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) ++ complete(&dev->cmd_complete); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct i2c_algorithm i2c_fh_algo = ++{ ++ .master_xfer = i2c_fh_xfer, ++ .functionality = i2c_fh_func, ++}; ++ ++static int __devinit fh_i2c_probe(struct platform_device *pdev) ++{ ++ struct fh_i2c_dev *dev; ++ struct i2c_adapter *adap; ++ struct resource *mem, *ioarea; ++ int irq, r; ++ char clk_name[32] = {0}; ++ pr_info("I2C driver:\n\tplatform registration... "); ++ ++ /* NOTE: driver uses the static register mapping */ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) ++ { ++ dev_err(&pdev->dev, "no mem resource?\n"); ++ return -EINVAL; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ { ++ dev_err(&pdev->dev, "no irq resource?\n"); ++ return irq; /* -ENXIO */ ++ } ++ ++ ioarea = request_mem_region(mem->start, resource_size(mem), ++ pdev->name); ++ if (!ioarea) ++ { ++ dev_err(&pdev->dev, "I2C region already claimed\n"); ++ return -EBUSY; ++ } ++ ++ dev = kzalloc(sizeof(struct fh_i2c_dev), GFP_KERNEL); ++ if (!dev) ++ { ++ r = -ENOMEM; ++ goto err_release_region; ++ } ++ ++ init_completion(&dev->cmd_complete); ++ mutex_init(&dev->lock); ++ dev->dev = get_device(&pdev->dev); ++ dev->irq = irq; ++ platform_set_drvdata(pdev, dev); ++ ++ snprintf(clk_name, sizeof(clk_name), "i2c%d_clk", pdev->id); ++ dev->clk = clk_get(NULL, clk_name); ++ ++ if (IS_ERR(dev->clk)) ++ { ++ r = -ENODEV; ++ goto err_free_mem; ++ } ++ clk_enable(dev->clk); ++ ++ dev->base = ioremap(mem->start, resource_size(mem)); ++ if (dev->base == NULL) ++ { ++ dev_err(&pdev->dev, "failure mapping io resources\n"); ++ r = -ENOMEM; ++ goto err_unuse_clocks; ++ } ++ { ++ dev->tx_fifo_depth = I2c_GetTxFifoDepth(dev->base); ++ dev->rx_fifo_depth = I2c_GetRxFifoDepth(dev->base); ++ } ++ i2c_fh_init(dev); ++ ++ pr_info("\ttx fifo depth: %d, rx fifo depth: %d\n", dev->tx_fifo_depth, dev->rx_fifo_depth); ++ ++ I2c_SetIntrMask( dev->base,DW_IC_INTR_NONE); /* disable IRQ */ ++ r = request_irq(dev->irq, i2c_fh_isr, IRQF_DISABLED,\ ++ dev_name(&pdev->dev), dev); ++ if (r) ++ { ++ dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); ++ goto err_iounmap; ++ } ++ ++ adap = &dev->adapter; ++ i2c_set_adapdata(adap, dev); ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON; ++ strlcpy(adap->name, "FH I2C adapter", ++ sizeof(adap->name)); ++ adap->algo = &i2c_fh_algo; ++ adap->dev.parent = &pdev->dev; ++ ++ adap->nr = pdev->id; ++ r = i2c_add_numbered_adapter(adap); ++ if (r) { ++ dev_err(&pdev->dev, "failure adding adapter\n"); ++ goto err_free_irq; ++ } ++ ++ pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" ++ "\t\tIO base addr: 0x%p)\n", "I2C", pdev->name, ++ pdev->id, dev->irq, dev->base); ++ ++ return 0; ++ ++err_free_irq: ++ free_irq(dev->irq, dev); ++err_iounmap: ++ iounmap(dev->base); ++err_unuse_clocks: ++ clk_disable(dev->clk); ++ clk_put(dev->clk); ++ dev->clk = NULL; ++err_free_mem: ++ platform_set_drvdata(pdev, NULL); ++ put_device(&pdev->dev); ++ kfree(dev); ++err_release_region: ++ release_mem_region(mem->start, resource_size(mem)); ++ ++ return r; ++} ++ ++static int __devexit fh_i2c_remove(struct platform_device *pdev) ++{ ++ struct fh_i2c_dev *dev = platform_get_drvdata(pdev); ++ struct resource *mem; ++ ++ platform_set_drvdata(pdev, NULL); ++ i2c_del_adapter(&dev->adapter); ++ put_device(&pdev->dev); ++ ++ clk_disable(dev->clk); ++ clk_put(dev->clk); ++ dev->clk = NULL; ++ i2c_fh_wait_master_not_active(dev); ++ writel(0, dev->base + DW_IC_ENABLE); ++ free_irq(dev->irq, dev); ++ kfree(dev); ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(mem->start, resource_size(mem)); ++ return 0; ++} ++ ++static struct platform_driver fh_i2c_driver = ++{ ++ .remove = __devexit_p(fh_i2c_remove), ++ .driver = ++ { ++ .name = "fh_i2c", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init fh_i2c_init_driver(void) ++{ ++ return platform_driver_probe(&fh_i2c_driver, fh_i2c_probe); ++} ++module_init(fh_i2c_init_driver); ++ ++static void __exit fh_i2c_exit_driver(void) ++{ ++ platform_driver_unregister(&fh_i2c_driver); ++} ++module_exit(fh_i2c_exit_driver); ++ ++MODULE_AUTHOR("QIN"); ++MODULE_ALIAS("platform:fh"); ++MODULE_DESCRIPTION("FH I2C bus adapter"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 35464744..6d75ca4f 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -157,6 +157,8 @@ config INTEL_MID_PTI + an Intel Atom (non-netbook) mobile device containing a MIPI + P1149.7 standard implementation. + ++ ++ + config SGI_IOC4 + tristate "SGI IOC4 Base IO support" + depends on PCI +@@ -404,6 +406,87 @@ config EP93XX_PWM + To compile this driver as a module, choose M here: the module will + be called ep93xx_pwm. + ++config FH_DW_I2S ++ tristate "FH DW I2S support" ++ default n ++ ++ ++ ++ ++config FH_PINCTRL ++ tristate "FH Pinctrl support" ++ default n ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called. ++ ++ ++config FH_SADC_V1 ++ depends on ARCH_FULLHAN ++ tristate "FH SADC support(v1 version)" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_sadc. ++ ++ HW para:10bits precision, 8 channels, 5M clk in. ++ one conversion need almost (12/5M *1)second ++ ++config FH_SADC_V11 ++ depends on FH_SADC_V1 && ARCH_FH8856 ++ tristate "FH SADC support(v11 version)" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_sadc. ++ ++ HW para:10bits precision, 8 channels, 5M clk in. ++ one conversion need almost (12/5M *1)second ++ ++config FH_SADC_V2 ++ depends on !FH_SADC_V1 ++ tristate "FH SADC support(v2 version)" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_sadc. ++ ++ HW para:12bits precision, 8 channels, 5M clk in. ++ one conversion need almost (12/5M *1)second ++ ++config FH_SADC_V21 ++ depends on FH_SADC_V2 ++ tristate "FH SADC support(v22 version)" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_sadc. ++ ++ HW para:12bits precision, 8 channels, 5M clk in. ++ one conversion need almost (12/5M *1)second ++ ++config FH_SADC_V22 ++ depends on FH_SADC_V2 ++ tristate "FH SADC support(v22 version)" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_sadc. ++ ++ HW para:12bits precision, 8 channels, 5M clk in. ++ one conversion need almost (12/5M *1)second ++ ++config FH_EFUSE ++ tristate "FH EFUSE support" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_efuse. ++ ++ HW para:60 bytes could be programmed. ++ the "efuse2aes map" is fixed by hardware..EX. 0~4 : aes key0, 5~8 : aes key1. ++ ++config FH_CLK_MISC ++ tristate "FH clk miscdev support" ++ default n ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called. ++ + config DS1682 + tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" + depends on I2C && EXPERIMENTAL +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 5f03172c..bf609f91 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o + 0bj-$(CONFIG_INTEL_MID_PTI) += pti.o + obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o + obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o ++obj-$(CONFIG_ATMEL_ACW) += atmel-acw.o + obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o + obj-$(CONFIG_BMP085) += bmp085.o + obj-$(CONFIG_ICS932S401) += ics932s401.o +@@ -31,6 +32,13 @@ obj-$(CONFIG_ISL29003) += isl29003.o + obj-$(CONFIG_ISL29020) += isl29020.o + obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o + obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o ++obj-$(CONFIG_FH_PINCTRL) += fh_pinctrl_dev.o ++obj-$(CONFIG_FH_DW_I2S) += fh_dw_i2s.o ++obj-$(CONFIG_FH_I2S) += fh_i2s.o ++obj-$(CONFIG_FH_SADC_V1) += fh_sadc.o ++obj-$(CONFIG_FH_SADC_V2) += fh_sadc_v2.o ++obj-$(CONFIG_FH_EFUSE) += fh_efuse.o ++ + obj-$(CONFIG_DS1682) += ds1682.o + obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o + obj-$(CONFIG_C2PORT) += c2port/ +@@ -46,3 +54,5 @@ obj-y += ti-st/ + obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o + obj-y += lis3lv02d/ + obj-y += carma/ ++obj-$(CONFIG_FH_DMAC_MISC) += fh_dma_miscdev.o ++obj-$(CONFIG_FH_CLK_MISC) += fh_clk_miscdev.o +diff --git a/drivers/misc/ac.h b/drivers/misc/ac.h +new file mode 100644 +index 00000000..93531a8d +--- /dev/null ++++ b/drivers/misc/ac.h +@@ -0,0 +1,61 @@ ++#ifndef __AC_H ++#define __AC_H ++ ++/* #define _FHIOWR _IOWR */ ++#define _FHIOWR(x, y, z) y ++ ++#define FH_AUDIO_IOCTL_BASE 'M' ++#define AC_INIT_CAPTURE_MEM _FHIOWR(FH_AUDIO_IOCTL_BASE, 0, int) ++#define AC_INIT_PLAYBACK_MEM _FHIOWR(FH_AUDIO_IOCTL_BASE, 1, int) ++#define AC_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 2, int) ++#define AC_SET_INPUT_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 3, int) ++#define AC_SET_OUTPUT_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 4, int) ++#define AC_AI_EN _FHIOWR(FH_AUDIO_IOCTL_BASE, 5, int) ++#define AC_AO_EN _FHIOWR(FH_AUDIO_IOCTL_BASE, 6, int) ++#define AC_AI_DISABLE _FHIOWR(FH_AUDIO_IOCTL_BASE, 7, int) ++#define AC_AO_DISABLE _FHIOWR(FH_AUDIO_IOCTL_BASE, 8, int) ++#define AC_AI_PAUSE _FHIOWR(FH_AUDIO_IOCTL_BASE, 9, int) ++#define AC_AI_RESUME _FHIOWR(FH_AUDIO_IOCTL_BASE, 10, int) ++#define AC_AO_PAUSE _FHIOWR(FH_AUDIO_IOCTL_BASE, 11, int) ++#define AC_AO_RESUME _FHIOWR(FH_AUDIO_IOCTL_BASE, 12, int) ++#define AC_AI_READ _FHIOWR(FH_AUDIO_IOCTL_BASE, 13, int) ++#define AC_AO_WRITE _FHIOWR(FH_AUDIO_IOCTL_BASE, 14, int) ++#define AC_AI_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 15, int) ++#define AC_AO_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 16, int) ++#define AC_AI_MICIN_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 17, int) ++#define AC_AEC_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 18, int) ++#define AC_NR_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 19, int) ++#define AC_NR2_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 20, int) ++#define AC_AGC_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 21, int) ++#define AC_WORK_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 22, int) ++#define AC_AI_READ_FRAME_EXT _FHIOWR(FH_AUDIO_IOCTL_BASE, 23, int) ++#define AC_AO_SET_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 24, int) ++#define AC_USING_EXTERNAL_CODEC _FHIOWR(FH_AUDIO_IOCTL_BASE, 25, int) ++#define AC_EXT_INTF _FHIOWR(FH_AUDIO_IOCTL_BASE, 100, int) ++ ++enum io_select { ++ mic_in = 0, ++ line_in = 1, ++ speaker_out = 2, ++ line_out = 3, ++}; ++ ++struct fh_audio_cfg_arg { ++ int io_type; ++ int volume; ++ int rate; ++ int frame_bit; ++ int channels; ++ int buffer_size; ++ int period_size; ++ int enc_type; /* encoding type */ ++}; ++ ++ ++struct fh_audio_ai_read_frame_ext { ++ unsigned int len; ++ unsigned char *data; ++ unsigned long long pts; ++}; ++ ++#endif +diff --git a/drivers/misc/fh_clk_miscdev.c b/drivers/misc/fh_clk_miscdev.c +new file mode 100644 +index 00000000..d3ea3bef +--- /dev/null ++++ b/drivers/misc/fh_clk_miscdev.c +@@ -0,0 +1,176 @@ ++#include <linux/miscdevice.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/errno.h> ++#include <linux/printk.h> ++#include <linux/module.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++#include <asm/uaccess.h> ++#include <linux/clk.h> ++ ++#include "fh_clk_miscdev.h" ++ ++//#define FH_CLK_DEBUG ++ ++#if defined(FH_CLK_DEBUG) ++#define PRINT_CLK_DBG(fmt, args...) \ ++ do \ ++ { \ ++ printk("FH_CLK_DEBUG: "); \ ++ printk(fmt, ##args); \ ++ } while (0) ++#else ++#define PRINT_CLK_DBG(fmt, args...) \ ++ do \ ++ { \ ++ } while (0) ++#endif ++ ++static int fh_clk_miscdev_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_clk_miscdev_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++ ++static long fh_clk_miscdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int ret = -ENODEV; ++ struct clk *clk; ++ struct clk_usr uclk; ++ ++ if (unlikely(_IOC_TYPE(cmd) != CLK_IOCTL_MAGIC)) ++ { ++ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n", ++ __func__, _IOC_TYPE(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (unlikely(_IOC_NR(cmd) > CLK_IOCTL_MAXNR)) ++ { ++ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ { ++ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ else if(_IOC_DIR(cmd) & _IOC_WRITE) ++ { ++ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ ++ if(ret) ++ { ++ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -EACCES); ++ return -EACCES; ++ } ++ ++ switch(cmd) ++ { ++ case ENABLE_CLK: ++ if (copy_from_user((void *)&uclk, ++ (void __user *)arg, ++ sizeof(struct clk_usr))) ++ return -EFAULT; ++ clk = clk_get(NULL, uclk.name); ++ if(!IS_ERR(clk)) { ++ clk_enable(clk); ++ ret = 0; ++ } ++ break; ++ case DISABLE_CLK: ++ if (copy_from_user((void *)&uclk, ++ (void __user *)arg, ++ sizeof(struct clk_usr))) ++ return -EFAULT; ++ clk = clk_get(NULL, uclk.name); ++ if (!IS_ERR(clk)) { ++ clk_disable(clk); ++ ret = 0; ++ } ++ break; ++ case SET_CLK_RATE: ++ if (copy_from_user((void *)&uclk, ++ (void __user *)arg, ++ sizeof(struct clk_usr))) ++ return -EFAULT; ++ clk = clk_get(NULL, uclk.name); ++ ret = PTR_ERR(clk); ++ if (!IS_ERR(clk)) ++ ret = clk_set_rate(clk, uclk.frequency); ++ ++ PRINT_CLK_DBG("%s, set clk: %s, rate: %lu\n", ++ __func__, uclk.name, uclk.frequency); ++ break; ++ case GET_CLK_RATE: ++ if (copy_from_user((void *)&uclk, ++ (void __user *)arg, ++ sizeof(struct clk_usr))) ++ return -EFAULT; ++ clk = clk_get(NULL, uclk.name); ++ ret = PTR_ERR(clk); ++ if (!IS_ERR(clk)) { ++ uclk.frequency = clk_get_rate(clk); ++ ret = 0; ++ } ++ PRINT_CLK_DBG("%s, get clk: %s, rate: %lu\n", ++ __func__, uclk.name, uclk.frequency); ++ } ++ ++ ++ return ret; ++} ++ ++static const struct file_operations fh_clk_fops = ++{ ++ .owner = THIS_MODULE, ++ .open = fh_clk_miscdev_open, ++ .release = fh_clk_miscdev_release, ++ .unlocked_ioctl = fh_clk_miscdev_ioctl, ++}; ++ ++static struct miscdevice fh_clk_miscdev = ++{ ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEVICE_NAME, ++ .fops = &fh_clk_fops, ++}; ++ ++int __init fh_clk_miscdev_init(void) ++{ ++ int err; ++ ++ err = misc_register(&fh_clk_miscdev); ++ ++ if(err < 0) ++ { ++ pr_err("%s: ERROR: %s registration failed, ret=%d", ++ __func__, DEVICE_NAME, err); ++ return -ENXIO; ++ } ++ ++ pr_info("CLK misc driver init successfully\n"); ++ return 0; ++} ++ ++ ++static void __exit fh_clk_miscdev_exit(void) ++{ ++ misc_deregister(&fh_clk_miscdev); ++} ++module_init(fh_clk_miscdev_init); ++module_exit(fh_clk_miscdev_exit); ++ ++MODULE_AUTHOR("QIN"); ++MODULE_DESCRIPTION("Misc Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform: FH"); +diff --git a/drivers/misc/fh_clk_miscdev.h b/drivers/misc/fh_clk_miscdev.h +new file mode 100644 +index 00000000..ce405554 +--- /dev/null ++++ b/drivers/misc/fh_clk_miscdev.h +@@ -0,0 +1,10 @@ ++ ++#ifndef FH_CLK_MISCDEV_H_ ++#define FH_CLK_MISCDEV_H_ ++ ++#include <mach/clock.h> ++ ++#define DEVICE_NAME "fh_clk_miscdev" ++ ++ ++#endif /* FH_CLK_MISCDEV_H_ */ +diff --git a/drivers/misc/fh_dma_miscdev.c b/drivers/misc/fh_dma_miscdev.c +new file mode 100644 +index 00000000..7fad61de +--- /dev/null ++++ b/drivers/misc/fh_dma_miscdev.c +@@ -0,0 +1,363 @@ ++#include <linux/miscdevice.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/errno.h> ++#include <linux/printk.h> ++#include <linux/module.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++#include <asm/uaccess.h> ++ ++ ++#include "fh_dma_miscdev.h" ++ ++#define MEMCPY_UNIT (4095 * 4 * 64) //4095 xfer * 32-bit * 64 desc ++ ++//#define FH_DMA_DEBUG ++ ++#ifdef FH_DMA_DEBUG ++#define PRINT_DMA_DBG(fmt, args...) \ ++ do \ ++ { \ ++ printk("FH_DMA_DEBUG: "); \ ++ printk(fmt, ## args); \ ++ } \ ++ while(0) ++#else ++#define PRINT_DMA_DBG(fmt, args...) do { } while (0) ++#endif ++ ++ ++static void fh_dma_callback(void *data) ++{ ++ PRINT_DMA_DBG("dma transfer done, end=%lu\n", jiffies); ++ complete(data); ++} ++ ++static int kick_off_dma(struct dma_chan *channel, unsigned int src_offset, unsigned int dst_offset, unsigned int size) ++{ ++ int ret; ++ struct completion cmp; ++ struct dma_async_tx_descriptor *dma_tx_desc = NULL; ++ struct dma_device *dma_dev = channel->device; ++ dma_cookie_t cookie; ++ unsigned long timeout; ++ unsigned long flag; ++ ++ flag = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP; ++ ++ PRINT_DMA_DBG("try to copy 0x%x bytes: 0x%x --> 0x%x\n", MEMCPY_UNIT, src_offset, dst_offset); ++ ++ dma_tx_desc = dma_dev->device_prep_dma_memcpy(channel, dst_offset, src_offset, size, flag); ++ ++ PRINT_DMA_DBG("device_prep_dma_memcpy end\n"); ++ ++ if(!dma_tx_desc) ++ { ++ pr_err("ERROR: %s, device_prep_dma_memcpy fail\n", __func__); ++ ret = -ENODEV; ++ return ret; ++ } ++ ++ init_completion(&cmp); ++ dma_tx_desc->callback = fh_dma_callback; ++ dma_tx_desc->callback_param = &cmp; ++ PRINT_DMA_DBG("tx_submit start\n"); ++ cookie = dma_tx_desc->tx_submit(dma_tx_desc); ++ PRINT_DMA_DBG("tx_submit end\n"); ++ if (dma_submit_error(cookie)) ++ { ++ pr_err("ERROR: %s, tx_submit fail\n", __func__); ++ ret = -ENODEV; ++ return ret; ++ } ++ PRINT_DMA_DBG("dma_async_issue_pending start\n"); ++ dma_async_issue_pending(channel); ++ PRINT_DMA_DBG("dma_async_issue_pending end, %d\n", DMA_MEMCPY_TIMEOUT); ++ ++ timeout = wait_for_completion_timeout(&cmp, msecs_to_jiffies(DMA_MEMCPY_TIMEOUT)); ++ ++ PRINT_DMA_DBG("wait_for_completion_timeout end, timeout: %lu\n", timeout); ++ ++ if(!timeout) ++ { ++ pr_err("ERROR: %s, dma transfer fail, timeout\n", __func__); ++ ret = -ENODEV; ++ return ret; ++ } ++ ++ ret = dma_async_is_tx_complete(channel, cookie, NULL, NULL); ++ ++ if(ret) ++ { ++ pr_err("ERROR: %s, dma transfer fail, incorrect status: %d\n", __func__, ret); ++ ret = -ENODEV; ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++static int fh_dma_start_transfer(struct dma_chan *channel, struct dma_memcpy* memcpy) ++{ ++ int ret; ++ unsigned int i; ++ ++ for(i=0; i<memcpy->size / MEMCPY_UNIT; i++) ++ { ++ ret = kick_off_dma(channel, memcpy->src_addr_phy + MEMCPY_UNIT*i, memcpy->dst_addr_phy + MEMCPY_UNIT*i, MEMCPY_UNIT); ++ if(ret) ++ { ++ return ret; ++ } ++ } ++ ++ ret = kick_off_dma(channel, memcpy->src_addr_phy + MEMCPY_UNIT*i, memcpy->dst_addr_phy + MEMCPY_UNIT*i, memcpy->size % MEMCPY_UNIT); ++ return ret; ++} ++ ++ ++static bool chan_filter(struct dma_chan *chan, void *param) ++{ ++ struct dma_memcpy* memcpy = param; ++ PRINT_DMA_DBG("chan_filter, channel id: %d\n", memcpy->chan_id); ++ if(memcpy->chan_id < 0) ++ { ++ return false; ++ } ++ ++ if(memcpy->chan_id == chan->chan_id) ++ { ++ return true; ++ } ++ else ++ { ++ return false; ++ } ++ ++} ++ ++static int fh_dma_memcpy(struct dma_memcpy* memcpy) ++{ ++ //fixme: ioctl should be atomic, otherwise channel will be changed. ++ struct dma_chan *dma_channel; ++ dma_cap_mask_t mask; ++ int ret; ++ ++ PRINT_DMA_DBG("fh_dma_memcpy start\n"); ++ PRINT_DMA_DBG("ioctl, memcpy->size: 0x%x\n", memcpy->size); ++ ++ ++ PRINT_DMA_DBG("fh_dma_request_channel start\n"); ++ dma_cap_zero(mask); ++ PRINT_DMA_DBG("dma_cap_zero end\n"); ++ dma_cap_set(DMA_MEMCPY, mask); ++ PRINT_DMA_DBG("dma_cap_set end\n"); ++ ++ dma_channel = dma_request_channel(mask, chan_filter, memcpy); ++ ++ PRINT_DMA_DBG("dma_request_channel finished, channel_addr: 0x%x\n", (u32)dma_channel); ++ ++ if(!dma_channel) ++ { ++ pr_err("ERROR: %s, No Channel Available, channel: %d\n", __func__, memcpy->chan_id); ++ return -EBUSY; ++ } ++ memcpy->chan_id = dma_channel->chan_id; ++ PRINT_DMA_DBG("dma channel name: %s\n", dma_chan_name(dma_channel)); ++ ++ ret = fh_dma_start_transfer(dma_channel, memcpy); ++ ++ if(ret) ++ { ++ pr_err("ERROR: %s, DMA Xfer Failed\n", __func__); ++ } ++ ++ dma_channel->device->device_free_chan_resources(dma_channel); ++ dma_release_channel(dma_channel); ++ ++ return ret; ++} ++ ++static long fh_dma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct dma_memcpy memcpy; ++ ++ ++ if (unlikely(_IOC_TYPE(cmd) != DMA_IOCTL_MAGIC)) ++ { ++ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n", ++ __func__, _IOC_TYPE(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (unlikely(_IOC_NR(cmd) > DMA_IOCTL_MAXNR)) ++ { ++ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ { ++ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ else if(_IOC_DIR(cmd) & _IOC_WRITE) ++ { ++ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ ++ if(ret) ++ { ++ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -EACCES); ++ return -EACCES; ++ } ++ ++ switch(cmd) ++ { ++ ++ case DMA_MEMCOPY: ++ if(copy_from_user((void *)&memcpy, ++ (void __user *)arg, ++ sizeof(struct dma_memcpy))) ++ { ++ return -EFAULT; ++ } ++ ret = fh_dma_memcpy(&memcpy); ++ break; ++ } ++ ++ return ret; ++} ++ ++static int fh_dma_open(struct inode *inode, struct file *file) ++{ ++ PRINT_DMA_DBG("fh_dma_open\n"); ++ return 0; ++} ++ ++static int fh_dma_release(struct inode *inode, struct file *filp) ++{ ++ PRINT_DMA_DBG("fh_dma_release\n"); ++ return 0; ++} ++ ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else ++ { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ ++ seq_printf(sfile, "\nISP Status\n"); ++ seq_printf(sfile, "\nCTRL: \n"); ++ ++#if 0 ++ int i; ++ u32 data; ++ seq_printf(sfile, "ipf reg:\n"); ++ for(i=0; i<10; i++) ++ { ++ data = GET_IPF_REG_V(i*4); ++ seq_printf(sfile, "0x%05x, 0x%08x\n", i*4, data); ++ } ++#endif ++ ++ return 0; ++} ++ ++static const struct seq_operations fh_dma_seq_ops = ++{ ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int isp_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &fh_dma_seq_ops); ++} ++ ++static struct file_operations fh_dma_proc_ops = ++{ ++ .owner = THIS_MODULE, ++ .open = isp_proc_open, ++ .read = seq_read, ++}; ++ ++static const struct file_operations fh_dma_fops = ++{ ++ .owner = THIS_MODULE, ++ .open = fh_dma_open, ++ .release = fh_dma_release, ++ .unlocked_ioctl = fh_dma_ioctl, ++}; ++ ++static struct miscdevice fh_dma_device = ++{ ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEVICE_NAME, ++ .fops = &fh_dma_fops, ++}; ++ ++static int __init fh_dma_init(void) ++{ ++ int ret; ++ struct proc_dir_entry *proc_file; ++ ret = misc_register(&fh_dma_device); ++ ++ if(ret < 0) ++ { ++ pr_err("%s: ERROR: %s registration failed", ++ __func__, DEVICE_NAME); ++ return -ENXIO; ++ } ++ ++ proc_file = create_proc_entry(PROC_FILE, 0644, NULL); ++ ++ if (proc_file) ++ proc_file->proc_fops = &fh_dma_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, DEVICE_NAME); ++ ++ ++ return ret; ++} ++ ++static void __exit fh_dma_exit(void) ++{ ++ remove_proc_entry(PROC_FILE, NULL); ++ misc_deregister(&fh_dma_device); ++} ++module_init(fh_dma_init); ++module_exit(fh_dma_exit); ++ ++MODULE_AUTHOR("QIN"); ++MODULE_DESCRIPTION("Misc Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform: FH"); +diff --git a/drivers/misc/fh_dma_miscdev.h b/drivers/misc/fh_dma_miscdev.h +new file mode 100644 +index 00000000..c294c331 +--- /dev/null ++++ b/drivers/misc/fh_dma_miscdev.h +@@ -0,0 +1,32 @@ ++ ++#ifndef FH_DMA_MISCDEV_H_ ++#define FH_DMA_MISCDEV_H_ ++ ++#include <linux/dmaengine.h> ++ ++ ++#define DEVICE_NAME "fh_dma_misc" ++#define PROC_FILE "driver/dma_misc" ++ ++#define DMA_IOCTL_MAGIC 'd' ++#define RESERVERD _IO(DMA_IOCTL_MAGIC, 0) ++#define REQUEST_CHANNEL _IOWR(DMA_IOCTL_MAGIC, 1, __u32) ++#define DMA_MEMCOPY _IOWR(DMA_IOCTL_MAGIC, 2, __u32) ++ ++#define DMA_IOCTL_MAXNR 14 ++ ++#define DMA_MEMCPY_TIMEOUT 5000 //msec ++ ++struct dma_memcpy ++{ ++ int chan_id; ++ void *src_addr_vir; ++ void *dst_addr_vir; ++ unsigned int size; ++ unsigned int src_addr_phy; ++ unsigned int dst_addr_phy; ++}; ++ ++ ++ ++#endif /* FH_DMA_MISCDEV_H_ */ +diff --git a/drivers/misc/fh_dw_i2s.c b/drivers/misc/fh_dw_i2s.c +new file mode 100644 +index 00000000..b27c41c3 +--- /dev/null ++++ b/drivers/misc/fh_dw_i2s.c +@@ -0,0 +1,1537 @@ ++/**@file ++ * @Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. ++ * @brief ++ * ++ * @author fullhan ++ * @date 2016-7-15 ++ * @version V1.0 ++ * @version V1.1 modify code style ++ * @note: misc audio driver for fh8830 embedded audio codec. ++ * @note History: ++ * @note <author> <time> <version > <desc> ++ * @note ++ * @warning: the codec is fixed to 24 bit, ++ * so remember to move the 24 bit data to 16 bit in ++ * application layer, the next version CPU will sovle this bug. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/irqreturn.h> ++#include <linux/clk.h> ++#include <linux/device.h> ++#include <linux/file.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/miscdevice.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/uaccess.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/slab.h> ++#include <linux/kernel.h> ++#include <linux/interrupt.h> ++#include <linux/types.h> ++#include <linux/poll.h> ++#include <linux/ioctl.h> ++#include <linux/workqueue.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/sched.h> ++#include <mach/fh_dmac.h> ++#include <mach/pmu.h> ++#include <mach/fh_predefined.h> ++#include <mach/chip.h> ++#include <mach/fh_i2s.h> ++ ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++#include "ac.h" ++ ++#define DEVICE_NAME "fh_audio" ++ ++#define NR_DESCS_PER_CHANNEL 64 ++#define FIX_SAMPLE_BIT 32 ++ ++#define AUDIO_DMA_PREALLOC_SIZE (128*1024) ++ ++#define I2S_INTR_RX_AVAILABLE 0x1 ++#define I2S_INTR_RX_OVERRUN 0x2 ++#define I2S_INTR_TX_AVAILABLE 0x10 ++#define I2S_INTR_TX_OVERRUN 0x20 ++ ++#define I2S_REG_IER_OFFSET 0x00 /*i2s enable reg*/ ++#define I2S_REG_IRER_OFFSET 0x04 /*i2s receiver block enable*/ ++#define I2S_REG_ITER_OFFSET 0x08 /*i2s transmitter block*/ ++#define I2S_REG_CER_OFFSET 0x0c /*clk en*/ ++#define I2S_REG_CCR_OFFSET 0x10 /*clk cfg reg*/ ++#define I2S_REG_RXFFR_OFFSET 0x14 /*reset rx fifo reg*/ ++#define I2S_REG_TXFFR_OFFSET 0x18 /*reset tx fifo reg*/ ++#define I2S_REG_LRBR0_OFFSET 0x20 /*left rx/tx buf reg*/ ++#define I2S_REG_RRBR0_OFFSET 0x24 /*right rx/tx buf reg*/ ++#define I2S_REG_RER0_OFFSET 0x28 /*rx en register*/ ++#define I2S_REG_TER0_OFFSET 0x2c /*tx en*/ ++#define I2S_REG_RCR0_OFFSET 0x30 /*rx config*/ ++#define I2S_REG_TCR0_OFFSET 0x34 /*tx config*/ ++#define I2S_REG_ISR0_OFFSET 0x38 /*intt status reg*/ ++#define I2S_REG_IMR0_OFFSET 0x3c /*intt mask reg*/ ++#define I2S_REG_ROR0_OFFSET 0x40 /*rx overrun reg*/ ++#define I2S_REG_TOR0_OFFSET 0x44 /*tx overrun reg*/ ++#define I2S_REG_RFCR0_OFFSET 0x48 /*rx fifo config reg*/ ++#define I2S_REG_TFCR0_OFFSET 0x4c /*tx fifo config reg*/ ++#define I2S_REG_RFF0_OFFSET 0x50 /*rx fifo flush reg*/ ++#define I2S_REG_TFF0_OFFSET 0x54 /*tx fifo flush reg*/ ++ ++#define I2S_REG_RXDMA_OFFSET 0x1c0 /*Receiver Block DMA Register*/ ++#define I2S_REG_RRXDMA_OFFSET 0x1c4 /*Reset Receiver Block DMA Register*/ ++#define I2S_REG_TXDMA_OFFSET 0x1c8 /*Transmitter Block DMA Register*/ ++#define I2S_REG_RTXDMA_OFFSET 0x1cc /*Reset Transmitter Block DMA Register*/ ++ ++#define I2S_REG_DMACR_OFFSET 0x180 /* DMA Control Register */ ++#define I2S_REG_DMATDLR_OFFSET 0x184 ++#define I2S_REG_DMARDLR_OFFSET 0x188 ++ ++#define I2S_DMA_RXEN_BIT 0 ++#define I2S_DMA_TXEN_BIT 1 ++ ++#define I2S_DMA_CAP_CHANNEL 2 ++#define I2S_DMA_PLAY_CHANNEL 3 ++ ++/* #define FH_AUDIO_DEBUG*/ ++#ifdef FH_AUDIO_DEBUG ++#define PRINT_AUDIO_DBG(fmt, args...) \ ++ do { \ ++ printk(KERN_INFO "FH_AUDIO_DEBUG: "); \ ++ printk(fmt, ## args); \ ++ } while (0); ++#else ++#define PRINT_AUDIO_DBG(fmt, args...) do { } while (0) ++#endif ++ ++enum audio_type { ++ capture = 0, playback, ++}; ++ ++enum audio_state { ++ STATE_NORMAL = 0, STATE_INIT, STATE_STOP, STATE_RUN, STATE_PAUSE ++}; ++ ++struct audio_config { ++ int rate; ++ int volume; ++ enum io_select io_type; ++ int frame_bit; ++ int channels; ++ int buffer_size; ++ int period_size; ++ int buffer_bytes; ++ int period_bytes; ++ int start_threshold; ++ int stop_threshold; ++}; ++ ++struct audio_ptr_t { ++ struct audio_config cfg; ++ enum audio_state state; ++ long size; ++ int hw_ptr; ++ int appl_ptr; ++ spinlock_t lock; ++ struct device dev; ++ u8 *area; /*virtual pointer*/ ++ dma_addr_t addr; /*physical address*/ ++ u8 *mmap_addr; ++}; ++ ++struct fh_audio_cfg { ++ struct audio_ptr_t capture; ++ struct audio_ptr_t playback; ++ wait_queue_head_t readqueue; ++ wait_queue_head_t writequeue; ++ struct semaphore sem_capture; ++ struct semaphore sem_playback; ++}; ++ ++struct fh_dma_chan { ++ struct dma_chan *chan; ++ void __iomem *ch_regs; ++ u8 mask; ++ u8 priority; ++ bool paused; ++ bool initialized; ++ spinlock_t lock; ++ /* these other elements are all protected by lock */ ++ unsigned long flags; ++ dma_cookie_t completed; ++ struct list_head active_list; ++ struct list_head queue; ++ struct list_head free_list; ++ struct fh_cyclic_desc *cdesc; ++ unsigned int descs_allocated; ++}; ++ ++struct channel_assign { ++ int capture_channel; ++ int playback_channel; ++}; ++ ++struct audio_dev { ++ struct channel_assign channel_assign; ++ int dma_master; ++ struct fh_audio_cfg audio_config; ++ struct miscdevice fh_audio_miscdev; ++ struct fh_i2s_platform_data *plat_data; ++}; ++ ++static const struct file_operations fh_i2s_fops; ++ ++static struct audio_dev fh_audio_dev = { ++ .channel_assign = { ++ .capture_channel = I2S_DMA_CAP_CHANNEL, ++ .playback_channel = I2S_DMA_PLAY_CHANNEL, ++ }, ++ .dma_master = 1, ++ .fh_audio_miscdev = { ++ .fops = &fh_i2s_fops, ++ .name = DEVICE_NAME, ++ .minor = MISC_DYNAMIC_MINOR, ++ } ++}; ++ ++static struct { ++ spinlock_t lock; ++ unsigned long paddr; ++ void __iomem *vaddr; ++ unsigned long acw_vaddr; ++ struct clk *clk; ++ struct clk *acodec_clk; ++ unsigned long in_use; ++ unsigned long next_heartbeat; ++ struct timer_list timer; ++ int expect_close; ++ int irq; ++} fh_i2s_module; ++ ++static struct infor_record_t ++{ ++ int record_pid; ++ int play_pid; ++} infor_record; ++ ++static struct fh_dma_chan *dma_rx_transfer; ++static struct fh_dma_chan *dma_tx_transfer; ++ ++static struct work_struct playback_wq; ++ ++static struct audio_param_store { ++ int input_volume; ++ enum io_select input_io_type; ++} audio_param_store; ++ ++static void fh_i2s_tx_dma_done(void *arg); ++static void fh_i2s_rx_dma_done(void *arg); ++static bool fh_i2s_dma_chan_filter(struct dma_chan *chan, void *filter_param); ++static void create_proc(void); ++static void remove_proc(void); ++static int config_i2s_clk(u32 rate, u32 bit); ++ ++static void fh_i2s_stop_playback(struct fh_audio_cfg *audio_config) ++{ ++ if (audio_config->playback.state == STATE_INIT) ++ goto free; ++ if (audio_config->playback.state == STATE_STOP) ++ return; ++ audio_config->playback.state = STATE_STOP; ++ clear_bit(I2S_DMA_TXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET); ++ writel(0, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET); ++ fh_dma_cyclic_stop(dma_tx_transfer->chan); ++ fh_dma_cyclic_free(dma_tx_transfer->chan); ++ ++free: ++ up(&audio_config->sem_playback); ++} ++ ++static void fh_i2s_stop_capture(struct fh_audio_cfg *audio_config) ++{ ++ if (audio_config->capture.state == STATE_INIT) ++ goto free; ++ if (audio_config->capture.state == STATE_STOP) ++ return; ++ audio_config->capture.state = STATE_STOP; ++ ++ clear_bit(I2S_DMA_RXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET); ++ writel(0, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET); ++ ++ fh_dma_cyclic_stop(dma_rx_transfer->chan); ++ fh_dma_cyclic_free(dma_rx_transfer->chan); ++ ++free: ++ up(&audio_config->sem_capture); ++} ++ ++static void switch_io_type(enum audio_type type, enum io_select io_type) ++{ ++} ++ ++static int get_param_from_volume(int volume) ++{ ++ int param, max_param, min_param, max_volume; ++ ++ max_volume = 100; ++ if (volume < 0 || volume > max_volume) { ++ printk(KERN_ERR "unsupported input volume\n"); ++ return -EINVAL; ++ } ++ max_param = 63; ++ min_param = 0; ++ param = max_param - (max_volume - volume); ++ if (param <= min_param) ++ param = min_param; ++ return param; ++} ++ ++static inline long bytes_to_frames(int frame_bit, int bytes) ++{ ++ return bytes * 8 / frame_bit; ++} ++ ++static inline long frames_to_bytes(int frame_bit, int frames) ++{ ++ return frames * frame_bit / 8; ++} ++ ++static void switch_input_volume(int volume) ++{ ++} ++ ++static void reset_dma_buff(struct audio_ptr_t *config) ++{ ++ config->appl_ptr = 0; ++ config->hw_ptr = 0; ++} ++ ++static int config_i2s_frame_bit(int bit) ++{ ++ int wss = 0; ++ int wlen = 0; ++ ++ switch (bit) { ++ case 16: ++ wss = 0; ++ wlen = 0b010; ++ break; ++ case 24: ++ wss = 1; ++ wlen = 0b100; ++ break; ++ case 32: ++ wss = 2; ++ wlen = 0b101; ++ break; ++ default: ++ return -EINVAL; ++ break; ++ } ++ ++ /* config sclk cycles (ws_out) */ ++ writel(wss << 3, fh_i2s_module.vaddr + I2S_REG_CCR_OFFSET); ++ ++ writel(wlen, fh_i2s_module.vaddr + I2S_REG_RCR0_OFFSET); ++ writel(wlen, fh_i2s_module.vaddr + I2S_REG_TCR0_OFFSET); ++ return 0; ++} ++ ++static int init_audio(enum audio_type type, struct fh_audio_cfg *audio_config, ++ struct fh_audio_cfg_arg *cfg) ++{ ++ struct audio_ptr_t *config = NULL; ++ int ret = 0; ++ int pid = current->tgid; ++ ++ if (type == capture) { ++ config = &audio_config->capture; ++ init_waitqueue_head(&audio_config->readqueue); ++ } else if (type == playback) { ++ config = &audio_config->playback; ++ init_waitqueue_head(&audio_config->writequeue); ++ } ++ ++ config->cfg.io_type = cfg->io_type; ++ config->cfg.volume = cfg->volume; ++ config->cfg.rate = cfg->rate; ++ config->cfg.channels = cfg->channels; ++ config->cfg.buffer_size = cfg->buffer_size; ++ config->cfg.frame_bit = cfg->frame_bit; ++ config->cfg.period_size = cfg->period_size; ++ config->cfg.buffer_bytes = ++ frames_to_bytes(config->cfg.frame_bit, config->cfg.buffer_size); ++ config->cfg.period_bytes = ++ frames_to_bytes(config->cfg.frame_bit, config->cfg.period_size); ++ config->cfg.start_threshold = config->cfg.buffer_bytes; ++ config->cfg.stop_threshold = config->cfg.buffer_bytes; ++ reset_dma_buff(config); ++ spin_lock_init(&config->lock); ++ audio_param_store.input_io_type = config->cfg.io_type; ++ audio_param_store.input_volume = config->cfg.volume; ++ ++ ret = config_i2s_clk(cfg->rate, cfg->frame_bit); ++ if (ret) { ++ pr_err("config_i2s_clk error %d\n", ret); ++ return ret; ++ } ++ ++ /* * config wrapper work format * */ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET);/*rx en*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET);/*tx en*/ ++ ++ /*set dma fifo size*/ ++ writel(0x1f, fh_i2s_module.vaddr + I2S_REG_DMARDLR_OFFSET); ++ /*set dma fifo size*/ ++ writel(0x1f, fh_i2s_module.vaddr + I2S_REG_DMATDLR_OFFSET); ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_CER_OFFSET);/*en clk*/ ++ ++ if (type == capture) { ++ infor_record.record_pid = pid; ++ audio_config->capture.state = STATE_INIT; ++ } else if (type == playback) { ++ infor_record.play_pid = pid; ++ audio_config->playback.state = STATE_INIT; ++ } ++ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_IER_OFFSET); ++ ++ return 0; ++} ++ ++static int avail_data_len(enum audio_type type, struct fh_audio_cfg *stream) ++{ ++ int delta; ++ ++ if (capture == type) { ++ spin_lock(&stream->capture.lock); ++ delta = stream->capture.hw_ptr - stream->capture.appl_ptr; ++ spin_unlock(&stream->capture.lock); ++ if (delta < 0) ++ delta += stream->capture.size; ++ return delta; ++ } else { ++ spin_lock(&stream->playback.lock); ++ delta = stream->playback.appl_ptr - stream->playback.hw_ptr; ++ spin_unlock(&stream->playback.lock); ++ if (delta <= 0) ++ delta += stream->playback.size; ++ return stream->playback.size - delta; ++ } ++} ++ ++static int fh_audio_close(struct inode *ip, struct file *fp) ++{ ++ struct miscdevice *miscdev = fp->private_data; ++ struct audio_dev ++ *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev); ++ struct fh_audio_cfg *audio_config = &dev->audio_config; ++ int pid; ++ ++ pid = current->tgid; ++ if (infor_record.play_pid == pid) ++ fh_i2s_stop_playback(audio_config); ++ ++ if (infor_record.record_pid == pid) ++ fh_i2s_stop_capture(audio_config); ++ return 0; ++} ++ ++static int register_tx_dma(struct fh_audio_cfg *audio_config) ++{ ++ int ret; ++ struct fh_dma_slave *tx_config; ++ ++ tx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL); ++ if (!tx_config) ++ return -ENOMEM; ++ ++ tx_config->cfg_hi = FHC_CFGH_DST_PER(11); ++ tx_config->dst_msize = FH_DMA_MSIZE_8; ++ tx_config->src_msize = FH_DMA_MSIZE_8; ++ if (audio_config->playback.cfg.frame_bit == 16) ++ tx_config->reg_width = FH_DMA_SLAVE_WIDTH_16BIT; ++ else ++ tx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT; ++ tx_config->fc = FH_DMA_FC_D_M2P; ++ tx_config->tx_reg = (u32)fh_i2s_module.paddr + I2S_REG_TXDMA_OFFSET; ++ tx_config->src_master = 0; ++ tx_config->dst_master = fh_audio_dev.dma_master; ++ ++ dma_tx_transfer->chan->private = tx_config; ++ if ((audio_config->playback.cfg.buffer_bytes ++ < audio_config->playback.cfg.period_bytes) ++ || (audio_config->playback.cfg.buffer_bytes <= 0) ++ || (audio_config->playback.cfg.period_bytes <= 0) ++ || (audio_config->playback.cfg.buffer_bytes ++ / audio_config->playback.cfg.period_bytes ++ > NR_DESCS_PER_CHANNEL)) { ++ printk(KERN_ERR "buffer_size and period_size are invalid\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ dma_tx_transfer->cdesc = fh_dma_cyclic_prep(dma_tx_transfer->chan, ++ audio_config->playback.addr, ++ audio_config->playback.cfg.buffer_bytes, ++ audio_config->playback.cfg.period_bytes, ++ DMA_MEM_TO_DEV); ++ if (IS_ERR(dma_tx_transfer->cdesc)) { ++ printk(KERN_ERR "cyclic desc err %ld\n", ++ PTR_ERR(dma_tx_transfer->cdesc)); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ dma_tx_transfer->cdesc->period_callback = fh_i2s_tx_dma_done; ++ dma_tx_transfer->cdesc->period_callback_param = audio_config; ++ fh_dma_cyclic_start(dma_tx_transfer->chan); ++ kfree(tx_config); ++ /*must set NULL to tell DMA driver that we free the DMA slave*/ ++ dma_tx_transfer->chan->private = NULL; ++ return 0; ++fail: ++ return ret; ++} ++ ++static int register_rx_dma(struct fh_audio_cfg *audio_config) ++{ ++ int ret; ++ struct fh_dma_slave *rx_config; ++ ++ rx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL); ++ if (!rx_config) ++ return -ENOMEM; ++ rx_config->cfg_hi = FHC_CFGH_SRC_PER(10); ++ rx_config->dst_msize = FH_DMA_MSIZE_8; ++ rx_config->src_msize = FH_DMA_MSIZE_8; ++ if (audio_config->capture.cfg.frame_bit == 16) ++ rx_config->reg_width = FH_DMA_SLAVE_WIDTH_16BIT; ++ else ++ rx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT; ++ rx_config->fc = FH_DMA_FC_D_P2M; ++ rx_config->rx_reg = (u32)fh_i2s_module.paddr + I2S_REG_RXDMA_OFFSET; ++ rx_config->src_master = fh_audio_dev.dma_master; ++ rx_config->dst_master = 0; ++ dma_rx_transfer->chan->private = rx_config; ++ if ((audio_config->capture.cfg.buffer_bytes ++ < audio_config->capture.cfg.period_bytes) ++ || (audio_config->capture.cfg.buffer_bytes <= 0) ++ || (audio_config->capture.cfg.period_bytes <= 0) ++ || (audio_config->capture.cfg.buffer_bytes ++ / audio_config->capture.cfg.period_bytes ++ > NR_DESCS_PER_CHANNEL)) { ++ printk(KERN_ERR "buffer_size and period_size are invalid\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ dma_rx_transfer->cdesc = fh_dma_cyclic_prep(dma_rx_transfer->chan, ++ audio_config->capture.addr, ++ audio_config->capture.cfg.buffer_bytes, ++ audio_config->capture.cfg.period_bytes, ++ DMA_DEV_TO_MEM); ++ if (IS_ERR(dma_rx_transfer->cdesc)) { ++ printk(KERN_ERR "cyclic desc err %ld\n", ++ PTR_ERR(dma_rx_transfer->cdesc)); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ dma_rx_transfer->cdesc->period_callback = fh_i2s_rx_dma_done; ++ dma_rx_transfer->cdesc->period_callback_param = audio_config; ++ fh_dma_cyclic_start(dma_rx_transfer->chan); ++ ++ kfree(rx_config); ++ /*must set NULL to tell DMA driver that we free the DMA slave*/ ++ dma_rx_transfer->chan->private = NULL; ++ return 0; ++fail: ++ kfree(rx_config); ++ return ret; ++} ++ ++static void playback_start_wq_handler(struct work_struct *work) ++{ ++ int avail; ++ ++ while (1) { ++ if (STATE_STOP == fh_audio_dev.audio_config.playback.state) ++ return; ++ avail = avail_data_len(playback, &fh_audio_dev.audio_config); ++ if (avail ++ > fh_audio_dev.audio_config.playback.cfg.period_bytes) ++ msleep(20); ++ else { ++ /*enable rx fifo*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET); ++ /*reset dma*/ ++ writel(0x1, fh_i2s_module.vaddr ++ + I2S_REG_RTXDMA_OFFSET); ++ /*reset dma*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_TXFFR_OFFSET); ++ /*reset dma*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET); ++ break; ++ } ++ } ++} ++ ++static int fh_i2s_start_playback(struct fh_audio_cfg *audio_config) ++{ ++ int ret; ++ ++ if (audio_config->playback.state == STATE_RUN) ++ return 0; ++ ++ if (audio_config->playback.cfg.buffer_bytes ++ >= AUDIO_DMA_PREALLOC_SIZE) { ++ pr_info("DMA prealloc buffer is smaller than" ++ "audio_config->buffer_bytes\n"); ++ return -ENOMEM; ++ } ++ memset(audio_config->playback.area, 0, ++ audio_config->playback.cfg.buffer_bytes); ++ audio_config->playback.size = audio_config->playback.cfg.buffer_bytes; ++ audio_config->playback.state = STATE_RUN; ++ ret = register_tx_dma(audio_config); ++ if (ret) ++ return ret; ++ INIT_WORK(&playback_wq, playback_start_wq_handler); ++ schedule_work(&playback_wq); ++ ++ /*reset tx dma*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RTXDMA_OFFSET); ++ /*reset tx fifo*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_TXFFR_OFFSET); ++ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET);/*tx en*/ ++ /*dma en tx*/ ++ set_bit(I2S_DMA_TXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET); ++ ++ return 0; ++} ++ ++static int fh_i2s_start_capture(struct fh_audio_cfg *audio_config) ++{ ++ int ret; ++ ++ if (audio_config->capture.state == STATE_RUN) ++ return 0; ++ ++ if (audio_config->capture.cfg.buffer_bytes >= AUDIO_DMA_PREALLOC_SIZE) { ++ printk( ++ "DMA prealloc buffer is smaller than audio_config->buffer_bytes\n"); ++ return -ENOMEM; ++ } ++ memset(audio_config->capture.area, 0, ++ audio_config->capture.cfg.buffer_bytes); ++ audio_config->capture.size = audio_config->capture.cfg.buffer_bytes; ++ ++ audio_config->capture.state = STATE_RUN; ++ ++ ret = register_rx_dma(audio_config); ++ if (ret) ++ return ret; ++ ++ /*reset rx dma*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RRXDMA_OFFSET); ++ /*reset rx fifo*/ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RXFFR_OFFSET); ++ ++ writel(0x1, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET);/*rx en*/ ++ ++ /*dma en rx*/ ++ set_bit(I2S_DMA_RXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET); ++ ++ return 0; ++} ++ ++static void fh_i2s_rx_dma_done(void *arg) ++{ ++ struct fh_audio_cfg *audio_config; ++ ++ audio_config = (struct fh_audio_cfg *) arg; ++ spin_lock(&audio_config->capture.lock); ++ audio_config->capture.hw_ptr += audio_config->capture.cfg.period_bytes; ++ if (audio_config->capture.hw_ptr > audio_config->capture.size) ++ audio_config->capture.hw_ptr = audio_config->capture.hw_ptr ++ - audio_config->capture.size; ++ spin_unlock(&audio_config->capture.lock); ++ if (waitqueue_active(&audio_config->readqueue)) { ++ int avail = avail_data_len(capture, audio_config); ++ if (avail > audio_config->capture.cfg.period_bytes) ++ wake_up_interruptible(&audio_config->readqueue); ++ } ++ ++} ++ ++static void fh_i2s_tx_dma_done(void *arg) ++{ ++ struct fh_audio_cfg *audio_config; ++ ++ audio_config = (struct fh_audio_cfg *) arg; ++ spin_lock(&audio_config->playback.lock); ++ audio_config->playback.hw_ptr += ++ audio_config->playback.cfg.period_bytes; ++ if (audio_config->playback.hw_ptr > audio_config->playback.size) { ++ audio_config->playback.hw_ptr = audio_config->playback.hw_ptr ++ - audio_config->playback.size; ++ } ++ memset(audio_config->playback.area + audio_config->playback.hw_ptr ++ - audio_config->playback.cfg.period_bytes, 0, ++ audio_config->playback.cfg.period_bytes); ++ spin_unlock(&audio_config->playback.lock); ++ if (waitqueue_active(&audio_config->writequeue)) { ++ int avail = avail_data_len(playback, audio_config); ++ ++ if (avail > audio_config->playback.cfg.period_bytes) ++ wake_up_interruptible(&audio_config->writequeue); ++ } ++} ++ ++static bool fh_i2s_dma_chan_filter(struct dma_chan *chan, ++ void *filter_param) ++{ ++ int dma_channel = *(int *) filter_param; ++ bool ret = false; ++ ++ if (chan->chan_id == dma_channel) ++ ret = true; ++ return ret; ++} ++ ++static int arg_config_support(struct fh_audio_cfg_arg *cfg) ++{ ++ int ret; ++ ++ ret = get_param_from_volume(cfg->volume); ++ if (ret < 0) ++ return -EINVAL; ++ return 0; ++} ++ ++static long fh_audio_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct fh_audio_cfg_arg cfg; ++ struct miscdevice *miscdev = filp->private_data; ++ struct audio_dev *dev = ++ container_of(miscdev, struct audio_dev, fh_audio_miscdev); ++ struct fh_audio_cfg *audio_config = &dev->audio_config; ++ int ret; ++ int value, pid; ++ int __user *p = (int __user *)arg; ++ ++ pid = current->tgid; ++ switch (cmd) { ++ case AC_INIT_CAPTURE_MEM: ++ ++ if (copy_from_user((void *)&cfg, (void __user *)arg, ++ sizeof(struct fh_audio_cfg_arg))) { ++ printk(KERN_ERR "copy err\n"); ++ return -EIO; ++ } ++ if (0 == arg_config_support(&cfg)) { ++ if (down_trylock(&audio_config->sem_capture)) { ++ pr_info("another thread is running capture.\n"); ++ return -EBUSY; ++ } ++ ret = init_audio(capture, audio_config, &cfg); ++ if (ret) { ++ up(&audio_config->sem_capture); ++ return ret; ++ } ++ } else { ++ return -EINVAL; ++ } ++ ++ break; ++ case AC_INIT_PLAYBACK_MEM: ++ if (copy_from_user((void *)&cfg, (void __user *)arg, ++ sizeof(struct fh_audio_cfg_arg))) { ++ printk(KERN_ERR "copy err\n"); ++ return -EIO; ++ } ++ ++ if (0 == arg_config_support(&cfg)) { ++ if (down_trylock(&audio_config->sem_playback)) { ++ printk(KERN_ERR "another thread is running playback.\n"); ++ return -EBUSY; ++ } ++ ret = init_audio(playback, audio_config, &cfg); ++ if (ret) { ++ up(&audio_config->sem_playback); ++ return ret; ++ } ++ } else ++ return -EINVAL; ++ break; ++ case AC_AI_EN: ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ return fh_i2s_start_capture(audio_config); ++ case AC_AO_EN: ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ return fh_i2s_start_playback(audio_config); ++ case AC_SET_VOL: ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ if (get_user(value, p)) ++ return -EFAULT; ++ ret = get_param_from_volume(value); ++ if (ret < 0) ++ return -EINVAL; ++ audio_param_store.input_volume = value; ++ switch_input_volume(audio_param_store.input_volume); ++ break; ++ case AC_SET_INPUT_MODE: ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ if (get_user(value, p)) ++ return -EFAULT; ++ if (value != mic_in && value != line_in) ++ return -EINVAL; ++ audio_param_store.input_io_type = value; ++ switch_io_type(capture, ++ audio_param_store.input_io_type); ++ break; ++ case AC_SET_OUTPUT_MODE: ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ if (get_user(value, p)) ++ return -EFAULT; ++ if (value != speaker_out && value != line_out) ++ return -EINVAL; ++ switch_io_type(playback, value); ++ break; ++ case AC_AI_DISABLE: ++ pr_info("[ac_driver]AC_AI_DISABLE\n"); ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ fh_i2s_stop_capture(audio_config); ++ pr_info(" AC_AI_DISABLE\n"); ++ break; ++ case AC_AO_DISABLE: ++ pr_info("[ac_driver]AC_AO_DISABLE\n"); ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ fh_i2s_stop_playback(audio_config); ++ pr_info(" AC_AO_DISABLE\n"); ++ break; ++ case AC_AI_PAUSE: ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ printk(KERN_INFO "capture pause\n"); ++ audio_config->capture.state = STATE_PAUSE; ++ /*enable rx*/ ++ writel(0, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET); ++ /*rx en*/ ++ writel(0, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET); ++ break; ++ case AC_AI_RESUME: ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ printk(KERN_INFO "capture resume\n"); ++ audio_config->capture.state = STATE_RUN; ++ /*enable rx*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET); ++ /*reset rx dma*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_RRXDMA_OFFSET); ++ /*reset rx fifo*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_RXFFR_OFFSET); ++ /*rx en*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET); ++ break; ++ case AC_AO_PAUSE: ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ audio_config->playback.state = STATE_PAUSE; ++ writel(0, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET); ++ writel(0, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET); ++ printk(KERN_INFO "playback pause\n"); ++ break; ++ case AC_AO_RESUME: ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ printk(KERN_INFO "playback resume\n"); ++ audio_config->playback.state = STATE_RUN; ++ /*enable tx*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET); ++ /*reset tx dma*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_RTXDMA_OFFSET); ++ /*reset tx fifo*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_TXFFR_OFFSET); ++ /*tx en*/ ++ writel(1, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET); ++ break; ++ case AC_AI_SET_VOL: ++ case AC_AO_SET_VOL: ++ case AC_AI_MICIN_SET_VOL: ++ return 0; ++ ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int fh_audio_open(struct inode *ip, struct file *fp) ++{ ++ ++ fp->private_data = &fh_audio_dev.fh_audio_miscdev; ++ return 0; ++} ++ ++static u32 fh_audio_poll(struct file *filp, poll_table *wait) ++{ ++ struct miscdevice *miscdev = filp->private_data; ++ struct audio_dev ++ *dev = container_of(miscdev, struct audio_dev, ++ fh_audio_miscdev); ++ struct fh_audio_cfg *audio_config = &dev->audio_config; ++ u32 mask = 0; ++ long avail; ++ if (STATE_RUN == audio_config->capture.state) { ++ poll_wait(filp, &audio_config->readqueue, wait); ++ avail = avail_data_len(capture, audio_config); ++ if (avail > audio_config->capture.cfg.period_bytes) ++ mask |= POLLIN | POLLRDNORM; ++ } ++ if (STATE_RUN == audio_config->playback.state) { ++ poll_wait(filp, &audio_config->writequeue, wait); ++ avail = avail_data_len(playback, audio_config); ++ if (avail > audio_config->playback.cfg.period_bytes) ++ mask |= POLLOUT | POLLWRNORM; ++ } ++ return mask; ++} ++ ++static int fh_audio_read(struct file *filp, char __user *buf, ++ size_t len, loff_t *off) ++{ ++ int ret; ++ struct miscdevice *miscdev = filp->private_data; ++ struct audio_dev *dev = container_of(miscdev, struct audio_dev, ++ fh_audio_miscdev); ++ struct fh_audio_cfg *audio_config = &dev->audio_config; ++ int after, left; ++ int pid, avail; ++ ++ pid = current->tgid; ++ if (infor_record.record_pid != pid) ++ return -EBUSY; ++ ++ /* wait for enough data*/ ++ ret = wait_event_interruptible_timeout(audio_config->readqueue, ++ avail_data_len(capture, audio_config) > ++ audio_config->capture.cfg.period_bytes, ++ msecs_to_jiffies(5000)); ++ ++ len -= len % (audio_config->capture.cfg.frame_bit / 8 * 2); ++ ++ avail = avail_data_len(capture, audio_config); ++ if (avail > len) ++ avail = len; ++ after = avail + audio_config->capture.appl_ptr; ++ if (after > audio_config->capture.size) { ++ left = avail - (audio_config->capture.size ++ - audio_config->capture.appl_ptr); ++ ret = copy_to_user(buf, audio_config->capture.area ++ + audio_config->capture.appl_ptr, ++ audio_config->capture.size ++ - audio_config->capture.appl_ptr); ++ ret = copy_to_user(buf+audio_config->capture.size ++ -audio_config->capture.appl_ptr, ++ audio_config->capture.area, left); ++ spin_lock(&audio_config->capture.lock); ++ audio_config->capture.appl_ptr = left; ++ spin_unlock(&audio_config->capture.lock); ++ } else { ++ ret = copy_to_user(buf, ++ audio_config->capture.area+audio_config->capture.appl_ptr, ++ avail); ++ spin_lock(&audio_config->capture.lock); ++ audio_config->capture.appl_ptr += avail; ++ spin_unlock(&audio_config->capture.lock); ++ } ++ ++ return avail; ++} ++ ++static int fh_audio_write(struct file *filp, const char __user *buf, ++ size_t len, loff_t *off) ++{ ++ struct miscdevice *miscdev = filp->private_data; ++ struct audio_dev *dev = container_of(miscdev, struct audio_dev, ++ fh_audio_miscdev); ++ struct fh_audio_cfg *audio_config = &dev->audio_config; ++ int ret; ++ int after, left; ++ int pid, avail; ++ ++ pid = current->tgid; ++ if (infor_record.play_pid != pid) ++ return -EBUSY; ++ ++ /* wait for enough data*/ ++ ret = wait_event_interruptible_timeout(audio_config->writequeue, ++ avail_data_len(playback, audio_config) > ++ audio_config->playback.cfg.period_bytes, ++ msecs_to_jiffies(5000)); ++ ++ len -= len % (audio_config->playback.cfg.frame_bit / 8 * 2); ++ ++ avail = avail_data_len(playback, audio_config); ++ if (0 == avail) ++ return 0; ++ if (avail > len) ++ avail = len; ++ after = avail+audio_config->playback.appl_ptr; ++ if (after > audio_config->playback.size) { ++ left = avail - (audio_config->playback.size- ++ audio_config->playback.appl_ptr); ++ ret = copy_from_user(audio_config->playback.area ++ + audio_config->playback.appl_ptr, ++ buf, audio_config->playback.size ++ - audio_config->playback.appl_ptr); ++ ret = copy_from_user(audio_config->playback.area, ++ buf+audio_config->playback.size ++ - audio_config->playback.appl_ptr, left); ++ spin_lock(&audio_config->playback.lock); ++ audio_config->playback.appl_ptr = left; ++ spin_unlock(&audio_config->playback.lock); ++ } else { ++ ret = copy_from_user(audio_config->playback.area ++ + audio_config->playback.appl_ptr, buf, avail); ++ spin_lock(&audio_config->playback.lock); ++ audio_config->playback.appl_ptr += avail; ++ spin_unlock(&audio_config->playback.lock); ++ } ++ ++ return avail; ++} ++ ++static irqreturn_t fh_audio_interrupt(int irq, void *dev_id) ++{ ++ u32 interrupts; ++ struct fh_audio_cfg *audio_config = &fh_audio_dev.audio_config; ++ ++ interrupts = readl(fh_i2s_module.vaddr + I2S_REG_ISR0_OFFSET); ++ ++ PRINT_AUDIO_DBG("interrupts: 0x%x\n", interrupts); ++ ++ if (interrupts & I2S_INTR_RX_AVAILABLE) { ++ fh_i2s_stop_capture(audio_config); ++ fh_i2s_start_capture(audio_config); ++ PRINT_AUDIO_DBG("I2S_INTR_RX_AVAILABLE\n"); ++ } ++ ++ if (interrupts & I2S_INTR_RX_OVERRUN) { ++ if (audio_config->capture.state == STATE_RUN) { ++ fh_i2s_stop_capture(audio_config); ++ fh_i2s_start_capture(audio_config); ++ } else { ++ /* reset rx fifo*/ ++ } ++ PRINT_AUDIO_DBG("I2S_INTR_RX_OVERRUN\n"); ++ } ++ ++ if (interrupts & I2S_INTR_TX_AVAILABLE) { ++ fh_i2s_stop_playback(audio_config); ++ fh_i2s_start_playback(audio_config); ++ PRINT_AUDIO_DBG("I2S_INTR_TX_AVAILABLE\n"); ++ } ++ ++ if (interrupts & I2S_INTR_TX_OVERRUN) { ++ fh_i2s_stop_playback(audio_config); ++ fh_i2s_start_playback(audio_config); ++ PRINT_AUDIO_DBG("I2S_INTR_TX_OVERRUN\n"); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct file_operations fh_i2s_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = fh_audio_ioctl, ++ .release = fh_audio_close, ++ .open = fh_audio_open, ++ .poll = fh_audio_poll, ++ .read = fh_audio_read, ++ .write = fh_audio_write, ++ ++}; ++ ++#define FREQ_12_288_MHz 12288000 ++#define FREQ_11_2896_MHz 11289600 ++ ++static int config_pllvco_freq(u32 freq) ++{ ++ u32 addr = fh_i2s_module.acw_vaddr; ++ if (addr == 0) { ++ pr_err("acw_vaddr is null\n"); ++ return -EFAULT; ++ } ++ if (freq == FREQ_12_288_MHz) { ++ /* config PLLVCO to 12.288M */ ++ writel(0x03, addr + 0xac); ++ msleep(20); ++ writel(0x07, addr + 0xb0); ++ writel(0x0f, addr + 0xb4); ++ writel(0x07, addr + 0xb8); ++ writel(0x31, addr + 0xbc); ++ writel(0x26, addr + 0xc0); ++ writel(0xe9, addr + 0xc4); ++ } else if (freq == FREQ_11_2896_MHz) { ++ /* config PLLVCO to 11.2896M */ ++ writel(0x03, addr + 0xac); ++ msleep(20); ++ writel(0x06, addr + 0xb0); ++ writel(0x1f, addr + 0xb4); ++ writel(0x0f, addr + 0xb8); ++ writel(0x86, addr + 0xbc); ++ writel(0xc2, addr + 0xc0); ++ writel(0x26, addr + 0xc4); ++ } else { ++ pr_err("unsupport freq %d\n", freq); ++ return -EINVAL; ++ } ++ ++ writel(0x00, addr + 0x9c); ++ writel(0x21, addr + 0xc8); ++ writel(0x07, addr + 0xcc); ++ writel(0x05, addr + 0xd0); ++ writel(0x02, addr + 0x8c); ++ writel(0x10, addr + 0xa0); ++ ++ return 0; ++} ++ ++static int config_i2s_clk(u32 rate, u32 bit) ++{ ++ u32 ret, freq, div; ++ struct fh_i2s_platform_data *pd = fh_audio_dev.plat_data; ++ ++ if (rate % 8000 == 0) { ++ freq = FREQ_12_288_MHz; ++ } else if (rate % 22050 == 0) { ++ freq = FREQ_11_2896_MHz; ++ } else { ++ pr_err("unsupport rate %d\n", rate); ++ return -EINVAL; ++ } ++ ++ ret = config_pllvco_freq(freq); ++ if (ret) { ++ pr_err("config_pllvco_freq err %d\n", ret); ++ return ret; ++ } ++ ++ div = freq / rate / bit / 2; ++ ++ if (div % 4 != 0 || freq % (rate*bit*2) != 0) { ++ pr_err("unsupport rate %d and bit %d\n", rate, bit); ++ return -EINVAL; ++ } ++ ++ pr_debug("freq %d, rate %d, bit %d, div %d\n", freq, rate, bit, div); ++ ++ if (pd->clk_config) ++ ret = pd->clk_config((div - 1) << 8 | 0x03); ++ else { ++ pr_err("pd->clk_config is invalid"); ++ ret = -EINVAL; ++ } ++ ++ ret = config_i2s_frame_bit(bit); ++ if (ret) { ++ pr_err("config_i2s_frame_bit err %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int fh_i2s_drv_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ int irq; ++ u32 acw_virt_addr = 0; ++ ++ struct resource *res_mem = ++ platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct resource *res_irq = ++ platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ ++ fh_audio_dev.plat_data = ++ (struct fh_i2s_platform_data *)pdev->dev.platform_data; ++ ++ if (res_mem) { ++ fh_i2s_module.paddr = res_mem->start; ++ fh_i2s_module.vaddr = devm_ioremap(&pdev->dev, res_mem->start, ++ resource_size(res_mem)); ++ } ++ ++ if (!fh_audio_dev.plat_data) { ++ dev_err(&pdev->dev, "plat_data not configured\n"); ++ ret = -EINVAL; ++ goto out_return; ++ } ++ ++ fh_audio_dev.channel_assign.capture_channel = ++ fh_audio_dev.plat_data->dma_capture_channel; ++ fh_audio_dev.channel_assign.playback_channel = ++ fh_audio_dev.plat_data->dma_playback_channel; ++ fh_audio_dev.dma_master = fh_audio_dev.plat_data->dma_master; ++ ++ if (!fh_i2s_module.vaddr || !fh_i2s_module.paddr) { ++ dev_err(&pdev->dev, "get mem resource error\n"); ++ ret = -ENOMEM; ++ goto out_return; ++ } ++ ++ if (!res_irq) { ++ pr_err("%s: getting resource failed" ++ "cannot get IORESOURCE_IRQ\n", __func__); ++ ret = -ENXIO; ++ goto out_return; ++ } ++ ++ spin_lock_init(&fh_i2s_module.lock); ++ ++ ret = misc_register(&fh_audio_dev.fh_audio_miscdev); ++ ++ if (ret) ++ goto out_return; ++ ++ irq = res_irq->start; ++ if (!irq) { ++ dev_err(&pdev->dev, "%s: cannot get irq\n", __func__); ++ ret = -ENXIO; ++ goto out_return; ++ } ++ ++ fh_i2s_module.irq = irq; ++ ++ ret = devm_request_irq(&pdev->dev, irq, fh_audio_interrupt, IRQF_SHARED, ++ DEVICE_NAME, &fh_i2s_module); ++ ++ if (ret) ++ goto out_return; ++ ++ acw_virt_addr = (unsigned int)devm_ioremap(&pdev->dev, ++ ACW_REG_BASE, SZ_4K); ++ if (!acw_virt_addr) { ++ dev_err(&pdev->dev, "cannot get acw_virt_addr\n"); ++ ret = -ENOMEM; ++ goto out_free_irq; ++ } ++ fh_i2s_module.acw_vaddr = acw_virt_addr; ++ ++ fh_i2s_module.clk = clk_get(NULL, "i2s_clk"); ++ if (IS_ERR(fh_i2s_module.clk)) { ++ ret = PTR_ERR(fh_i2s_module.clk); ++ goto out_free_irq; ++ } else { ++ clk_enable(fh_i2s_module.clk); ++ } ++ ++ if (fh_audio_dev.plat_data->acodec_clk_name) { ++ char *clk_name = fh_audio_dev.plat_data->acodec_clk_name; ++ ++ fh_i2s_module.acodec_clk = clk_get(NULL, clk_name); ++ if (IS_ERR(fh_i2s_module.acodec_clk)) ++ dev_err(&pdev->dev, "cannot find clk: %s\n", clk_name); ++ else ++ clk_enable(fh_i2s_module.acodec_clk); ++ } ++ ++ dev_info(&pdev->dev, "FH DW I2S Driver\n"); ++ return 0; ++ ++out_free_irq: ++ devm_free_irq(&pdev->dev, irq, &fh_i2s_module); ++out_return: ++ dev_err(&pdev->dev, "%s failed\n", __func__); ++ return ret; ++} ++ ++static int fh_i2s_drv_remove(struct platform_device *pdev) ++{ ++ misc_deregister(&fh_audio_dev.fh_audio_miscdev); ++ ++ devm_free_irq(&pdev->dev, fh_i2s_module.irq, &fh_i2s_module); ++ ++ if (fh_i2s_module.clk) { ++ clk_disable(fh_i2s_module.clk); ++ clk_put(fh_i2s_module.clk); ++ } ++ if (fh_i2s_module.acodec_clk) { ++ clk_disable(fh_i2s_module.acodec_clk); ++ clk_put(fh_i2s_module.acodec_clk); ++ } ++ dev_info(&pdev->dev, "FH DW I2S Driver Removed\n"); ++ return 0; ++} ++ ++static struct platform_driver fh_audio_driver = { ++ .probe = fh_i2s_drv_probe, ++ .remove = fh_i2s_drv_remove, ++ .driver = { ++ .name = DEVICE_NAME, ++ .owner = THIS_MODULE, ++ } ++}; ++ ++static int audio_prealloc_dma_buffer(struct fh_audio_cfg *audio_config) ++{ ++ int pg; ++ gfp_t gfp_flags; ++ pg = get_order(AUDIO_DMA_PREALLOC_SIZE); ++ gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN; ++ audio_config->capture.dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ audio_config->capture.area = dma_alloc_coherent( ++ &audio_config->capture.dev, PAGE_SIZE << pg, ++ &audio_config->capture.addr, gfp_flags); ++ if (!audio_config->capture.area) { ++ printk(KERN_ERR"no enough mem for capture buffer alloc\n"); ++ return -1; ++ } ++ audio_config->playback.dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ audio_config->playback.area = dma_alloc_coherent( ++ &audio_config->playback.dev, PAGE_SIZE << pg, ++ &audio_config->playback.addr, gfp_flags); ++ if (!audio_config->playback.area) { ++ printk(KERN_ERR"no enough mem for playback buffer alloc\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static void audio_free_prealloc_dma_buffer(struct fh_audio_cfg *audio_config) ++{ ++ int pg; ++ pg = get_order(AUDIO_DMA_PREALLOC_SIZE); ++ dma_free_coherent(&audio_config->capture.dev, PAGE_SIZE << pg, ++ audio_config->capture.area, audio_config->capture.addr); ++ dma_free_coherent(&audio_config->playback.dev, PAGE_SIZE << pg, ++ audio_config->playback.area, ++ audio_config->playback.addr); ++} ++ ++static void init_audio_mutex(struct fh_audio_cfg *audio_config) ++{ ++ sema_init(&audio_config->sem_capture, 1); ++ sema_init(&audio_config->sem_playback, 1); ++} ++ ++static int audio_request_dma_channel(void) ++{ ++ dma_cap_mask_t mask; ++ ++ dma_rx_transfer = kzalloc(sizeof(struct fh_dma_chan), GFP_KERNEL); ++ if (!dma_rx_transfer) { ++ printk(KERN_ERR"alloc dma_rx_transfer failed\n"); ++ goto mem_fail; ++ } ++ ++ dma_tx_transfer = kzalloc(sizeof(struct fh_dma_chan), GFP_KERNEL); ++ if (!dma_tx_transfer) { ++ printk(KERN_ERR"alloc dma_tx_transfer failed\n"); ++ goto mem_fail; ++ } ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_rx_transfer->chan = dma_request_channel(mask, ++ fh_i2s_dma_chan_filter, ++ &fh_audio_dev.channel_assign.capture_channel); ++ if (!dma_rx_transfer->chan) { ++ printk(KERN_ERR"request audio rx dma channel failedx\n"); ++ goto channel_fail; ++ } ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_tx_transfer->chan = dma_request_channel(mask, ++ fh_i2s_dma_chan_filter, ++ &fh_audio_dev.channel_assign.playback_channel); ++ if (!dma_tx_transfer->chan) { ++ printk(KERN_ERR"request tx dma channel failed\n"); ++ goto channel_fail; ++ } ++ ++ return 0; ++channel_fail: ++ if (dma_rx_transfer->chan) { ++ dma_release_channel(dma_rx_transfer->chan); ++ dma_rx_transfer->chan = NULL; ++ } ++ if (dma_tx_transfer->chan) { ++ dma_release_channel(dma_tx_transfer->chan); ++ dma_tx_transfer->chan = NULL; ++ } ++ ++mem_fail: ++ if (dma_rx_transfer != NULL) { ++ kfree(dma_rx_transfer); ++ dma_rx_transfer = NULL; ++ } ++ if (dma_tx_transfer != NULL) { ++ kfree(dma_tx_transfer); ++ dma_tx_transfer = NULL; ++ } ++ ++ return -EFAULT; ++} ++ ++static void audio_release_dma_channel(void) ++{ ++ /*release audio tx dma channel*/ ++ if (dma_tx_transfer != NULL) { ++ if (dma_tx_transfer->chan) { ++ dma_release_channel(dma_tx_transfer->chan); ++ dma_tx_transfer->chan = NULL; ++ } ++ kfree(dma_tx_transfer); ++ dma_tx_transfer = NULL; ++ } ++ ++ /*release audio rx dma channel*/ ++ if (dma_rx_transfer != NULL) { ++ if (dma_rx_transfer->chan) { ++ dma_release_channel(dma_rx_transfer->chan); ++ dma_rx_transfer->chan = NULL; ++ } ++ ++ kfree(dma_rx_transfer); ++ dma_rx_transfer = NULL; ++ } ++} ++ ++static int __init fh_audio_init(void) ++{ ++ int ret = 0; ++ ++ create_proc(); ++ init_audio_mutex(&fh_audio_dev.audio_config); ++ ret = platform_driver_register(&fh_audio_driver); ++ if (ret) ++ goto failed; ++ ret = audio_prealloc_dma_buffer(&fh_audio_dev.audio_config); ++ if (ret) ++ goto unregister_driver; ++ ret = audio_request_dma_channel(); ++ if (ret) ++ goto free_dma_buffer; ++ ++ return 0; ++ ++free_dma_buffer: ++ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config); ++unregister_driver: ++ platform_driver_unregister(&fh_audio_driver); ++failed: ++ remove_proc(); ++ pr_err("%s failed\n", __func__); ++ return ret; ++} ++module_init(fh_audio_init); ++ ++static void __exit fh_audio_exit(void) ++{ ++ remove_proc(); ++ audio_release_dma_channel(); ++ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config); ++ platform_driver_unregister(&fh_audio_driver); ++} ++module_exit(fh_audio_exit); ++ ++MODULE_AUTHOR("Fullhan"); ++MODULE_DESCRIPTION("FH_DW_I2S"); ++MODULE_LICENSE("GPL"); ++ ++/****************************debug proc*****************************/ ++#include <linux/proc_fs.h> ++ ++#define PROC_NAME "driver/"DEVICE_NAME ++static struct proc_dir_entry *proc_file; ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ int i; ++ u32 data; ++ ++ if (fh_i2s_module.vaddr == NULL) ++ seq_printf(sfile, "reg is null\n"); ++ else { ++ for (i = 0; i <= 0x20; i += 4) { ++ data = readl(fh_i2s_module.vaddr + i); ++ seq_printf(sfile, "0x%02x reg = 0x%x\n", i, data); ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct seq_operations fh_dwi2s_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &fh_dwi2s_seq_ops); ++} ++ ++static const struct file_operations fh_dwi2s_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = proc_open, ++ .read = seq_read, ++}; ++ ++static void create_proc(void) ++{ ++ proc_file = proc_create(PROC_NAME, 0644, NULL, &fh_dwi2s_proc_ops); ++ ++ if (proc_file == NULL) ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, DEVICE_NAME); ++ ++} ++ ++static void remove_proc(void) ++{ ++ remove_proc_entry(PROC_NAME, NULL); ++} +diff --git a/drivers/misc/fh_efuse.c b/drivers/misc/fh_efuse.c +new file mode 100644 +index 00000000..e3ff972a +--- /dev/null ++++ b/drivers/misc/fh_efuse.c +@@ -0,0 +1,613 @@ ++/* ++ * fh_efuse.c ++ * ++ * Created on: Mar 13, 2015 ++ * Author: duobao ++ */ ++#include <linux/uaccess.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++/***************************************************************************** ++ * Include Section ++ * add all #include here ++ *****************************************************************************/ ++#include "fh_efuse.h" ++#include <mach/fh_efuse_plat.h> ++ ++/***************************************************************************** ++ * Define section ++ * add all #define here ++ *****************************************************************************/ ++ ++#define wrap_readl(wrap, name) \ ++ __raw_readl(&(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define wrap_writel(wrap, name, val) \ ++ __raw_writel((val), &(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define wrap_readw(wrap, name) \ ++ __raw_readw(&(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define wrap_writew(wrap, name, val) \ ++ __raw_writew((val), &(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define wrap_readb(wrap, name) \ ++ __raw_readb(&(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define wrap_writeb(wrap, name, val) \ ++ __raw_writeb((val), &(((struct wrap_efuse_reg *)wrap->regs)->name)) ++ ++#define FH_EFUSE_PLAT_DEVICE_NAME "fh_efuse" ++#define FH_EFUSE_MISC_DEVICE_NAME "fh_efuse" ++#define FH_EFUSE_MISC_DEVICE_NODE_NAME "fh_efuse_node" ++#define EFUSE_HW_BUFFER_POS (4) ++/**************************************************************************** ++ * ADT section ++ * add definition of user defined Data Type ++ * that only be used in this file here ++ ***************************************************************************/ ++ ++struct wrap_efuse_reg { ++ u32 efuse_cmd; /*0x0*/ ++ u32 efuse_config; /*0x4*/ ++ u32 efuse_match_key; /*0x8*/ ++ u32 efuse_timing0; /*0xc*/ ++ u32 efuse_timing1; /*0x10*/ ++ u32 efuse_timing2; /*0x14*/ ++ u32 efuse_timing3; /*0x18*/ ++ u32 efuse_timing4; /*0x1c*/ ++ u32 efuse_timing5; /*0x20*/ ++ u32 efuse_timing6; /*0x24*/ ++ u32 efuse_dout; /*0x28*/ ++ u32 efuse_status0; /*0x2c*/ ++ u32 efuse_status1; /*0x30*/ ++ u32 efuse_status2; /*0x34*/ ++ u32 efuse_status3; /*0x38*/ ++ u32 efuse_status4; /*0x3c*/ ++ u32 efuse_mem_info; ++}; ++ ++ ++ ++ ++enum { ++ CMD_TRANS_AESKEY = 4, ++ CMD_WFLGA_AUTO = 8, ++}; ++ ++struct wrap_efuse_obj s_efuse_obj = {0}; ++ ++#define EFUSE_MAX_ENTRY 60 ++ ++ ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Global variables section - Exported ++ * add declaration of global variables that will be exported here ++ * e.g. ++ * int8_t foo; ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++static int fh_efuse_open(struct inode *inode, struct file *file); ++static int fh_efuse_release(struct inode *inode, struct file *filp); ++static long fh_efuse_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg); ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++ ++static const struct file_operations fh_efuse_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_efuse_open, ++ .release = fh_efuse_release, ++ .unlocked_ioctl = fh_efuse_ioctl, ++}; ++ ++static struct miscdevice fh_efuse_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = FH_EFUSE_MISC_DEVICE_NAME, ++ /*.nodename = FH_EFUSE_MISC_DEVICE_NODE_NAME,*/ ++ .fops = &fh_efuse_fops, ++}; ++ ++static int fh_efuse_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_efuse_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++void efuse_detect_complete(struct wrap_efuse_obj *obj, int pos) ++{ ++ unsigned int rdata; ++ unsigned int time = 0; ++ /*printk("efuse wait pos %x...\n",pos);*/ ++ do { ++ time++; ++ rdata = wrap_readl(obj, efuse_status0); ++ if (time > 1000) { ++ printk("[efuse]:detect time out...pos: 0x%x\n", pos); ++ return; ++ } ++ udelay(10); ++ } while ((rdata&(1<<pos)) != 1<<pos); ++ /*printk("efuse wait pos done...\n",pos);*/ ++ udelay(10); ++} ++ ++void auto_check_efuse_pro_bits(struct wrap_efuse_obj *obj, u32 *buff) ++{ ++ /*first set auto check cmd*/ ++ wrap_writel(obj, efuse_cmd, CMD_WFLGA_AUTO); ++ efuse_detect_complete(obj, 8); ++ /* ++ mdelay(300); ++ read status from hw status ++ bit 1 means could be writen.... ++ */ ++ buff[0] = wrap_readl(obj, efuse_status1); ++ buff[1] = wrap_readl(obj, efuse_status2); ++} ++ ++void open_efuse_power(struct wrap_efuse_obj *obj) ++{ ++ unsigned int data; ++ data = wrap_readl(obj, efuse_config); ++ data |= 1<<27; ++ data = wrap_writel(obj, efuse_config, data); ++} ++ ++void efuse_buffer_set(struct wrap_efuse_obj *obj, unsigned int value) ++{ ++ unsigned int data; ++ data = wrap_readl(obj, efuse_config); ++ data &= ~(1 << EFUSE_HW_BUFFER_POS); ++ data |= value << EFUSE_HW_BUFFER_POS; ++ data = wrap_writel(obj, efuse_config, data); ++} ++ ++void efuse_write_key_byte(struct wrap_efuse_obj *obj, u32 entry, u8 data) ++{ ++ u32 temp = 0; ++ temp = (u32)data; ++ /*0~255*/ ++ temp &= ~0xffffff00; ++ temp <<= 12; ++ /*0~63*/ ++ entry &= 0x3f; ++ temp |= (entry<<4) | (0x02); ++ /* ++ printk("efuse write entry: %x,data: %x\n",entry,data); ++ ++ printk("efuse write data :%x\n",temp); ++ wrap_writel(obj,efuse_cmd,(data<<12) + (entry<<4) + (0x02)); ++ */ ++ wrap_writel(obj, efuse_cmd, temp); ++ efuse_detect_complete(obj, 2); ++} ++ ++void efuse_load_usrcmd(struct wrap_efuse_obj *obj) ++{ ++ wrap_writel(obj, efuse_cmd, 1); ++ efuse_detect_complete(obj, 1); ++} ++ ++void refresh_efuse(struct wrap_efuse_obj *obj) ++{ ++ wrap_writel(obj, efuse_cmd, CMD_WFLGA_AUTO); ++ efuse_detect_complete(obj, 8); ++ efuse_load_usrcmd(obj); ++} ++ ++void efuse_check_map_para(unsigned int size, struct ex_key_map *p_key_map) ++{ ++ int loop; ++ if (size > MAX_EX_KEY_MAP_SIZE) { ++ printk(KERN_ERR "%s :: size : %d > max size : %d\n", ++ __func__, size, MAX_EX_KEY_MAP_SIZE); ++ } ++ for (loop = 0; loop < size; loop++) { ++ if ((p_key_map[loop].ex_mem_entry % 4 != 0) ++ || (p_key_map[loop].crypto_key_no != loop)) { ++ printk(KERN_ERR \ ++ "map[%d]:entry[0x%x]:aes key[0x%x] para error..\n", ++ loop, ++ p_key_map[loop].ex_mem_entry, ++ p_key_map[loop].crypto_key_no); ++ } ++ } ++} ++ ++void efuse_check_update_trans_flag(struct wrap_efuse_obj *obj, ++u32 start_no, u32 size, struct af_alg_usr_def *p_alg){ ++ ++ int i; ++ struct ex_key_map *p_key_map; ++ struct ex_key_map *old_p_key_map; ++ struct af_alg_usr_def *p_old_usr_def; ++ int key_map_size; ++ ++ p_old_usr_def = &obj->old_usr_def; ++ /* first check if use cpu mode */ ++ if (p_old_usr_def->mode != p_alg->mode) { ++ obj->efuse_trans_flag = EFUSE_NEED_TRANS; ++ p_old_usr_def->mode = p_alg->mode; ++ /* not return here..maybe para not the same.. ++ just update below. */ ++ } ++ if (obj->open_flag & CRYPTO_EX_MEM_SWITCH_KEY) { ++ if (p_alg->mode & CRYPTO_EX_MEM_SWITCH_KEY) { ++ if (p_alg->mode & CRYPTO_EX_MEM_4_ENTRY_1_KEY) { ++ key_map_size = p_alg->adv.ex_key_para.map_size; ++ p_key_map = &p_alg->adv.ex_key_para.map[0]; ++ old_p_key_map = &p_old_usr_def->adv.ex_key_para.map[0]; ++ efuse_check_map_para(key_map_size, p_key_map); ++ /* check map size */ ++ if (key_map_size != p_old_usr_def->adv.ex_key_para.map_size) { ++ /* cpy new to old */ ++ memcpy(p_old_usr_def, p_alg, ++ sizeof(struct af_alg_usr_def)); ++ obj->efuse_trans_flag = EFUSE_NEED_TRANS; ++ return; ++ } ++ /* check para. */ ++ for (i = 0; i < key_map_size; i++, ++ p_key_map++, old_p_key_map++) { ++ if (memcmp(p_key_map, old_p_key_map, ++ sizeof(struct ex_key_map))) { ++ /* cmp error */ ++ memcpy(p_old_usr_def, p_alg, ++ sizeof(struct af_alg_usr_def)); ++ obj->efuse_trans_flag = EFUSE_NEED_TRANS; ++ return; ++ } ++ } ++ } ++ } else { ++ /*chip need set the map...and usr not set */ ++ key_map_size = size; ++ if (key_map_size != obj->old_size) { ++ obj->old_size = key_map_size; ++ obj->efuse_trans_flag = EFUSE_NEED_TRANS; ++ return; ++ } ++ } ++ } else { ++ key_map_size = size; ++ if (key_map_size != obj->old_size) { ++ obj->old_size = key_map_size; ++ obj->efuse_trans_flag = EFUSE_NEED_TRANS; ++ return; ++ } ++ } ++} ++ ++void efuse_trans_key(struct wrap_efuse_obj *obj, ++u32 start_no, u32 size, struct af_alg_usr_def *p_alg) ++{ ++ int i; ++ struct ex_key_map *p_key_map; ++ int key_map_size; ++ unsigned int temp_reg; ++ ++ efuse_check_update_trans_flag(obj, start_no, size, p_alg); ++ if (obj->efuse_trans_flag != EFUSE_NEED_TRANS) { ++ /* printk("###DO NOT need to update efuse para to aes...\n"); */ ++ return; ++ } else { ++ /* clear update flag. */ ++ obj->efuse_trans_flag = 0; ++ /* printk("<<<need to update efuse para to aes...\n"); */ ++ } ++ if (obj->open_flag & CRYPTO_EX_MEM_SWITCH_KEY) { ++ if (p_alg->mode & CRYPTO_EX_MEM_SWITCH_KEY) { ++ if (p_alg->mode & CRYPTO_EX_MEM_4_ENTRY_1_KEY) { ++ key_map_size = p_alg->adv.ex_key_para.map_size; ++ p_key_map = &p_alg->adv.ex_key_para.map[0]; ++ efuse_check_map_para(key_map_size, p_key_map); ++ for (i = 0; i < key_map_size; ++ i++, p_key_map++) { ++ refresh_efuse(obj); ++ temp_reg = ++ wrap_readl(obj, efuse_config); ++ temp_reg &= ~(0xf<<28); ++ temp_reg |= ++ (p_key_map->ex_mem_entry / 4) << 28; ++ wrap_writel(obj, ++ efuse_config, temp_reg); ++ wrap_writel(obj, ++ efuse_cmd, (i << 20) + 0x04); ++ efuse_detect_complete(obj, 4); ++ } ++ } ++ } else { ++ /*chip need set the map...and usr not set */ ++ key_map_size = size; ++ for (i = 0; i < key_map_size; i++) { ++ refresh_efuse(obj); ++ temp_reg = wrap_readl(obj, efuse_config); ++ temp_reg &= ~(0xf<<28); ++ temp_reg |= i << 28; ++ wrap_writel(obj, efuse_config, temp_reg); ++ wrap_writel(obj, efuse_cmd, (i << 20) + 0x04); ++ efuse_detect_complete(obj, 4); ++ } ++ } ++ } else { ++ key_map_size = size; ++ for (i = 0; i < key_map_size; i++) { ++ refresh_efuse(obj); ++ wrap_writel(obj, efuse_cmd, (i << 20) + 0x04); ++ efuse_detect_complete(obj, 4); ++ } ++ } ++ ++} ++ ++static void aes_biglittle_swap(u8 *buf) ++{ ++ u8 tmp, tmp1; ++ tmp = buf[0]; ++ tmp1 = buf[1]; ++ buf[0] = buf[3]; ++ buf[1] = buf[2]; ++ buf[2] = tmp1; ++ buf[3] = tmp; ++} ++void efuse_get_lock_status(struct wrap_efuse_obj *obj, ++struct efuse_status *status) ++{ ++ status->efuse_apb_lock = (wrap_readl(obj, efuse_status0)>>20) & 0x0f; ++ status->aes_ahb_lock = (wrap_readl(obj, efuse_status0)>>24) & 0x0f; ++} ++ ++void efuse_read_entry(struct wrap_efuse_obj *obj, ++u32 key, u32 start_entry, u8 *buff, u32 size) ++{ ++ /* ++ wrap_writel(obj,efuse_cmd,1); ++ set key.. ++ */ ++ u32 data, i; ++ ++ for (i = 0; i < size; i++) { ++ wrap_writel(obj, efuse_match_key, key); ++ wrap_writel(obj, efuse_cmd, ((start_entry + i)<<4) + 0x03); ++ efuse_detect_complete(obj, 3); ++ data = wrap_readl(obj, efuse_dout); ++ *buff++ = (u8)data; ++ } ++} ++ ++ ++long fh_efuse_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int i; ++ ++ EFUSE_INFO efuse_info = {0}; ++ u32 *p_dst = NULL; ++ u8 *p_dst_8 = NULL; ++ unsigned int data; ++ u32 temp_swap_data[32] = {0}; ++ ++ if (copy_from_user((void *) &efuse_info, (void __user*) arg, ++ sizeof(EFUSE_INFO))) { ++ return -EFAULT; ++ } ++ ++ refresh_efuse(&s_efuse_obj); ++ switch (cmd) { ++ case IOCTL_EFUSE_CHECK_PRO: ++ auto_check_efuse_pro_bits(&s_efuse_obj, ++ efuse_info.status.protect_bits); ++ break; ++ case IOCTL_EFUSE_WRITE_KEY: ++ if (copy_from_user((void *) &temp_swap_data[0], ++ (void __user *) efuse_info.key_buff, ++ efuse_info.key_size)) { ++ return -EFAULT; ++ } ++ ++ p_dst = &temp_swap_data[0]; ++ ++ for (i = 0; i < efuse_info.key_size / sizeof(u32); i++) ++ aes_biglittle_swap((u8 *) (p_dst + i)); ++ p_dst_8 = (u8 *)&temp_swap_data[0]; ++ ++ for (i = 0; i < efuse_info.key_size; i++) { ++ efuse_write_key_byte(&s_efuse_obj, ++ efuse_info.efuse_entry_no + i, *(p_dst_8 + i)); ++ } ++ ++ break; ++ case IOCTL_EFUSE_CHECK_LOCK: ++ ++ efuse_get_lock_status(&s_efuse_obj, &efuse_info.status); ++ break; ++ case IOCTL_EFUSE_TRANS_KEY: ++ printk(KERN_WARNING "please use efuse transkey with aes...\n"); ++ break; ++ case IOCTL_EFUSE_SWITCH_CPU_KEY_MODE: ++ printk(KERN_WARNING "please use cpu key with aes...\n"); ++ break; ++ case IOCTL_EFUSE_SWITCH_EFUSE_KEY_MODE: ++ printk(KERN_WARNING "please use efuse key with aes...\n"); ++ break; ++ case IOCTL_EFUSE_CHECK_ERROR: ++ printk(KERN_WARNING "not support...\n"); ++ break; ++ case IOCTL_EFUSE_READ_KEY: ++ /*printf("match is : %x..\n",match_key);*/ ++ efuse_read_entry(&s_efuse_obj, efuse_info.status.error, ++ efuse_info.efuse_entry_no, ++ (u8 *)&temp_swap_data[0], efuse_info.key_size); ++ p_dst = (u32 *)temp_swap_data; ++ for (i = 0; i < efuse_info.key_size / sizeof(u32); i++) { ++ aes_biglittle_swap((u8 *) (p_dst + i)); ++ /*printk("swap data is %x\n",*(p_dst + i));*/ ++ } ++ if (copy_to_user((void __user *) (efuse_info.key_buff), ++ (void *) &temp_swap_data[0], ++ efuse_info.key_size)) { ++ return -EFAULT; ++ } ++ /*memcpy(efuse_user_info,&efuse_info,sizeof(EFUSE_INFO));*/ ++ break; ++ case IOCTL_EFUSE_SET_LOCK: ++ /*parse lock data...*/ ++ data = efuse_info.status.aes_ahb_lock; ++ data <<= 4; ++ data &= 0xf0; ++ efuse_info.status.efuse_apb_lock &= 0x0f; ++ data |= efuse_info.status.efuse_apb_lock; ++ efuse_write_key_byte(&s_efuse_obj, 63, (u8)data); ++ break; ++ case IOCTL_EFUSE_SET_MAP_PARA_4_TO_1: ++ printk(KERN_WARNING "not support here..\ ++ pls check if chip support this func and set core para\n"); ++ break; ++ case IOCTL_EFUSE_SET_MAP_PARA_1_TO_1: ++ printk(KERN_WARNING "not support func here...\n"); ++ break; ++ case IOCTL_EFUSE_CLR_MAP_PARA: ++ printk(KERN_WARNING "not support here...\n"); ++ break; ++ default: ++ break; ++ } ++ memcpy((void *)&s_efuse_obj.status, (void *)&efuse_info.status, ++ sizeof(struct efuse_status)); ++ if (copy_to_user((void __user *) (&((EFUSE_INFO *)arg)->status), ++ (void *) &efuse_info.status, ++ sizeof(struct efuse_status))) { ++ return -EFAULT; ++ } ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ++ * function body ++ * ++ * ++ *****************************************************************************/ ++static int __devinit fh_efuse_probe(struct platform_device *pdev) ++{ ++ int err; ++ struct resource *res; ++ struct fh_efuse_platform_data *p_efuse_plat; ++ p_efuse_plat = ++ (struct fh_efuse_platform_data *) pdev->dev.platform_data; ++ if (p_efuse_plat == NULL) { ++ dev_err(&pdev->dev, "efuse get platform data error..\n"); ++ return -ENODEV; ++ } ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "efuse get platform source error..\n"); ++ return -ENODEV; ++ } ++ ++ res = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "efuse region already claimed\n"); ++ return -EBUSY; ++ } ++ ++ s_efuse_obj.regs = ioremap(res->start, resource_size(res)); ++ if (s_efuse_obj.regs == NULL) { ++ err = -ENXIO; ++ goto fail_no_ioremap; ++ } ++ s_efuse_obj.open_flag = p_efuse_plat->efuse_support_flag; ++ if (s_efuse_obj.open_flag & CRYPTO_EX_MEM_INDEP_POWER) { ++ /*efuse power up*/ ++ open_efuse_power(&s_efuse_obj); ++ } ++#ifdef EFUSE_BUFFER_OFF ++ efuse_buffer_set(&s_efuse_obj, 0); ++#endif ++ err = misc_register(&fh_efuse_misc); ++ ++ if (err != 0) { ++ dev_err(&pdev->dev, "efuse register misc error\n"); ++ return err; ++ } ++ ++ platform_set_drvdata(pdev, &fh_efuse_misc); ++ ++ return 0; ++ ++fail_no_ioremap: ++ release_mem_region(res->start, resource_size(res)); ++ ++ return err; ++} ++ ++static int __exit fh_efuse_remove(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct miscdevice *misc; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ misc = (struct miscdevice *)platform_get_drvdata(pdev); ++ misc_deregister(misc); ++ iounmap(s_efuse_obj.regs); ++ release_mem_region(res->start, resource_size(res)); ++ ++ return 0; ++} ++ ++/******************* ++ * ++ * ++ * add platform cause of i need the board info... ++ * in the probe function. i will register the sadc misc drive... ++ * then the app can open the sadc misc device.. ++ * ++ ******************/ ++static struct platform_driver fh_efuse_driver = { ++ .driver = { ++ .name = FH_EFUSE_PLAT_DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_efuse_probe, ++ .remove = __exit_p(fh_efuse_remove), ++}; ++ ++static int __init fh_efuse_init(void) ++{ ++ return platform_driver_register(&fh_efuse_driver); ++} ++ ++static void __exit fh_efuse_exit(void) ++{ ++ platform_driver_unregister(&fh_efuse_driver); ++} ++ ++module_init(fh_efuse_init); ++module_exit(fh_efuse_exit); ++ ++MODULE_DESCRIPTION("fh efuse driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("zhangy@fullhan.com"); ++MODULE_ALIAS("platform:FH_efuse"); +diff --git a/drivers/misc/fh_efuse.h b/drivers/misc/fh_efuse.h +new file mode 100644 +index 00000000..f018b7e0 +--- /dev/null ++++ b/drivers/misc/fh_efuse.h +@@ -0,0 +1,102 @@ ++/* ++ * fh_efuse.h ++ * ++ * Created on: Aug 9, 2016 ++ * Author: duobao ++ */ ++ ++#ifndef FH_EFUSE_H_ ++#define FH_EFUSE_H_ ++ ++#include <linux/io.h> ++#include <linux/scatterlist.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/scatterlist.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/workqueue.h> ++#include <linux/bug.h> ++#include <linux/completion.h> ++#include <linux/miscdevice.h> ++#include <linux/fs.h> ++#include <crypto/if_alg.h> ++/**************************************************************************** ++ * #define section ++ * add constant #define here if any ++ ***************************************************************************/ ++/*#define FH_EFUSE_PROC_FILE "driver/efuse"*/ ++#define MAX_EFUSE_MAP_SIZE 8 ++ ++#define IOCTL_EFUSE_CHECK_PRO 0 ++#define IOCTL_EFUSE_WRITE_KEY 1 ++#define IOCTL_EFUSE_CHECK_LOCK 2 ++#define IOCTL_EFUSE_TRANS_KEY 3 ++#define IOCTL_EFUSE_SWITCH_CPU_KEY_MODE 4 ++#define IOCTL_EFUSE_SWITCH_EFUSE_KEY_MODE 5 ++#define IOCTL_EFUSE_CHECK_ERROR 6 ++#define IOCTL_EFUSE_READ_KEY 7 ++#define IOCTL_EFUSE_SET_LOCK 8 ++#define IOCTL_EFUSE_SET_MAP_PARA_4_TO_1 9 ++#define IOCTL_EFUSE_SET_MAP_PARA_1_TO_1 10 ++#define IOCTL_EFUSE_CLR_MAP_PARA 11 ++ ++#define EFUSE_NEED_TRANS 0x55 ++/**************************************************************************** ++ * ADT section ++ * add Abstract Data Type definition here ++ ***************************************************************************/ ++ ++struct efuse_status { ++ /*bit 1 means could write..0 not write*/ ++ u32 protect_bits[2]; ++ /*bit 1 means cpu couldn't read efuse entry data...*/ ++ u32 efuse_apb_lock; ++ u32 aes_ahb_lock; ++ u32 error; ++}; ++ ++typedef struct { ++ u32 efuse_entry_no; /*from 0 ~ 31*/ ++ u8 *key_buff; ++ u32 key_size; ++ u32 trans_key_start_no; /*from 0 ~ 7*/ ++ u32 trans_key_size; /*max 8*/ ++ struct efuse_status status; ++} EFUSE_INFO; ++ ++struct wrap_efuse_obj { ++ void *regs; ++ /*write key*/ ++ u32 efuse_entry_no; /*from 0 ~ 31*/ ++ u8 *key_buff; ++ u32 key_size; ++ /*trans key*/ ++ u32 trans_key_start_no; /*from 0 ~ 7*/ ++ u32 trans_key_size; /*max 8*/ ++ /*status*/ ++ struct efuse_status status; ++ u32 open_flag; ++ /*add check if need efuse transkey*/ ++ u32 efuse_trans_flag; ++ /* for old driver just check size. ++ for have mapping func, should check the adv_info para.*/ ++ u32 old_size; ++ struct af_alg_usr_def old_usr_def; ++}; ++ ++ ++/**************************************************************************** ++ * extern variable declaration section ++ ***************************************************************************/ ++ ++/**************************************************************************** ++ * section ++ * add function prototype here if any ++ ***************************************************************************/ ++void efuse_trans_key(struct wrap_efuse_obj *obj, u32 start_no, ++u32 size, struct af_alg_usr_def *p_alg); ++#endif /* FH_EFUSE_H_ */ +diff --git a/drivers/misc/fh_i2s.c b/drivers/misc/fh_i2s.c +new file mode 100644 +index 00000000..84e6292c +--- /dev/null ++++ b/drivers/misc/fh_i2s.c +@@ -0,0 +1,1346 @@ ++/**@file ++ * @Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd. ++ * @brief ++ * ++ * @author fullhan ++ * @date 2016-7-15 ++ * @version V1.0 ++ * @version V1.1 modify code style ++ * @note: misc i2s driver for fh8830 embedded i2s codec. ++ * @note History: ++ * @note <author> <time> <version > <desc> ++ * @note ++ * @warning: the codec is fixed to 24 bit, so remember to move the 24 bit data to 16 bit in ++ * application layer, the next version CPU will sovle this bug. ++ */ ++ ++ ++#include <linux/irqreturn.h> ++#include <linux/clk.h> ++#include <linux/device.h> ++#include <linux/file.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/miscdevice.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/uaccess.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/slab.h> ++#include <linux/kernel.h> ++#include <linux/interrupt.h> ++#include <linux/types.h> ++#include <linux/poll.h> ++#include <linux/ioctl.h> ++#include <linux/i2c.h> ++#include <linux/workqueue.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <mach/fh_dmac.h> ++#include <mach/fh_predefined.h> ++ ++#include "fh_i2s.h" ++ ++ ++#define NR_DESCS_PER_CHANNEL 64 ++ ++#define FIX_SAMPLE_BIT 32 ++ ++#define I2S_HW_NUM_RX 0 ++#define I2S_HW_NUM_TX 1 ++#define I2S_DMA_CAP_CHANNEL 2 ++#define I2S_DMA_PAY_CHANNEL 3 ++ ++#define I2S_CTRL 0x0 ++#define I2S_TXFIFO_CTRL 0x4 ++#define I2S_RXFIFO_CTRL 0x8 ++#define I2S_STATUS 0x0c ++#define I2S_DAT_CTL 0x10 ++#define I2S_DBG_CTL 0x14 ++#define I2S_STATUS1 0x18 ++#define I2S_STATUS2 0x1c ++ ++#define I2S_DACL_FIFO 0xf0a00100 ++#define I2S_DACR_FIFO 0xf0a00300 ++#define I2S_ADC_FIFO 0xf0a00200 ++ ++#define I2S_DMA_PREALLOC_SIZE 128*1024 ++ ++#define I2S_INTR_RX_UNDERFLOW 0x10000 ++#define I2S_INTR_RX_OVERFLOW 0x20000 ++#define I2S_INTR_TX_UNDERFLOW 0x40000 ++#define I2S_INTR_TX_OVERFLOW 0x80000 ++ ++#define I2S_EXT_EN 1<<12 ++#define I2S_EN 1<<0 ++#define I2S_DACL_CHEN_EN 1<<30 ++#define I2S_DACR_CHEN_EN 1<<31 ++#define I2S_ADC_CHEN_EN 1<<29 ++#define I2S_SHIFT_BIT 6 ++#define I2S_DAC_FIFO_CLEAR 1<<4 ++#define I2S_ADC_FIFO_CLEAR 1<<4 ++#define I2S_ADC_FIFO_EN 1<<0 ++#define I2S_DAC_FIFO_EN 1<<0 ++#define FH_i2s_DEBUG ++#ifdef FH_i2s_DEBUG ++#define PRINT_i2s_DBG(fmt, args...) \ ++ do \ ++ { \ ++ printk("FH_i2s_DEBUG: "); \ ++ printk(fmt, ## args); \ ++ } \ ++ while(0) ++#else ++#define PRINT_i2s_DBG(fmt, args...) do { } while (0) ++#endif ++ ++enum i2s_type ++{ ++ capture = 0, ++ playback, ++}; ++ ++ ++enum i2s_state ++{ ++ STATE_NORMAL = 0, ++ STATE_XRUN, ++ STATE_STOP, ++ STATE_RUN, ++ STATE_PAUSE ++}; ++ ++struct i2s_infor_record_t ++{ ++ int record_pid; ++ int play_pid; ++}i2s_infor_record; ++ ++ ++struct fh_dma_chan ++{ ++ struct dma_chan *chan; ++ void __iomem *ch_regs; ++ u8 mask; ++ u8 priority; ++ bool paused; ++ bool initialized; ++ spinlock_t lock; ++ /* these other elements are all protected by lock */ ++ unsigned long flags; ++ dma_cookie_t completed; ++ struct list_head active_list; ++ struct list_head queue; ++ struct list_head free_list; ++ struct fh_cyclic_desc *cdesc; ++ unsigned int descs_allocated; ++}; ++ ++struct i2s_config { ++ int rate; ++ int volume; ++ int frame_bit; ++ int channels; ++ int buffer_size; ++ int period_size; ++ int buffer_bytes; ++ int period_bytes; ++ int start_threshold; ++ int stop_threshold; ++}; ++ ++struct i2s_ptr_t ++{ ++ struct i2s_config cfg; ++ enum i2s_state state; ++ long size; ++ int hw_ptr; ++ int appl_ptr; ++ spinlock_t lock; ++ struct device dev; ++ u8 *area; /*virtual pointer*/ ++ dma_addr_t addr; /*physical address*/ ++ u8 * mmap_addr; ++}; ++ ++struct fh_i2s_cfg ++{ ++ struct i2s_ptr_t capture; ++ struct i2s_ptr_t playback; ++ wait_queue_head_t readqueue; ++ wait_queue_head_t writequeue; ++ struct semaphore sem_capture; ++ struct semaphore sem_playback; ++}; ++ ++struct fh_i2s_dma_chan ++{ ++ struct dma_chan *chan; ++ void __iomem *ch_regs; ++ u8 mask; ++ u8 priority; ++ bool paused; ++ bool initialized; ++ spinlock_t lock; ++ /* these other elements are all protected by lock */ ++ unsigned long flags; ++ dma_cookie_t completed; ++ struct list_head active_list; ++ struct list_head queue; ++ struct list_head free_list; ++ struct dma_async_tx_descriptor *cdesc; ++ unsigned int descs_allocated; ++}; ++ ++struct fh_I2S_dma_transfer ++{ ++ struct dma_chan *chan; ++ struct fh_dma_slave cfg; ++ struct scatterlist sgl; ++ struct fh_cyclic_desc *desc; ++}; ++ ++struct channel_assign ++{ ++ int capture_channel; ++ int playback_channel; ++}; ++ ++struct i2s_dev ++{ ++ struct channel_assign channel_assign; ++ struct fh_i2s_cfg i2s_config; ++ struct miscdevice fh_i2s_miscdev; ++}; ++ ++static const struct file_operations I2S_fops; ++ ++static struct i2s_dev fh_i2s_dev = ++{ ++ .channel_assign = { ++ .capture_channel = I2S_DMA_CAP_CHANNEL, ++ .playback_channel = I2S_DMA_PAY_CHANNEL, ++ }, ++ .fh_i2s_miscdev = { ++ .fops = &I2S_fops, ++ .name = "fh_fh8830_i2s", ++ .minor = MISC_DYNAMIC_MINOR, ++ } ++ ++}; ++ ++static struct ++{ ++ spinlock_t lock; ++ void __iomem *regs; ++ struct clk *clk; ++ unsigned long in_use; ++ unsigned long next_heartbeat; ++ struct timer_list timer; ++ int irq; ++} fh_i2s_module; ++static struct fh_dma_chan *dma_rx_transfer = NULL; ++static struct fh_dma_chan *dma_tx_transfer = NULL; ++static struct work_struct playback_wq; ++ ++static struct i2s_param_store ++{ ++ int input_volume; ++} i2s_param_store; ++ ++ ++static void fh_I2S_tx_dma_done(void *arg); ++static void fh_I2S_rx_dma_done(void *arg); ++static bool fh_I2S_dma_chan_filter(struct dma_chan *chan, void *filter_param); ++ ++void fh_I2S_stop_playback(struct fh_i2s_cfg *i2s_config) ++{ ++ ++ if(i2s_config->playback.state == STATE_STOP) ++ { ++ return; ++ } ++ i2s_config->playback.state = STATE_STOP; ++ writel(0, fh_i2s_module.regs + I2S_TXFIFO_CTRL);//tx fifo disable ++ fh_dma_cyclic_stop(dma_tx_transfer->chan); ++ fh_dma_cyclic_free(dma_tx_transfer->chan); ++ up(&i2s_config->sem_playback); ++} ++ ++void fh_I2S_stop_capture(struct fh_i2s_cfg *i2s_config) ++{ ++ ++ u32 rx_status; ++ if(i2s_config->capture.state == STATE_STOP) ++ { ++ return; ++ } ++ rx_status = readl( fh_i2s_module.regs + I2S_RXFIFO_CTRL);//clear rx fifo ++ rx_status = rx_status|I2S_ADC_FIFO_CLEAR; ++ writel(rx_status,fh_i2s_module.regs + I2S_RXFIFO_CTRL); ++ ++ i2s_config->capture.state = STATE_STOP; ++ ++ writel(0, fh_i2s_module.regs + I2S_RXFIFO_CTRL);//rx fifo disable ++ ++ fh_dma_cyclic_stop(dma_rx_transfer->chan); ++ fh_dma_cyclic_free(dma_rx_transfer->chan); ++ up(&i2s_config->sem_capture); ++} ++ ++ ++int fh_i2s_get_factor_from_table(int rate) ++{ ++ return 0; ++} ++ ++void fh_switch_input_volume(int volume) ++{ ++ ++} ++ ++void init_i2s(enum i2s_type type,struct fh_i2s_cfg *i2s_config) ++{ ++ ++} ++ ++static inline long bytes_to_frames(int frame_bit, int bytes) ++{ ++ return bytes * 8 /frame_bit; ++} ++ ++static inline long fh_i2s_frames_to_bytes(int frame_bit, int frames) ++{ ++ return frames * frame_bit / 8; ++} ++ ++int i2s_avail_data_len(enum i2s_type type,struct fh_i2s_cfg *stream) ++{ ++ int delta; ++ if (capture == type) ++ { ++ spin_lock(&stream->capture.lock); ++ delta = stream->capture.hw_ptr - stream->capture.appl_ptr; ++ spin_unlock(&stream->capture.lock); ++ if (delta < 0) ++ { ++ delta += stream->capture.size; ++ } ++ return delta; ++ } ++ else ++ { ++ spin_lock(&stream->playback.lock); ++ delta = stream->playback.appl_ptr - stream->playback.hw_ptr; ++ spin_unlock(&stream->playback.lock); ++ if (delta < 0) ++ { ++ delta += stream->playback.size; ++ } ++ return stream->playback.size - delta; ++ } ++} ++ ++static int fh_i2s_close(struct inode *ip, struct file *fp) ++{ ++ struct miscdevice *miscdev = fp->private_data; ++ struct i2s_dev *dev = container_of(miscdev, struct i2s_dev, fh_i2s_miscdev); ++ struct fh_i2s_cfg *i2s_config = &dev->i2s_config; ++ int pid; ++ ++ pid= current->tgid; ++ ++ if( i2s_infor_record.play_pid == pid) ++ { ++ fh_I2S_stop_playback(i2s_config); ++ ++ } ++ if (i2s_infor_record.record_pid==pid) ++ { ++ fh_I2S_stop_capture(i2s_config); ++ } ++ return 0; ++} ++ ++int fh_i2s_register_tx_dma(struct fh_i2s_cfg *i2s_config) ++{ ++ int ret; ++ unsigned int reg; ++ struct fh_dma_slave *tx_slave; ++ tx_slave = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL); ++ if (!tx_slave) ++ { ++ return -ENOMEM; ++ } ++ tx_slave->cfg_hi = FHC_CFGH_DST_PER(I2S_HW_NUM_TX); ++ tx_slave->dst_msize = FH_DMA_MSIZE_8; ++ tx_slave->src_msize = FH_DMA_MSIZE_8; ++ tx_slave->reg_width = FH_DMA_SLAVE_WIDTH_32BIT; ++ tx_slave->fc = FH_DMA_FC_D_M2P; ++ tx_slave->tx_reg = I2S_DACL_FIFO; ++ dma_tx_transfer->chan->private = tx_slave; ++ ++ if ((i2s_config->playback.cfg.buffer_bytes < i2s_config->playback.cfg.period_bytes) || ++ (i2s_config->playback.cfg.buffer_bytes <= 0) || (i2s_config->playback.cfg.period_bytes <= 0) || ++ (i2s_config->playback.cfg.buffer_bytes/i2s_config->playback.cfg.period_bytes > NR_DESCS_PER_CHANNEL)) ++ { ++ printk(KERN_ERR "buffer_size and period_size are invalid\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ dma_tx_transfer->cdesc = ++ fh_dma_cyclic_prep(dma_tx_transfer->chan,i2s_config->playback.addr, ++ i2s_config->playback.cfg.buffer_bytes,i2s_config->playback.cfg.period_bytes, DMA_MEM_TO_DEV); ++ if(dma_tx_transfer->cdesc <= 0) ++ { ++ printk(KERN_ERR "cyclic desc err\n"); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ dma_tx_transfer->cdesc->period_callback = fh_I2S_tx_dma_done; ++ dma_tx_transfer->cdesc->period_callback_param = i2s_config; ++ fh_dma_cyclic_start(dma_tx_transfer->chan); ++ if (tx_slave) ++ { ++ kfree(tx_slave); ++ } ++ ++ reg = readl(fh_i2s_module.regs + I2S_CTRL); ++ reg = reg <<I2S_SHIFT_BIT; ++ reg |= I2S_DACL_CHEN_EN; ++ writel(reg,fh_i2s_module.regs + I2S_CTRL);// enable left tx fifo ++ ++ writel(0x1<<4,fh_i2s_module.regs + I2S_TXFIFO_CTRL);// clear tx fifo ++ writel(0x20027,fh_i2s_module.regs + I2S_TXFIFO_CTRL);// enbale tx fifo ++ ++ /*must set NULL to tell DMA driver that we free the DMA slave*/ ++ dma_tx_transfer->chan->private = NULL; ++ ++ return 0; ++fail: ++ return ret; ++} ++ ++int fh_i2s_register_rx_dma( struct fh_i2s_cfg *i2s_config) ++{ ++ int ret; ++ unsigned int reg; ++ struct fh_dma_slave *rx_slave; ++ rx_slave = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL); ++ if (!rx_slave) ++ { ++ return -ENOMEM; ++ } ++ ++ rx_slave->cfg_hi = FHC_CFGH_SRC_PER(I2S_HW_NUM_RX); ++ rx_slave->dst_msize = FH_DMA_MSIZE_8; ++ rx_slave->src_msize = FH_DMA_MSIZE_8; ++ rx_slave->reg_width = FH_DMA_SLAVE_WIDTH_32BIT; ++ rx_slave->fc = FH_DMA_FC_D_P2M; ++ rx_slave->rx_reg = I2S_ADC_FIFO; ++ dma_rx_transfer->chan->private = rx_slave; ++ ++ if ((i2s_config->capture.cfg.buffer_bytes < i2s_config->capture.cfg.period_bytes) || ++ (i2s_config->capture.cfg.buffer_bytes <= 0) ||(i2s_config->capture.cfg.period_bytes <= 0) || ++ (i2s_config->capture.cfg.buffer_bytes/i2s_config->capture.cfg.period_bytes > NR_DESCS_PER_CHANNEL)) ++ { ++ printk(KERN_ERR "buffer_size and period_size are invalid\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ dma_rx_transfer->cdesc= ++ fh_dma_cyclic_prep(dma_rx_transfer->chan,i2s_config->capture.addr, ++ i2s_config->capture.cfg.buffer_bytes,i2s_config->capture.cfg.period_bytes, DMA_DEV_TO_MEM); ++ if(dma_rx_transfer->cdesc <= 0) ++ { ++ printk(KERN_ERR" cyclic desc err\n"); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ dma_rx_transfer->cdesc->period_callback = fh_I2S_rx_dma_done; ++ dma_rx_transfer->cdesc->period_callback_param = i2s_config; ++ fh_dma_cyclic_start(dma_rx_transfer->chan); ++ ++ reg = readl(fh_i2s_module.regs + I2S_CTRL); ++ reg = reg<<I2S_SHIFT_BIT; ++ reg |= I2S_ADC_CHEN_EN ; ++ writel(reg,fh_i2s_module.regs + I2S_CTRL);//enbale dac fifo ++ writel(0x1<<4,fh_i2s_module.regs + I2S_RXFIFO_CTRL);// clear rx fifo ++ writel(0x20027,fh_i2s_module.regs + I2S_RXFIFO_CTRL);// enable rx fifo ++ ++ ++ if (rx_slave) ++ { ++ kfree(rx_slave); ++ } ++ /*must set NULL to tell DMA driver that we free the DMA slave*/ ++ dma_rx_transfer->chan->private = NULL; ++ return 0; ++fail: ++ kfree(rx_slave); ++ return ret; ++} ++ ++ ++void fh_i2s_playback_start_wq_handler(struct work_struct *work) ++{ ++ int avail; ++ while(1) ++ { ++ if (STATE_STOP == fh_i2s_dev.i2s_config.playback.state) ++ { ++ return; ++ } ++ avail = i2s_avail_data_len(playback, &fh_i2s_dev.i2s_config); ++ if (avail > fh_i2s_dev.i2s_config.playback.cfg.period_bytes) ++ { ++ msleep(0); ++ } ++ else ++ { ++ break; ++ } ++ ++ } ++} ++ ++int fh_I2S_start_playback(struct fh_i2s_cfg *i2s_config) ++{ ++ int ret; ++ ++ if(i2s_config->playback.state == STATE_RUN) ++ { ++ return 0; ++ } ++ if (i2s_config->playback.cfg.buffer_bytes >= I2S_DMA_PREALLOC_SIZE) ++ { ++ printk("DMA prealloc buffer is smaller than i2s_config->buffer_bytes\n"); ++ return -ENOMEM; ++ } ++ memset(i2s_config->playback.area, 0x0, i2s_config->playback.cfg.buffer_bytes); ++ i2s_config->playback.size = i2s_config->playback.cfg.buffer_bytes; ++ i2s_config->playback.state = STATE_RUN; ++ ret = fh_i2s_register_tx_dma(i2s_config); ++ if (ret < 0) ++ { ++ return ret; ++ } ++ INIT_WORK(&playback_wq, fh_i2s_playback_start_wq_handler); ++ schedule_work(&playback_wq); ++ ++ return 0; ++} ++ ++int fh_I2S_start_capture(struct fh_i2s_cfg *i2s_config) ++{ ++ if(i2s_config->capture.state == STATE_RUN) ++ { ++ return 0; ++ } ++ ++ if (i2s_config->capture.cfg.buffer_bytes >= I2S_DMA_PREALLOC_SIZE) ++ { ++ printk("DMA prealloc buffer is smaller than i2s_config->buffer_bytes\n"); ++ return -ENOMEM; ++ } ++ memset(i2s_config->capture.area, 0, i2s_config->capture.cfg.buffer_bytes); ++ i2s_config->capture.size = i2s_config->capture.cfg.buffer_bytes; ++ ++ i2s_config->capture.state = STATE_RUN; ++ return fh_i2s_register_rx_dma(i2s_config); ++} ++ ++ ++static void fh_I2S_rx_dma_done(void *arg) ++{ ++ struct fh_i2s_cfg *i2s_config; ++ i2s_config = ( struct fh_i2s_cfg *)arg; ++ spin_lock(&i2s_config->capture.lock); ++ i2s_config->capture.hw_ptr += i2s_config->capture.cfg.period_bytes; ++ if (i2s_config->capture.hw_ptr > i2s_config->capture.size ) ++ { ++ i2s_config->capture.hw_ptr = i2s_config->capture.hw_ptr - i2s_config->capture.size; ++ } ++ spin_unlock(&i2s_config->capture.lock); ++ if (waitqueue_active(&i2s_config->readqueue)) ++ { ++ int avail = i2s_avail_data_len(capture,i2s_config); ++ if (avail > i2s_config->capture.cfg.period_bytes) ++ { ++ wake_up_interruptible(&i2s_config->readqueue); ++ } ++ } ++ ++} ++ ++ ++static void fh_I2S_tx_dma_done(void *arg) ++{ ++ ++ struct fh_i2s_cfg *i2s_config; ++ i2s_config = ( struct fh_i2s_cfg *)arg; ++ spin_lock(&i2s_config->playback.lock); ++ i2s_config->playback.hw_ptr += i2s_config->playback.cfg.period_bytes; ++ if (i2s_config->playback.hw_ptr > i2s_config->playback.size ) ++ { ++ i2s_config->playback.hw_ptr = i2s_config->playback.hw_ptr - i2s_config->playback.size; ++ } ++ spin_unlock(&i2s_config->playback.lock); ++ if (waitqueue_active(&i2s_config->writequeue)) ++ { ++ int avail = i2s_avail_data_len(playback,i2s_config); ++ if (avail > i2s_config->playback.cfg.period_bytes) ++ { ++ wake_up_interruptible(&i2s_config->writequeue); ++ } ++ } ++} ++ ++bool fh_I2S_dma_chan_filter(struct dma_chan *chan, void *filter_param) ++{ ++ int dma_channel = *(int *)filter_param; ++ bool ret = false; ++ ++ if (chan->chan_id == dma_channel) ++ { ++ ret = true; ++ } ++ return ret; ++} ++ ++int fh_i2s_arg_config_support(struct fh_i2s_cfg_arg * cfg) ++{ ++ return 0; ++} ++ ++void fh_i2s_reset_dma_buff(enum i2s_type type, struct fh_i2s_cfg *i2s_config) ++{ ++ if (capture == type) ++ { ++ i2s_config->capture.appl_ptr = 0; ++ i2s_config->capture.hw_ptr = 0; ++ } ++ else ++ { ++ i2s_config->playback.appl_ptr = 0; ++ i2s_config->playback.hw_ptr = 0; ++ } ++} ++ ++static long fh_i2s_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ struct fh_i2s_cfg_arg cfg; ++ struct miscdevice *miscdev = filp->private_data; ++ struct i2s_dev *dev = container_of(miscdev, struct i2s_dev, fh_i2s_miscdev); ++ struct fh_i2s_cfg *i2s_config = &dev->i2s_config; ++ int pid; ++ int rx_status; ++ int tx_status; ++ ++ pid = current->tgid; ++ switch (cmd) ++ { ++ case I2S_INIT_CAPTURE_MEM: ++ ++ if (copy_from_user((void *)&cfg, (void __user *)arg, sizeof(struct fh_i2s_cfg_arg))) ++ { ++ printk(KERN_ERR "copy err\n"); ++ return -EIO; ++ } ++ if (0 == fh_i2s_arg_config_support(&cfg)) ++ { ++ if (down_trylock(&i2s_config->sem_capture)) ++ { ++ printk(KERN_ERR "another thread is running capture.\n"); ++ return -EBUSY; ++ } ++ i2s_infor_record.record_pid = pid; ++ i2s_config->capture.cfg.volume = cfg.volume; ++ i2s_config->capture.cfg.rate = cfg.rate; ++ i2s_config->capture.cfg.channels = cfg.channels; ++ i2s_config->capture.cfg.buffer_size = cfg.buffer_size; ++ i2s_config->capture.cfg.frame_bit = FIX_SAMPLE_BIT; ++ i2s_config->capture.cfg.period_size = cfg.period_size; ++ i2s_config->capture.cfg.buffer_bytes = fh_i2s_frames_to_bytes(i2s_config->capture.cfg.frame_bit,i2s_config->capture.cfg.buffer_size); ++ i2s_config->capture.cfg.period_bytes = fh_i2s_frames_to_bytes(i2s_config->capture.cfg.frame_bit,i2s_config->capture.cfg.period_size); ++ i2s_config->capture.cfg.start_threshold =i2s_config->capture.cfg.buffer_bytes; ++ i2s_config->capture.cfg.stop_threshold = i2s_config->capture.cfg.buffer_bytes; ++ fh_i2s_reset_dma_buff(capture, i2s_config); ++ init_waitqueue_head(&i2s_config->readqueue); ++ spin_lock_init(&i2s_config->capture.lock); ++ init_i2s(capture, i2s_config); ++ i2s_param_store.input_volume = i2s_config->capture.cfg.volume; ++ /* * config sample * */ ++ ++ } ++ else ++ { ++ return -EINVAL; ++ } ++ ++ break; ++ case I2S_INIT_PLAYBACK_MEM: ++ if (copy_from_user((void *)&cfg, (void __user *)arg, sizeof(struct fh_i2s_cfg_arg))) ++ { ++ printk(KERN_ERR "copy err\n"); ++ return -EIO; ++ } ++ ++ if (0 == fh_i2s_arg_config_support(&cfg)) ++ { ++ if (down_trylock(&i2s_config->sem_playback)) ++ { ++ printk(KERN_ERR "another thread is running playback.\n"); ++ return -EBUSY; ++ } ++ i2s_infor_record.play_pid = pid; ++ i2s_config->playback.cfg.volume = cfg.volume; ++ i2s_config->playback.cfg.rate = cfg.rate; ++ i2s_config->playback.cfg.channels = cfg.channels; ++ i2s_config->playback.cfg.buffer_size = cfg.buffer_size; ++ i2s_config->playback.cfg.frame_bit = FIX_SAMPLE_BIT; ++ i2s_config->playback.cfg.period_size = cfg.period_size; ++ i2s_config->playback.cfg.buffer_bytes = fh_i2s_frames_to_bytes(i2s_config->playback.cfg.frame_bit,i2s_config->playback.cfg.buffer_size); ++ i2s_config->playback.cfg.period_bytes = fh_i2s_frames_to_bytes(i2s_config->playback.cfg.frame_bit,i2s_config->playback.cfg.period_size); ++ i2s_config->playback.cfg.start_threshold =i2s_config->playback.cfg.buffer_bytes; ++ i2s_config->playback.cfg.stop_threshold = i2s_config->playback.cfg.buffer_bytes; ++ fh_i2s_reset_dma_buff(playback, i2s_config); ++ init_waitqueue_head(&i2s_config->writequeue); ++ spin_lock_init(&i2s_config->playback.lock); ++ init_i2s(playback, i2s_config); ++ ++ } ++ else ++ { ++ return -EINVAL; ++ } ++ break; ++ case I2S_AI_EN: ++ if (i2s_infor_record.record_pid != pid){ ++ return -EBUSY; ++ } ++ return fh_I2S_start_capture(i2s_config); ++ case I2S_AO_EN: ++ if (i2s_infor_record.play_pid != pid) { ++ return -EBUSY; ++ } ++ return fh_I2S_start_playback(i2s_config); ++ ++ case I2S_AI_DISABLE: ++ printk("[ac_driver]AC_AI_DISABLE\n"); ++ if (i2s_infor_record.record_pid != pid) { ++ return -EBUSY; ++ } ++ fh_I2S_stop_capture(i2s_config); ++ printk(" AC_AI_DISABLE\n"); ++ break; ++ case I2S_AO_DISABLE: ++ printk("[ac_driver]AC_AO_DISABLE\n"); ++ if (i2s_infor_record.play_pid != pid) { ++ return -EBUSY; ++ } ++ fh_I2S_stop_playback(i2s_config); ++ printk(" AC_AO_DISABLE\n"); ++ break; ++ case I2S_AI_PAUSE: ++ if (i2s_infor_record.record_pid != pid) { ++ return -EBUSY; ++ } ++ printk(KERN_INFO "capture pause\n"); ++ i2s_config->capture.state = STATE_PAUSE; ++ rx_status = readl(fh_i2s_module.regs + I2S_RXFIFO_CTRL);/*rx fifo disable*/ ++ rx_status = rx_status&(~I2S_ADC_FIFO_EN); ++ writel(rx_status, fh_i2s_module.regs + I2S_RXFIFO_CTRL);/*rx fifo disable*/ ++ break; ++ case I2S_AI_RESUME: ++ if (i2s_infor_record.record_pid != pid) { ++ return -EBUSY; ++ } ++ printk(KERN_INFO "capture resume\n"); ++ i2s_config->capture.state = STATE_RUN; ++ rx_status = readl( fh_i2s_module.regs + I2S_RXFIFO_CTRL);//clear rx fifo ++ rx_status = rx_status|I2S_ADC_FIFO_CLEAR; ++ writel(rx_status,fh_i2s_module.regs + I2S_RXFIFO_CTRL);/*enable rx fifo*/ ++ rx_status = rx_status&(~I2S_ADC_FIFO_CLEAR); ++ rx_status = rx_status|I2S_ADC_FIFO_EN; ++ writel(rx_status,fh_i2s_module.regs + I2S_RXFIFO_CTRL);/*enable rx fifo*/ ++ break; ++ case I2S_AO_PAUSE: ++ if (i2s_infor_record.play_pid != pid) { ++ return -EBUSY; ++ } ++ i2s_config->playback.state = STATE_PAUSE; ++ printk(KERN_INFO "playback pause\n"); ++ tx_status = readl(fh_i2s_module.regs + I2S_TXFIFO_CTRL);/*rx fifo disable*/ ++ tx_status = tx_status&(~I2S_DAC_FIFO_EN); ++ writel(tx_status, fh_i2s_module.regs + I2S_TXFIFO_CTRL);/*tx fifo disable*/ ++ break; ++ case I2S_AO_RESUME: ++ if (i2s_infor_record.play_pid != pid) { ++ return -EBUSY; ++ } ++ printk(KERN_INFO "playback resume\n"); ++ i2s_config->playback.state = STATE_RUN; ++ tx_status = readl( fh_i2s_module.regs + I2S_TXFIFO_CTRL);//clear rx fifo ++ tx_status = tx_status|I2S_DAC_FIFO_EN; ++ writel(tx_status,fh_i2s_module.regs + I2S_TXFIFO_CTRL); //enable tx fifo read enable ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++static int fh_i2s_open(struct inode *ip, struct file *fp) ++{ ++ ++ fp->private_data = &fh_i2s_dev.fh_i2s_miscdev; ++ ++ return 0; ++} ++ ++static u32 fh_i2s_poll(struct file *filp, poll_table *wait) ++{ ++ struct miscdevice *miscdev = filp->private_data; ++ struct i2s_dev *dev = container_of(miscdev, struct i2s_dev, fh_i2s_miscdev); ++ struct fh_i2s_cfg *i2s_config = &dev->i2s_config; ++ u32 mask = 0; ++ long avail; ++ if (STATE_RUN == i2s_config->capture.state) ++ { ++ poll_wait(filp,&i2s_config->readqueue,wait); ++ avail = i2s_avail_data_len(capture, i2s_config); ++ if (avail > i2s_config->capture.cfg.period_bytes) ++ { ++ mask |= POLLIN | POLLRDNORM; ++ } ++ } ++ if (STATE_RUN == i2s_config->playback.state) ++ { ++ poll_wait(filp,&i2s_config->writequeue,wait); ++ avail = i2s_avail_data_len(playback, i2s_config); ++ if (avail > i2s_config->playback.cfg.period_bytes) ++ { ++ mask |= POLLOUT | POLLWRNORM; ++ } ++ } ++ return mask; ++} ++ ++static int fh_i2s_read(struct file *filp, char __user *buf, size_t len, loff_t *off) ++{ ++ ++ int ret; ++ struct miscdevice *miscdev = filp->private_data; ++ struct i2s_dev *dev = container_of(miscdev, struct i2s_dev, fh_i2s_miscdev); ++ struct fh_i2s_cfg *i2s_config = &dev->i2s_config; ++ int after,left; ++ int pid,avail; ++ pid = current->tgid; ++ if (i2s_infor_record.record_pid != pid){ ++ return -EBUSY; ++ } ++ ++ avail = i2s_avail_data_len(capture, i2s_config); ++ if (avail > len) ++ { ++ avail = len; ++ } ++ after = avail + i2s_config->capture.appl_ptr; ++ if(after > i2s_config->capture.size) ++ { ++ left = avail - (i2s_config->capture.size - i2s_config->capture.appl_ptr); ++ ret = copy_to_user(buf, i2s_config->capture.area+i2s_config->capture.appl_ptr, i2s_config->capture.size-i2s_config->capture.appl_ptr); ++ ret = copy_to_user(buf+i2s_config->capture.size-i2s_config->capture.appl_ptr,i2s_config->capture.area,left); ++ spin_lock(&i2s_config->capture.lock); ++ i2s_config->capture.appl_ptr = left; ++ spin_unlock(&i2s_config->capture.lock); ++ } ++ else ++ { ++ ret = copy_to_user(buf,i2s_config->capture.area+i2s_config->capture.appl_ptr,avail); ++ spin_lock(&i2s_config->capture.lock); ++ i2s_config->capture.appl_ptr += avail; ++ spin_unlock(&i2s_config->capture.lock); ++ } ++ ++ return avail; ++ ++} ++ ++static int fh_i2s_write(struct file *filp, const char __user *buf, ++ size_t len, loff_t *off) ++{ ++ ++ struct miscdevice *miscdev = filp->private_data; ++ struct i2s_dev *dev = container_of(miscdev, struct i2s_dev, fh_i2s_miscdev); ++ struct fh_i2s_cfg *i2s_config = &dev->i2s_config; ++ int ret; ++ int after,left; ++ int pid,avail; ++ pid = current->tgid; ++ if (i2s_infor_record.play_pid != pid){ ++ return -EBUSY; ++ } ++ avail = i2s_avail_data_len(playback,i2s_config); ++ if (0 == avail) ++ { ++ return 0; ++ } ++ if (avail > len) ++ { ++ avail = len; ++ } ++ after = avail+i2s_config->playback.appl_ptr; ++ if(after > i2s_config->playback.size) ++ { ++ left = avail - (i2s_config->playback.size-i2s_config->playback.appl_ptr); ++ ret = copy_from_user(i2s_config->playback.area+i2s_config->playback.appl_ptr,buf,i2s_config->playback.size-i2s_config->playback.appl_ptr); ++ ret = copy_from_user(i2s_config->playback.area,buf+i2s_config->playback.size-i2s_config->playback.appl_ptr,left); ++ spin_lock(&i2s_config->playback.lock); ++ i2s_config->playback.appl_ptr = left; ++ spin_unlock(&i2s_config->playback.lock); ++ } ++ else ++ { ++ ret = copy_from_user(i2s_config->playback.area+i2s_config->playback.appl_ptr,buf,avail); ++ spin_lock(&i2s_config->playback.lock); ++ i2s_config->playback.appl_ptr += avail; ++ spin_unlock(&i2s_config->playback.lock); ++ } ++ ++ return avail; ++} ++ ++static irqreturn_t fh_i2s_interrupt(int irq, void *dev_id) ++{ ++#if 0 ++#ifndef CONFIG_MACH_FH8830_FPGA ++ u32 interrupts, rx_status; ++ struct fh_i2s_cfg *i2s_config = &fh_i2s_dev.i2s_config; ++ ++ interrupts = readl(fh_i2s_module.regs + I2S_CTRL); ++ //interrupts &= ~(0x3ff) << 16; ++ writel(interrupts, fh_i2s_module.regs + I2S_CTRL); ++ ++ if(interrupts & I2S_INTR_RX_UNDERFLOW) ++ { ++ fh_I2S_stop_capture(i2s_config); ++ fh_I2S_start_capture(i2s_config); ++ PRINT_i2s_DBG("I2S_INTR_RX_UNDERFLOW\n"); ++ } ++ ++ if(interrupts & I2S_INTR_RX_OVERFLOW) ++ { ++ if (i2s_config->capture.state == STATE_RUN) { ++ fh_I2S_stop_capture(i2s_config); ++ fh_I2S_start_capture(i2s_config); ++ } else { ++ rx_status = readl( fh_i2s_module.regs + I2S_RXFIFO_CTRL);//clear rx fifo ++ rx_status = rx_status|(1<<4); ++ writel(rx_status,fh_i2s_module.regs + I2S_RXFIFO_CTRL); ++ } ++ PRINT_i2s_DBG("I2S_INTR_RX_OVERFLOW\n"); ++ } ++ ++ if(interrupts & I2S_INTR_TX_UNDERFLOW) ++ { ++ fh_I2S_stop_playback(i2s_config); ++ fh_I2S_start_playback(i2s_config); ++ PRINT_i2s_DBG("I2S_INTR_TX_UNDERFLOW\n"); ++ } ++ ++ if(interrupts & I2S_INTR_TX_OVERFLOW) ++ { ++ fh_I2S_stop_playback(i2s_config); ++ fh_I2S_start_playback(i2s_config); ++ PRINT_i2s_DBG("I2S_INTR_TX_OVERFLOW\n"); ++ } ++ ++ PRINT_i2s_DBG("interrupts: 0x%x\n", interrupts); ++#endif ++#endif ++ return IRQ_HANDLED; ++} ++ ++static const struct file_operations I2S_fops = ++{ ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = fh_i2s_ioctl, ++ .release = fh_i2s_close, ++ .open = fh_i2s_open, ++ .poll = fh_i2s_poll, ++ .read = fh_i2s_read, ++ .write = fh_i2s_write, ++ ++}; ++ ++static int __devinit fh_i2s_drv_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct resource *irq_res, *mem; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) ++ return -EINVAL; ++ printk("I2S probe\n"); ++ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), ++ "fh_fh8830_i2s_module")) ++ return -ENOMEM; ++ printk("I2S :%d\n",__LINE__); ++ PRINT_i2s_DBG("%d\n",__LINE__); ++ fh_i2s_module.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); ++ PRINT_i2s_DBG("probe: regs %p\n",fh_i2s_module.regs); ++ if (!fh_i2s_module.regs){ ++ ret = -ENOMEM; ++ goto remap_fail; ++ } ++ ++ fh_i2s_module.clk = clk_get(NULL, "ac_clk"); ++ if (!fh_i2s_module.clk) { ++ ret = -EINVAL; ++ goto clk_fail; ++ } ++ clk_enable(fh_i2s_module.clk); ++ PRINT_i2s_DBG("%d\n",__LINE__); ++ spin_lock_init(&fh_i2s_module.lock); ++ ++ ret = misc_register(&fh_i2s_dev.fh_i2s_miscdev); ++ ++ if (ret) ++ goto out_disable_clk; ++ ++ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!irq_res) ++ { ++ pr_err("%s: ERROR: getting resource failed" ++ "cannot get IORESOURCE_IRQ\n", __func__); ++ ret = -ENXIO; ++ goto out_disable_clk; ++ } ++ fh_i2s_module.irq = irq_res->start; ++ ret = request_irq(fh_i2s_module.irq, fh_i2s_interrupt, IRQF_SHARED, "i2s", &fh_i2s_module); ++ ret = readl(fh_i2s_module.regs + I2S_DBG_CTL); ++ ret = ret | I2S_EXT_EN| I2S_EN; ++ writel(ret,fh_i2s_module.regs + I2S_DBG_CTL); ++ return 0; ++ ++out_disable_clk: ++ clk_disable(fh_i2s_module.clk); ++ fh_i2s_module.clk = NULL; ++clk_fail: ++ devm_iounmap(&pdev->dev, fh_i2s_module.regs); ++ fh_i2s_module.regs = NULL; ++remap_fail: ++ devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); ++ return ret; ++} ++ ++static int __devexit fh_I2S_drv_remove(struct platform_device *pdev) ++{ ++ struct resource *mem; ++ misc_deregister(&fh_i2s_dev.fh_i2s_miscdev); ++ ++ free_irq(fh_i2s_module.irq, &fh_i2s_module); ++ ++ if (fh_i2s_module.clk) { ++ clk_disable(fh_i2s_module.clk); ++ clk_put(fh_i2s_module.clk); ++ } ++ if (fh_i2s_module.regs) { ++ devm_iounmap(&pdev->dev, fh_i2s_module.regs); ++ } ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (mem) { ++ devm_release_mem_region(&pdev->dev, mem->start, resource_size(mem)); ++ } ++ printk("I2S remove ok\n"); ++ return 0; ++} ++ ++static struct platform_driver fh_i2s_driver = ++{ ++ .probe = fh_i2s_drv_probe, ++ .remove = __devexit_p(fh_I2S_drv_remove), ++ .driver = { ++ .name = "fh_fh8830_i2s", ++ .owner = THIS_MODULE, ++ } ++}; ++ ++void i2s_prealloc_dma_buffer(struct fh_i2s_cfg *i2s_config) ++{ ++ int pg; ++ gfp_t gfp_flags; ++ pg = get_order(I2S_DMA_PREALLOC_SIZE); ++ gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN; ++ i2s_config->capture.dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ i2s_config->capture.area = dma_alloc_coherent(&i2s_config->capture.dev, PAGE_SIZE << pg, &i2s_config->capture.addr, gfp_flags ); ++ if (!i2s_config->capture.area) ++ { ++ printk(KERN_ERR"no enough mem for capture buffer alloc\n"); ++ return ; ++ } ++ i2s_config->playback.dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ i2s_config->playback.area = dma_alloc_coherent(&i2s_config->playback.dev, PAGE_SIZE << pg, &i2s_config->playback.addr, gfp_flags ); ++ if (!i2s_config->playback.area) ++ { ++ printk(KERN_ERR"no enough mem for playback buffer alloc\n"); ++ return ; ++ } ++} ++ ++void i2s_free_prealloc_dma_buffer(struct fh_i2s_cfg *i2s_config) ++{ ++ int pg; ++ pg = get_order(I2S_DMA_PREALLOC_SIZE); ++ dma_free_coherent(&i2s_config->capture.dev, PAGE_SIZE<<pg, i2s_config->capture.area, i2s_config->capture.addr); ++ dma_free_coherent(&i2s_config->playback.dev, PAGE_SIZE<<pg, i2s_config->playback.area, i2s_config->playback.addr); ++} ++ ++static void init_i2s_mutex(struct fh_i2s_cfg *i2s_config) ++{ ++ sema_init(&i2s_config->sem_capture, 1); ++ sema_init(&i2s_config->sem_playback, 1); ++} ++ ++int i2s_request_dma_channel(void) ++{ ++ dma_cap_mask_t mask; ++ /*request i2s rx dma channel*/ ++ dma_rx_transfer = kzalloc(sizeof(struct fh_dma_chan), GFP_KERNEL); ++ if (!dma_rx_transfer) ++ { ++ printk(KERN_ERR"alloc dma_rx_transfer failed\n"); ++ goto mem_fail; ++ } ++ memset(dma_rx_transfer, 0, sizeof(struct fh_dma_chan)); ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_rx_transfer->chan = dma_request_channel(mask, fh_I2S_dma_chan_filter, &fh_i2s_dev.channel_assign.capture_channel); ++ if (!dma_rx_transfer->chan) ++ { ++ printk(KERN_ERR"request i2s rx dma channel failed \n"); ++ goto channel_fail; ++ } ++ ++ /*request i2s tx dma channel*/ ++ dma_tx_transfer = kzalloc(sizeof(struct fh_dma_chan), GFP_KERNEL); ++ if (!dma_tx_transfer) ++ { ++ printk(KERN_ERR"alloc dma_tx_transfer failed\n"); ++ goto mem_fail; ++ } ++ memset(dma_tx_transfer, 0, sizeof(struct fh_dma_chan)); ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_tx_transfer->chan = dma_request_channel(mask, fh_I2S_dma_chan_filter, &fh_i2s_dev.channel_assign.playback_channel); ++ if (!dma_tx_transfer->chan) ++ { ++ printk(KERN_ERR"request dma channel failed \n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++channel_fail: ++ if (!dma_rx_transfer->chan) ++ { ++ dma_release_channel(dma_rx_transfer->chan); ++ dma_rx_transfer->chan = NULL; ++ } ++ if (!dma_tx_transfer->chan) ++ { ++ dma_release_channel(dma_tx_transfer->chan); ++ dma_tx_transfer->chan = NULL; ++ } ++ ++mem_fail: ++ if (dma_rx_transfer != NULL) ++ { ++ kfree(dma_rx_transfer); ++ dma_rx_transfer = NULL; ++ } ++ if (dma_tx_transfer != NULL) ++ { ++ kfree(dma_tx_transfer); ++ dma_tx_transfer = NULL; ++ } ++ ++ return -EFAULT; ++} ++ ++void i2s_release_dma_channel(void) ++{ ++ /*release i2s tx dma channel*/ ++ if (dma_tx_transfer != NULL) ++ { ++ if (dma_tx_transfer->chan) { ++ dma_release_channel(dma_tx_transfer->chan); ++ dma_tx_transfer->chan = NULL; ++ } ++ kfree(dma_tx_transfer); ++ dma_tx_transfer = NULL; ++ } ++ ++ /*release i2s rx dma channel*/ ++ if (dma_rx_transfer != NULL) ++ { ++ if (dma_rx_transfer->chan) { ++ dma_release_channel(dma_rx_transfer->chan); ++ dma_rx_transfer->chan = NULL; ++ } ++ ++ kfree(dma_rx_transfer); ++ dma_rx_transfer = NULL; ++ } ++ ++ ++} ++static void create_fh8830_i2s_proc(void); ++static void remove_fh8830_i2s_proc(void); ++static int __init fh_i2s_init(void) ++{ ++ int status; ++ init_i2s_mutex(&fh_i2s_dev.i2s_config); ++ ++ i2s_prealloc_dma_buffer(&fh_i2s_dev.i2s_config); ++ ++ status = i2s_request_dma_channel(); ++ if(status) ++ printk("fh i2s init fail status=0x%x\n",status); ++ create_fh8830_i2s_proc(); ++ return platform_driver_register(&fh_i2s_driver); ++} ++module_init(fh_i2s_init); ++ ++static void __exit fh_i2s_exit(void) ++{ ++ ++ remove_fh8830_i2s_proc(); ++ i2s_release_dma_channel(); ++ i2s_free_prealloc_dma_buffer(&fh_i2s_dev.i2s_config); ++ platform_driver_unregister(&fh_i2s_driver); ++} ++module_exit(fh_i2s_exit); ++ ++MODULE_AUTHOR("FH_i2s"); ++MODULE_DESCRIPTION("FH_i2s"); ++MODULE_LICENSE("GPL"); ++ ++/****************************debug proc*****************************/ ++#include <linux/proc_fs.h> ++#include <asm/unistd.h> ++struct proc_dir_entry *proc_ac_entry; ++#define proc_name "fh_fh8830_i2s" ++#define I2S_TEST_LOOP 1 ++#define I2S_TEST_OUT 0 ++ssize_t proc_ac_read(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ ssize_t len = 0; ++ int i; ++ unsigned int reg; ++ unsigned int *data_addr; ++ unsigned int file_len; ++ struct file *fp; ++ loff_t pos; ++ mm_segment_t old_fs; ++ for (i = 0;i <= 0x1C;i += 4) { ++ printk(KERN_INFO"0x%x reg = 0x%x\n",i, readl(fh_i2s_module.regs + i)); ++ } ++ for (i = 80;i <= 0xd0;i += 4) { ++ printk(KERN_INFO"0x%x reg = 0x%x\n",i, readl(fh_i2s_module.regs + i)); ++ } ++ printk("loop test start __________\n"); ++ writel(0xe0000000,fh_i2s_module.regs + I2S_CTRL);// ctrl ++ writel(0x1,fh_i2s_module.regs + I2S_TXFIFO_CTRL);// tx ++ writel(0x1,fh_i2s_module.regs + I2S_RXFIFO_CTRL);// rx ++ writel(0x1 <<12 |0x3,fh_i2s_module.regs + I2S_DBG_CTL);// loop ++ ++ writel(0x1000000,0xfe0901ac); ++ i = 0; ++ data_addr = kzalloc(4096*4, GFP_KERNEL); ++ if (!data_addr) ++ { ++ printk("alloc dma_rx_transfer failed\n"); ++ } ++ memset(data_addr, 0, 4096*4); ++ mdelay(1000); ++ while (1) { ++#if I2S_TEST_LOOP ++ reg =0xff & readl(fh_i2s_module.regs + 0x0c); ++ ++ if(reg >0){ ++ reg = readl(fh_i2s_module.regs +0x200); ++ writel(reg,fh_i2s_module.regs + 0x100); ++ } ++ ++#endif ++ ++ ++#if I2S_TEST_OUT ++ reg =0xff00 & readl(fh_i2s_module.regs + 0x0c); ++ reg = reg>>8; ++ // printk("write dac date reg = %x \n ",reg); ++ if (reg < 0x40) { ++ writel(i, fh_i2s_module.regs + 0x100); ++ writel(i, fh_i2s_module.regs + 0x300); ++ ++ ++ } ++ i = i+0x200; ++ if(i >= 0xffffff) ++ i = 0; ++ // printk("water level 0x%x\n",readl(fh_i2s_module.regs + 0x0c)); ++ ++#endif ++ } ++//TEST I2S_INPUT TO FILE ++ pos =0; ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ fp = filp_open("/home/test",O_RDWR|O_CREAT,0644); ++ if(IS_ERR(fp)){ ++ printk("file is error\n"); ++ return 1; ++ ++ } ++ file_len = fp->f_op->write(fp,(void*)data_addr,4096,&pos); ++ printk("write len is %d\n",len); ++ set_fs(old_fs); ++ filp_close(fp,NULL); ++ printk("loop test stop ___________\n"); ++ for (i = 0;i <= 0x1C;i += 4) { ++ printk(KERN_INFO"0x%x reg = 0x%x\n",i, readl(fh_i2s_module.regs + i)); ++ } ++ for (i = 80;i <= 0xd0;i += 4) { ++ printk(KERN_INFO"0x%x reg = 0x%x\n",i, readl(fh_i2s_module.regs + i)); ++ } ++ return len; ++} ++ ++static void create_fh8830_i2s_proc(void) ++{ ++ proc_ac_entry = create_proc_entry(proc_name, S_IRUGO, NULL); ++ if (!proc_ac_entry) ++ { ++ printk(KERN_ERR"create proc failed\n"); ++ } ++ else ++ { ++ proc_ac_entry->read_proc = proc_ac_read; ++ } ++} ++ ++static void remove_fh8830_i2s_proc(void) ++{ ++ remove_proc_entry(proc_name, NULL); ++} +diff --git a/drivers/misc/fh_i2s.h b/drivers/misc/fh_i2s.h +new file mode 100644 +index 00000000..7f067a76 +--- /dev/null ++++ b/drivers/misc/fh_i2s.h +@@ -0,0 +1,35 @@ ++#ifndef __FH_LINBA0_I2S_H ++#define __FH_LINBA0_I2S_H ++ ++#define FH_I2S_IOCTL_MEM_BASE 'M' ++#define I2S_INIT_CAPTURE_MEM _IOWR(FH_I2S_IOCTL_MEM_BASE, 0, int) ++#define I2S_INIT_PLAYBACK_MEM _IOWR(FH_I2S_IOCTL_MEM_BASE, 1, int) ++ ++#define FH_I2S_IOCTL_PARAM_BASE 'P' ++#define I2S_SET_VOL _IOWR(FH_I2S_IOCTL_PARAM_BASE, 0, int) ++#define I2S_SET_INPUT_MODE _IOWR(FH_I2S_IOCTL_PARAM_BASE, 1, int) ++#define I2S_SET_OUTPUT_MODE _IOWR(FH_I2S_IOCTL_PARAM_BASE, 2, int) ++ ++#define FH_I2S_IOCTL_ENA_BASE 'E' ++#define I2S_AI_EN _IOWR(FH_I2S_IOCTL_ENA_BASE, 0, int) ++#define I2S_AO_EN _IOWR(FH_I2S_IOCTL_ENA_BASE, 1, int) ++#define I2S_AI_DISABLE _IOWR(FH_I2S_IOCTL_ENA_BASE, 2, int) ++#define I2S_AO_DISABLE _IOWR(FH_I2S_IOCTL_ENA_BASE, 3, int) ++#define I2S_AI_PAUSE _IOWR(FH_I2S_IOCTL_ENA_BASE, 4, int) ++#define I2S_AI_RESUME _IOWR(FH_I2S_IOCTL_ENA_BASE, 5, int) ++#define I2S_AO_PAUSE _IOWR(FH_I2S_IOCTL_ENA_BASE, 6, int) ++#define I2S_AO_RESUME _IOWR(FH_I2S_IOCTL_ENA_BASE, 7, int) ++ ++ ++struct fh_i2s_cfg_arg{ ++ ++ int volume; ++ int rate; ++ int frame_bit; ++ int channels; ++ int buffer_size; ++ int period_size; ++}; ++ ++#endif ++ +diff --git a/drivers/misc/fh_pinctrl_dev.c b/drivers/misc/fh_pinctrl_dev.c +new file mode 100644 +index 00000000..c8790f40 +--- /dev/null ++++ b/drivers/misc/fh_pinctrl_dev.c +@@ -0,0 +1,279 @@ ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/pwm.h> ++#include <linux/printk.h> ++#include <linux/fs.h> ++#include <linux/miscdevice.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++#include <asm/uaccess.h> ++#include "fh_pinctrl_dev.h" ++ ++#define FH_PINCTRL_PROC_FILE "driver/pinctrl" ++ ++#undef FH_PINCTRL_DEBUG ++#ifdef FH_PINCTRL_DEBUG ++#define PRINT_DBG(fmt,args...) printk(fmt,##args) ++#else ++#define PRINT_DBG(fmt,args...) do{} while(0) ++#endif ++ ++struct proc_dir_entry *pinctrl_proc_file; ++ ++static int fh_pinctrl_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_pinctrl_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++ ++static long fh_pinctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ ++ if (unlikely(_IOC_TYPE(cmd) != PINCTRL_IOCTL_MAGIC)) ++ { ++ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n", ++ __func__, _IOC_TYPE(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (unlikely(_IOC_NR(cmd) > PINCTRL_IOCTL_MAXNR)) ++ { ++ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ { ++ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ else if(_IOC_DIR(cmd) & _IOC_WRITE) ++ { ++ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++ } ++ ++ if(ret) ++ { ++ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -EACCES); ++ return -EACCES; ++ } ++ ++ switch(cmd) ++ { ++ ++ } ++ ++ return ret; ++} ++ ++static const struct file_operations fh_pinctrl_fops = ++{ ++ .owner = THIS_MODULE, ++ .open = fh_pinctrl_open, ++ .release = fh_pinctrl_release, ++ .unlocked_ioctl = fh_pinctrl_ioctl, ++}; ++ ++static struct miscdevice fh_pinctrl_misc = ++{ ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEVICE_NAME, ++ .fops = &fh_pinctrl_fops, ++}; ++ ++static void del_char(char* str,char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while(*q) ++ { ++ if (*q !=ch) ++ { ++ *p++ = *q; ++ } ++ q++; ++ } ++ *p='\0'; ++} ++ ++static ssize_t fh_pinctrl_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off) ++{ ++ int i; ++ char message[32] = {0}; ++ char * const delim = ","; ++ char *cur = message; ++ char* param_str[4]; ++ unsigned int param[4]; ++ ++ len = (len > 32) ? 32 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ for(i=0; i<4; i++) ++ { ++ param_str[i] = strsep(&cur, delim); ++ if(!param_str[i]) ++ { ++ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i); ++ pr_err("[dev/mux], [dev name], [mux name], [func sel]\n"); ++ return -EINVAL; ++ } ++ else ++ { ++ del_char(param_str[i], ' '); ++ del_char(param_str[i], '\n'); ++ } ++ } ++ ++ if(!strcmp(param_str[0], "dev")) ++ { ++ fh_pinctrl_sdev(param_str[1], 0); ++ } ++ else if(!strcmp(param_str[0], "mux")) ++ { ++ param[3] = (u32)simple_strtoul(param_str[3], NULL, 10); ++ if(param[3] < 0) ++ { ++ pr_err("ERROR: parameter[3] is incorrect\n"); ++ return -EINVAL; ++ } ++ fh_pinctrl_smux(param_str[1], param_str[2], param[3], 0); ++ } ++ else ++ { ++ pr_err("ERROR: parameter[0] is incorrect\n" ++ "[dev/mux], [dev name], [mux name], [func sel]\n"); ++ return -EINVAL; ++ } ++ ++ return len; ++} ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else ++ { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ ++ fh_pinctrl_prt(sfile); ++ return 0; ++} ++ ++static const struct seq_operations isp_seq_ops = ++{ ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_pinctrl_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &isp_seq_ops); ++} ++ ++static struct file_operations fh_pinctrl_proc_ops = ++{ ++ .owner = THIS_MODULE, ++ .open = fh_pinctrl_proc_open, ++ .read = seq_read, ++ .write = fh_pinctrl_proc_write, ++ .release = seq_release, ++}; ++ ++ ++static int __devinit fh_pinctrl_probe(struct platform_device *pdev) ++{ ++ int err; ++ ++ err = misc_register(&fh_pinctrl_misc); ++ ++ if(err < 0) ++ { ++ pr_err("%s: ERROR: %s registration failed", ++ __func__, DEVICE_NAME); ++ return -ENXIO; ++ } ++ ++ pinctrl_proc_file = create_proc_entry(FH_PINCTRL_PROC_FILE, 0644, NULL); ++ ++ if (pinctrl_proc_file) ++ pinctrl_proc_file->proc_fops = &fh_pinctrl_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, DEVICE_NAME); ++ ++ return 0; ++} ++ ++static int __exit fh_pinctrl_remove(struct platform_device *pdev) ++{ ++ misc_deregister(&fh_pinctrl_misc); ++ return 0; ++} ++ ++static struct platform_driver fh_pinctrl_driver = ++{ ++ .driver = ++ { ++ .name = DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_pinctrl_probe, ++ .remove = __exit_p(fh_pinctrl_remove), ++}; ++ ++static int __init fh_pinctrl_dev_init(void) ++{ ++ return platform_driver_register(&fh_pinctrl_driver); ++} ++ ++static void __exit fh_pinctrl_dev_exit(void) ++{ ++ ++ platform_driver_unregister(&fh_pinctrl_driver); ++ ++} ++ ++module_init(fh_pinctrl_dev_init); ++module_exit(fh_pinctrl_dev_exit); ++ ++ ++MODULE_AUTHOR("fullhan"); ++ ++MODULE_DESCRIPTION("FH PINCTRL driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR); +diff --git a/drivers/misc/fh_pinctrl_dev.h b/drivers/misc/fh_pinctrl_dev.h +new file mode 100644 +index 00000000..8fbf6c0e +--- /dev/null ++++ b/drivers/misc/fh_pinctrl_dev.h +@@ -0,0 +1,18 @@ ++ ++#ifndef FH_PINCTRL_DEV_H_ ++#define FH_PINCTRL_DEV_H_ ++ ++#include <linux/slab.h> ++#include <linux/ioctl.h> ++#include <mach/pinctrl.h> ++ ++ ++#define DEVICE_NAME "fh_pinctrl" ++ ++ ++#define PINCTRL_IOCTL_MAGIC 'p' ++ ++#define PINCTRL_IOCTL_MAXNR 8 ++ ++ ++#endif /* FH_PINCTRL_DEV_H_ */ +diff --git a/drivers/misc/fh_sadc.c b/drivers/misc/fh_sadc.c +new file mode 100644 +index 00000000..54925642 +--- /dev/null ++++ b/drivers/misc/fh_sadc.c +@@ -0,0 +1,557 @@ ++/* ++ * fh_sadc.c ++ * ++ * Created on: Mar 13, 2015 ++ * Author: duobao ++ */ ++#include <linux/uaccess.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++/***************************************************************************** ++ * Include Section ++ * add all #include here ++ *****************************************************************************/ ++#include <mach/fh_sadc.h> ++#include <mach/pmu.h> ++ ++/***************************************************************************** ++ * Define section ++ * add all #define here ++ *****************************************************************************/ ++#define wrap_readl(wrap, name) \ ++ __raw_readl(&(((struct wrap_sadc_reg *)wrap->regs)->name)) ++ ++#define wrap_writel(wrap, name, val) \ ++ __raw_writel((val), &(((struct wrap_sadc_reg *)wrap->regs)->name)) ++ ++ ++#if defined(CONFIG_FH_SADC_V11) ++#define SADC_REF (1800) ++#define SADC_MAX_AD_VALUE (0xfff) ++#else ++#define SADC_REF (3300) ++#define SADC_MAX_AD_VALUE (0x3ff) ++#endif ++ ++#define IOCTL_GET_SADC_DATA 1 ++#define IOCTL_SADC_POWER_DOWN 0xff ++#define SADC_WRAP_BASE (0xf1200000) ++#define SADC_IRQn (23) ++#define SADC_MAX_CONTROLLER (1) ++#define SADC_STATUS_COLESD (0) ++#define SADC_STATUS_OPEN (1) ++#define FH_SADC_PLAT_DEVICE_NAME "fh_sadc" ++#define FH_SADC_MISC_DEVICE_NAME "fh_sadc" ++/**************************************************************************** ++* ADT section ++* add definition of user defined Data Type that only be used in this file here ++***************************************************************************/ ++struct sadc_info { ++ int channel; ++ int sadc_data; ++}; ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Global variables section - Exported ++ * add declaration of global variables that will be exported here ++ * e.g. ++ * int8_t foo; ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++static u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc,\ ++ u32 channel, u16 *buf); ++static int fh_sadc_open(struct inode *inode, struct file *file); ++static int fh_sadc_release(struct inode *inode, struct file *filp); ++static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,\ ++ unsigned long arg); ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++static struct wrap_sadc_obj fh_sadc_obj; ++ ++static const struct file_operations fh_sadc_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_sadc_open, ++ .release = fh_sadc_release, ++ .unlocked_ioctl = fh_sadc_ioctl, ++}; ++ ++static struct miscdevice fh_sadc_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = FH_SADC_MISC_DEVICE_NAME, ++ .fops = &fh_sadc_fops, ++}; ++ ++/***************************************************************************** ++ * ++ * ++ * function body ++ * ++ * ++ *****************************************************************************/ ++u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, u32 channel, ++ u16 *buf) { ++ u32 xainsel = 1 << channel; ++ u32 xversel = 0; ++ u32 xpwdb = 1; ++ /*cnt*/ ++ u32 sel2sam_pre_cnt = 2; ++ u32 sam_cnt = 2; ++ u32 sam2sel_pos_cnt = 2; ++ /*time out*/ ++ u32 eoc_tos = 0xff; ++ u32 eoc_toe = 0xff; ++ u32 time_out = 0xffff; ++ /*set isr en..*/ ++ u32 sadc_isr = 0x01; ++ /*start*/ ++ u32 sadc_cmd = 0x01; ++ /*get data*/ ++ u32 temp_data = 0; ++ u32 ret_time; ++ ++ /*control...*/ ++ wrap_writel(sadc, sadc_control, xainsel | (xversel << 8) \ ++ | (xpwdb << 12)); ++ ++ wrap_writel(sadc, sadc_cnt, ++ sel2sam_pre_cnt | (sam_cnt << 8) | \ ++ (sam2sel_pos_cnt << 16)); ++ ++ wrap_writel(sadc, sadc_timeout, ++ eoc_tos | (eoc_toe << 8) | (time_out << 16)); ++ ++ wrap_writel(sadc, sadc_ier, sadc_isr); ++ ++ wrap_writel(sadc, sadc_cmd, sadc_cmd); ++ ++ ret_time = wait_for_completion_timeout(&sadc->done, 5000); ++ if (ret_time == 0) { ++ printk(KERN_ERR "sadc timeout..\n"); ++ return SADC_TIMEOUT; ++ } ++ ++ switch (channel) { ++ case 0: ++ case 1: ++ /*read channel 0 1*/ ++ temp_data = wrap_readl(sadc, sadc_dout0); ++ break; ++ ++ case 2: ++ case 3: ++ /*read channel 2 3*/ ++ temp_data = wrap_readl(sadc, sadc_dout1); ++ break; ++ ++ case 4: ++ case 5: ++ /*read channel 4 5*/ ++ temp_data = wrap_readl(sadc, sadc_dout2); ++ break; ++ ++ case 6: ++ case 7: ++ /*read channel 6 7*/ ++ temp_data = wrap_readl(sadc, sadc_dout3); ++ break; ++ default: ++ break; ++ } ++ if (channel % 2) { ++ /*read low 16bit*/ ++ *buf = (u16) (temp_data & 0xffff); ++ } else { ++ /*read high 16bit*/ ++ *buf = (u16) (temp_data >> 16); ++ } ++ return 0; ++ ++} ++EXPORT_SYMBOL(fh_sadc_isr_read_data); ++ ++ ++int fh_sadc_enable(void) ++{ ++ u32 control_reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg |= 1 << 12; ++ wrap_writel(sadc, sadc_control, control_reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_enable); ++ ++int fh_sadc_disable(void) ++{ ++ u32 control_reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg &= ~(1 << 12); ++ wrap_writel(sadc, sadc_control, control_reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_disable); ++ ++static irqreturn_t fh_sadc_isr(int irq, void *dev_id) ++{ ++ ++ u32 isr_status; ++ struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) dev_id; ++ ++ isr_status = wrap_readl(sadc, sadc_int_status); ++ if (isr_status & 0x01) { ++ ++ u32 sadc_isr = 0x00; ++ wrap_writel(sadc, sadc_ier, sadc_isr); ++ ++ wrap_writel(sadc, sadc_int_status, isr_status); ++ complete(&(sadc->done)); ++ } else { ++ ++ printk(KERN_ERR "sadc maybe error!\n"); ++ } ++ return IRQ_HANDLED; ++} ++ ++long fh_sadc_get_value(int channel) ++{ ++ unsigned int ret; ++ long w = 0; ++ u16 ad_raw_data; ++ if (channel < 0) { ++ printk(KERN_ERR "ERROR: %s, sadc channel no %d is incorrect\n", ++ __func__, channel); ++ return 0; ++ } ++ ++ fh_sadc_enable(); ++ ++ ret = fh_sadc_isr_read_data(&fh_sadc_obj, channel, &ad_raw_data); ++ ++ if (ret != 0) { ++ printk(KERN_INFO "sadc error code:0x%x\n", ret); ++ } else { ++ w = ad_raw_data * SADC_REF / SADC_MAX_AD_VALUE; ++ printk(KERN_INFO "the value of sadc is: %ld\n", w); ++ } ++ ++ return w; ++} ++EXPORT_SYMBOL(fh_sadc_get_value); ++ ++static void del_char(char *str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) ++ *p++ = *q; ++ q++; ++ } ++ *p = '\0'; ++} ++ ++static ssize_t fh_sadc_proc_write(struct file *filp, const char *buf, ++ size_t len, loff_t *off) ++{ ++ char message[32] = {0}; ++ char * const delim = ","; ++ char *cur = message, *power_str; ++ int power; ++ unsigned int str_len; ++ str_len = 10; ++ len = (len > 32) ? 32 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ power_str = strsep(&cur, delim); ++ if (!power_str) { ++ pr_err("%s: ERROR: parameter is empty\n", __func__); ++ return -EINVAL; ++ } else { ++ del_char(power_str, ' '); ++ del_char(power_str, '\n'); ++ power = kstrtouint(power_str, 0, &str_len); ++ if (power < 0) { ++ pr_err("%s: ERROR: parameter is incorrect\n",\ ++ __func__); ++ return -EINVAL; ++ } ++ } ++ ++ power ? fh_sadc_enable() : fh_sadc_disable(); ++ ++ return len; ++} ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter; ++ counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ int i; ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ u32 ret; ++ ++ reg = (wrap_readl(sadc, sadc_control) & 0x1000); ++ ++ seq_printf(sfile, "\nSADC Status:\n"); ++ seq_printf(sfile, "Power %s\n\n", reg ? "up" : "down"); ++ ++ for (i = 0; i < 8; i++) { ++ u16 ad_raw_data; ++ ret = fh_sadc_isr_read_data(&fh_sadc_obj, i, &ad_raw_data); ++ if (ret != 0) ++ seq_printf(sfile, "sadc error code:0x%x\n", ret); ++ else ++ seq_printf(sfile, "channel: %d \tvalue: %u\n", i, ++ ad_raw_data * SADC_REF / SADC_MAX_AD_VALUE); ++ } ++ return 0; ++} ++ ++static const struct seq_operations isp_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_sadc_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &isp_seq_ops); ++} ++ ++static const struct file_operations fh_sadc_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_sadc_proc_open, ++ .read = seq_read, ++ .write = fh_sadc_proc_write, ++ .release = seq_release, ++}; ++ ++static int __devinit fh_sadc_probe(struct platform_device *pdev) ++{ ++ int err; ++ struct resource *res; ++ struct clk *sadc_clk; ++ ++ sadc_clk = clk_get(&pdev->dev, "sadc_clk"); ++ if (IS_ERR(sadc_clk)) { ++ err = PTR_ERR(sadc_clk); ++ return -EPERM; ++ } ++ clk_enable(sadc_clk); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "sadc get platform source error..\n"); ++ return -ENODEV; ++ } ++ ++ fh_sadc_obj.irq_no = platform_get_irq(pdev, 0); ++ if (fh_sadc_obj.irq_no < 0) { ++ dev_warn(&pdev->dev, "sadc interrupt is not available.\n"); ++ return fh_sadc_obj.irq_no; ++ } ++ ++ res = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "sadc region already claimed\n"); ++ return -EBUSY; ++ } ++ ++ fh_sadc_obj.regs = ioremap(res->start, resource_size(res)); ++ if (fh_sadc_obj.regs == NULL) { ++ err = -ENXIO; ++ goto fail_no_ioremap; ++ } ++ ++ init_completion(&fh_sadc_obj.done); ++ mutex_init(&fh_sadc_obj.sadc_lock); ++ fh_sadc_obj.active_channel_no = 0; ++ ++ err = request_irq(fh_sadc_obj.irq_no, fh_sadc_isr, 0,\ ++ dev_name(&pdev->dev),\ ++ &fh_sadc_obj); ++ if (err) { ++ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err); ++ err = -ENXIO; ++ goto err_irq; ++ } ++ ++ err = misc_register(&fh_sadc_misc); ++ ++ if (err < 0) { ++ pr_err("%s: ERROR: %s registration failed", __func__, ++ FH_SADC_MISC_DEVICE_NAME); ++ err = -ENXIO; ++ goto misc_error; ++ } ++ ++ fh_sadc_obj.proc_file = create_proc_entry(FH_SADC_PROC_FILE, ++ 0644, NULL); ++ ++ if (fh_sadc_obj.proc_file) ++ fh_sadc_obj.proc_file->proc_fops = &fh_sadc_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, "SADC"); ++ ++ return 0; ++ ++misc_error: ++ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj); ++ ++err_irq: ++ iounmap(fh_sadc_obj.regs); ++ ++fail_no_ioremap: ++ release_mem_region(res->start, resource_size(res)); ++ ++ return err; ++} ++ ++static int __exit fh_sadc_remove(struct platform_device *pdev) ++{ ++ ++ struct resource *res; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ misc_deregister(&fh_sadc_misc); ++ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj); ++ iounmap(fh_sadc_obj.regs); ++ release_mem_region(res->start, resource_size(res)); ++ return 0; ++ ++} ++ ++ ++static int fh_sadc_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_sadc_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++static long fh_sadc_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) { ++ ++ u32 ad_data; ++ u32 control_reg; ++ u16 ad_raw_data; ++ struct sadc_info sadc_info; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ mutex_lock(&sadc->sadc_lock); ++ if (cmd == IOCTL_GET_SADC_DATA) { ++ if (copy_from_user((void *) &sadc_info, (void __user*) arg, ++ sizeof(sadc_info))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ if ((wrap_readl(sadc, sadc_status2) & 0x10)) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EBUSY; ++ } ++ fh_sadc_isr_read_data(&fh_sadc_obj, sadc_info.channel,\ ++ &ad_raw_data); ++ ad_data = ad_raw_data * SADC_REF; ++ ad_data /= SADC_MAX_AD_VALUE; ++ sadc_info.sadc_data = ad_data; ++ if (put_user(sadc_info.sadc_data, ++ (int __user *)(&((struct sadc_info *)arg)\ ++ ->sadc_data))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ } ++ ++ else if (cmd == IOCTL_SADC_POWER_DOWN) { ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg &= ~(1 << 12); ++ wrap_writel(sadc, sadc_control, control_reg); ++ } ++ mutex_unlock(&sadc->sadc_lock); ++ return 0; ++} ++ ++ ++/******************* ++ * ++ * ++ *add platform cause of i need the board info... ++ *in the probe function. i will register the sadc ++ *misc drive...then the app can open the sadc misc device.. ++ * ++ ******************/ ++static struct platform_driver fh_sadc_driver = { ++ .driver = { ++ .name = FH_SADC_PLAT_DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_sadc_probe, ++ .remove = __exit_p(fh_sadc_remove), ++}; ++ ++ ++ ++static int __init fh_sadc_init(void) ++{ ++ return platform_driver_register(&fh_sadc_driver); ++} ++ ++static void __exit fh_sadc_exit(void) ++{ ++ ++ platform_driver_unregister(&fh_sadc_driver); ++ ++} ++ ++module_init(fh_sadc_init); ++module_exit(fh_sadc_exit); ++ ++MODULE_DESCRIPTION("fh sadc driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("zhangy@fullhan.com"); ++MODULE_ALIAS("platform:FH_sadc"); +diff --git a/drivers/misc/fh_sadc_v2.c b/drivers/misc/fh_sadc_v2.c +new file mode 100644 +index 00000000..482e1ded +--- /dev/null ++++ b/drivers/misc/fh_sadc_v2.c +@@ -0,0 +1,1150 @@ ++/* ++ * fh_sadc.c ++ * ++ * Created on: Mar 13, 2015 ++ * Author: duobao ++ */ ++#include <linux/uaccess.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++/***************************************************************************** ++ * Include Section ++ * add all #include here ++ *****************************************************************************/ ++#include <mach/fh_sadc.h> ++#include <mach/pmu.h> ++#include <linux/sched.h> ++ ++ ++/***************************************************************************** ++ * Define section ++ * add all #define here ++ *****************************************************************************/ ++#define wrap_readl(wrap, name) \ ++ __raw_readl(&(((struct wrap_sadc_reg *)wrap->regs)->name)) ++ ++#define wrap_writel(wrap, name, val) \ ++ __raw_writel((val), &(((struct wrap_sadc_reg *)wrap->regs)->name)) ++ ++ ++#define IOCTL_GET_SINGLE_SADC_DATA 0x1 ++#define IOCTL_CONTINUE_SADC_CFG 0x3 ++#define IOCTL_CONTINUE_SADC_START 0x4 ++#define IOCTL_CONTINUE_SADC_END 0x5 ++#ifdef CONFIG_FH_SADC_V22 ++#define IOCTL_HIT_SADC_CFG 0x6 ++#endif ++#define IOCTL_SADC_POWER_DOWN 0xff ++ ++ ++ ++ ++#define SADC_WRAP_BASE (SADC_REG_BASE) ++#define SADC_IRQn (23) ++#define SADC_MAX_CONTROLLER (1) ++#define SADC_STATUS_COLESD (0) ++#define SADC_STATUS_OPEN (1) ++#define FH_SADC_PLAT_DEVICE_NAME "fh_sadc" ++#define FH_SADC_MISC_DEVICE_NAME "fh_sadc" ++/*void (*g_sadc_get_continue_data)(u8 channel, u32 value) = NULL;*/ ++/*void (*g_sadc_get_hit_data)(u8 channel, u32 value) = NULL;*/ ++ ++/**************************************************************************** ++* ADT section ++* add definition of user defined Data Type that only be used in this file here ++***************************************************************************/ ++struct sadc_info { ++ int channel; ++ int sadc_data; ++}; ++ ++struct sadc_continue_cfg { ++ u32 channel_cfg; ++ u32 continue_time; /*ms*/ ++ u32 glitch_value; /*mv*/ ++ u32 glitch_time; /*count*/ ++ u32 eq_flag; ++ u32 zero_value; /*ms*/ ++ u32 precision; /*0xfff*/ ++ u32 powerdown; ++}; ++ ++struct sadc_continue_ctrl { ++ struct sadc_info usrdata; ++ u32 flag; ++}; ++ ++ ++#ifdef CONFIG_FH_SADC_V22 ++struct sadc_hit_data_cfg { ++ u8 channel_cfg; ++ u8 value_en; ++ u16 hit_gap;/*mv*/ ++ u16 value[8];/*mv*/ ++}; ++#endif ++ ++struct sadc_continue_ctrl g_sadc_data[SADC_CHANNEL_NUM]; ++u32 g_sadc_debug; ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Global variables section - Exported ++ * add declaration of global variables that will be exported here ++ * e.g. ++ * int8_t foo; ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++static u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc,\ ++ u32 channel, u16 *buf); ++static int fh_sadc_open(struct inode *inode, struct file *file); ++static int fh_sadc_release(struct inode *inode, struct file *filp); ++static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,\ ++ unsigned long arg); ++static int fh_sadc_read(struct file *filp, char __user *buf, ++ size_t len, loff_t *off); ++ ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++static struct wrap_sadc_obj fh_sadc_obj; ++ ++static const struct file_operations fh_sadc_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_sadc_open, ++ .read = fh_sadc_read, ++ .release = fh_sadc_release, ++ .unlocked_ioctl = fh_sadc_ioctl, ++}; ++ ++static struct miscdevice fh_sadc_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = FH_SADC_MISC_DEVICE_NAME, ++ .fops = &fh_sadc_fops, ++}; ++ ++/***************************************************************************** ++ * ++ * ++ * function body ++ * ++ * ++ *****************************************************************************/ ++u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, u32 channel, ++ u16 *buf) { ++ u32 xainsel = 1 << channel; ++ u32 xversel = 0; ++ u32 xpwdb = 1; ++ /*cnt*/ ++ u32 sel2sam_pre_cnt = 2; ++ u32 sam_cnt = 2; ++ u32 sam2sel_pos_cnt = 2; ++ /*time out*/ ++ u32 eoc_tos = 0xff; ++ u32 eoc_toe = 0xff; ++ u32 time_out = 0xffff; ++ /*set isr en..*/ ++ u32 sadc_isr = 0x01; ++ /*start*/ ++ u32 sadc_cmd = 0x01; ++ /*get data*/ ++ u32 temp_data = 0; ++ u32 ret_time; ++ ++ /*control...*/ ++ wrap_writel(sadc, sadc_control, xainsel | (xversel << 8) \ ++ | (xpwdb << 12)); ++ ++ wrap_writel(sadc, sadc_cnt, ++ sel2sam_pre_cnt | (sam_cnt << 8) | \ ++ (sam2sel_pos_cnt << 16)); ++ ++ wrap_writel(sadc, sadc_timeout, ++ eoc_tos | (eoc_toe << 8) | (time_out << 16)); ++ ++ wrap_writel(sadc, sadc_ier, sadc_isr); ++ ++ wrap_writel(sadc, sadc_cmd, sadc_cmd); ++ ++ ret_time = wait_for_completion_timeout(&sadc->done, 5000); ++ if (ret_time == 0) { ++ printk(KERN_ERR "sadc timeout..\n"); ++ return SADC_TIMEOUT; ++ } ++ ++ switch (channel) { ++ case 0: ++ case 1: ++ /*read channel 0 1*/ ++ temp_data = wrap_readl(sadc, sadc_dout0); ++ break; ++ ++ case 2: ++ case 3: ++ /*read channel 2 3*/ ++ temp_data = wrap_readl(sadc, sadc_dout1); ++ break; ++ ++ case 4: ++ case 5: ++ /*read channel 4 5*/ ++ temp_data = wrap_readl(sadc, sadc_dout2); ++ break; ++ ++ case 6: ++ case 7: ++ /*read channel 6 7*/ ++ temp_data = wrap_readl(sadc, sadc_dout3); ++ break; ++ default: ++ break; ++ } ++ if (channel % 2) { ++ /*read low 16bit*/ ++ *buf = (u16) (temp_data & 0xffff); ++ } else { ++ /*read high 16bit*/ ++ *buf = (u16) (temp_data >> 16); ++ } ++ return 0; ++ ++} ++EXPORT_SYMBOL(fh_sadc_isr_read_data); ++ ++/* 0:single mode;1:continue mode*/ ++int fh_sadc_mode_set(u32 mode) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_model); ++ if (mode) ++ reg |= 1; ++ else ++ reg &= (~1); ++ wrap_writel(sadc, sadc_model, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_mode_set); ++ ++int fh_sadc_lpc_en_set(u32 lpc_flag) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_chn_cfg); ++ if (lpc_flag) ++ reg |= (1 << 28); ++ else ++ reg &= (~(1 << 28)); ++ wrap_writel(sadc, sadc_chn_cfg, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_lpc_en_set); ++ ++u32 fh_sadc_lpc_en_get(void) ++{ ++ u32 reg; ++ u32 ret; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_chn_cfg); ++ reg &= (1 << 28); ++ ret = reg >> 28; ++ return ret; ++} ++EXPORT_SYMBOL(fh_sadc_lpc_en_get); ++ ++int fh_sadc_scan_delta(u32 scan_delta) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ u32 value; ++ ++ value = ((u32)scan_delta*SADC_MAX_AD_VALUE)/SADC_REF; ++ if (value > 0x3f) ++ value = 0x3f; ++ reg = wrap_readl(sadc, sadc_chn_cfg1); ++ reg &= (~(0x3f<<0)); ++ reg |= value ; ++ wrap_writel(sadc, sadc_chn_cfg1, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_scan_delta); ++ ++ ++int fh_sadc_glitch_en_set(u32 glitch_flag) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_chn_cfg); ++ if (glitch_flag) ++ reg |= (1 << 27); ++ else ++ reg &= (~(1 << 27)); ++ wrap_writel(sadc, sadc_chn_cfg, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_glitch_en_set); ++ ++u32 fh_sadc_glitch_en_get(void) ++{ ++ u32 reg; ++ u32 ret; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_chn_cfg); ++ reg &= (1 << 27); ++ ret = reg >> 27; ++ return ret; ++} ++EXPORT_SYMBOL(fh_sadc_glitch_en_get); ++ ++int fh_sadc_scan_start(void) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_scan_en); ++ reg |= (1 << 0); ++ wrap_writel(sadc, sadc_scan_en, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_scan_start); ++ ++int fh_sadc_scan_end(void) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_scan_en); ++ reg |= (1 << 1); ++ wrap_writel(sadc, sadc_scan_en, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_scan_end); ++ ++int fh_sadc_scan_power_cnt(u8 scan_power_cnt) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_chn_cfg1); ++ reg &= (~(0xff<<8)); ++ reg |= (scan_power_cnt << 8); ++ wrap_writel(sadc, sadc_chn_cfg1, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_scan_power_cnt); ++ ++ ++int fh_sadc_cons_ch_eq_set(u32 chn_num) ++{ ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ reg = wrap_readl(sadc, sadc_glitch_cfg); ++ reg |= (chn_num&0xff); ++ wrap_writel(sadc, sadc_glitch_cfg, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_cons_ch_eq_set); ++ ++int fh_sadc_set_act_bit(u32 act_bit) ++{ ++ u32 reg; ++ u32 value; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ if (act_bit > 12) ++ value = 12; ++ else ++ value = act_bit; ++ value = (~(1<<value))&0xfff; ++ reg = wrap_readl(sadc, sadc_glitch_cfg); ++ reg &= (~(0xfff<<8)); ++ reg |= (value<<8); ++ wrap_writel(sadc, sadc_glitch_cfg, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_set_act_bit); ++ ++int fh_sadc_set_continuous_time(u32 continuous_time) ++{ ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ struct clk *sadc_clk; ++ u32 value; ++ ++ sadc_clk = clk_get(NULL, "sadc_clk"); ++ if (IS_ERR(sadc_clk)) ++ return -EPERM; ++ ++ /*value = (glitch_time/1000)*sadc_clk->rate;FPGA 1000000HZ*/ ++ value = continuous_time*(1000000/1000); ++ wrap_writel(sadc, sadc_continuous_time, value); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_set_continuous_time); ++ ++int fh_sadc_set_glitch_time(u32 glitch_time) ++{ ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ wrap_writel(sadc, sadc_glitch_time, glitch_time); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_set_glitch_time); ++ ++int fh_sadc_set_zero_value(u32 zero_value) ++{ ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ u32 value; ++ u32 reg; ++ ++ value = (zero_value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ reg = wrap_readl(sadc, sadc_glitch_cfg); ++ reg &= (~(0xfff<<20)); ++ reg |= (value<<20); ++ wrap_writel(sadc, sadc_glitch_cfg, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_set_zero_value); ++ ++#ifdef CONFIG_FH_SADC_V22 ++int fh_sadc_hit_data_config(struct sadc_hit_data_cfg *hit_data) ++{ ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ u32 value; ++ u32 value1; ++ u32 reg; ++ ++ value = hit_data->hit_gap; ++ value = (value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ reg = value|(hit_data->value_en << 16)|(hit_data->channel_cfg << 24); ++ wrap_writel(sadc, sadc_hit_cfg, reg); ++ ++ value = hit_data->value[0]; ++ value = (value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ ++ value1 = hit_data->value[1]; ++ value1 = (value1*SADC_MAX_AD_VALUE)/SADC_REF; ++ value1 &= 0xfff; ++ reg = value | (value1 << 16); ++ ++ wrap_writel(sadc, sadc_hit_value0, reg); ++ ++ value = hit_data->value[2]; ++ value = (value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ ++ value1 = hit_data->value[3]; ++ value1 = (value1*SADC_MAX_AD_VALUE)/SADC_REF; ++ value1 &= 0xfff; ++ reg = value | (value1 << 16); ++ ++ wrap_writel(sadc, sadc_hit_value1, reg); ++ ++ value = hit_data->value[4]; ++ value = (value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ ++ value1 = hit_data->value[5]; ++ value1 = (value1*SADC_MAX_AD_VALUE)/SADC_REF; ++ value1 &= 0xfff; ++ reg = value | (value1 << 16); ++ ++ wrap_writel(sadc, sadc_hit_value2, reg); ++ ++ value = hit_data->value[6]; ++ value = (value*SADC_MAX_AD_VALUE)/SADC_REF; ++ value &= 0xfff; ++ ++ value1 = hit_data->value[7]; ++ value1 = (value1*SADC_MAX_AD_VALUE)/SADC_REF; ++ value1 &= 0xfff; ++ reg = value | (value1 << 16); ++ ++ wrap_writel(sadc, sadc_hit_value3, reg); ++ ++ reg = wrap_readl(sadc, sadc_ier); ++ reg &= (~(0xff<<24)); ++ reg |= (hit_data->value_en << 24); ++ wrap_writel(sadc, sadc_ier, reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_hit_data_config); ++#endif ++ ++int fh_sadc_enable(void) ++{ ++ u32 control_reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg |= 1 << 12; ++ wrap_writel(sadc, sadc_control, control_reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_enable); ++ ++int fh_sadc_disable(void) ++{ ++ u32 control_reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg &= ~(1 << 12); ++ wrap_writel(sadc, sadc_control, control_reg); ++ return 0; ++} ++EXPORT_SYMBOL(fh_sadc_disable); ++ ++ ++u32 fh_sadc_default_config(void) ++{ ++ u32 xversel = 0; ++ u32 xpwdb = 1; ++ /*cnt*/ ++ u32 sel2sam_pre_cnt = 2; ++ u32 sam_cnt = 2; ++ u32 sam2sel_pos_cnt = 2; ++ /*time out*/ ++ u32 eoc_tos = 0xff; ++ u32 eoc_toe = 0xff; ++ u32 time_out = 0xffff; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ /*sadc act bit default 12bit*/ ++ fh_sadc_set_act_bit(12); ++ /*control...*/ ++ wrap_writel(sadc, sadc_control, (xversel << 8) \ ++ | (xpwdb << 12)); ++ ++ wrap_writel(sadc, sadc_cnt, ++ sel2sam_pre_cnt | (sam_cnt << 8) | \ ++ (sam2sel_pos_cnt << 16)); ++ ++ wrap_writel(sadc, sadc_timeout, ++ eoc_tos | (eoc_toe << 8) | (time_out << 16)); ++ ++ ++ return 0; ++} ++ ++static irqreturn_t fh_sadc_isr(int irq, void *dev_id) ++{ ++ ++ u32 isr_status; ++ u32 temp_data = 0; ++ u32 temp_data1 = 0; ++ u32 channel = 0; ++ u32 data = 0; ++ u32 data1 = 0; ++ struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) dev_id; ++ ++ isr_status = wrap_readl(sadc, sadc_int_status); ++ if (isr_status & 0x01) { ++ ++ u32 sadc_isr = 0x00; ++ wrap_writel(sadc, sadc_ier, sadc_isr); ++ ++ wrap_writel(sadc, sadc_int_status, isr_status); ++ complete(&(sadc->done)); ++ return IRQ_HANDLED; ++ } ++ if (isr_status & 0x10000) { ++ channel = wrap_readl(sadc, sadc_status2); ++ channel = ((channel>>12)&0x7); ++ switch (channel/2) { ++ case 0: ++ /*read channel 0 1*/ ++ temp_data = wrap_readl(sadc, sadc_dout0); ++ break; ++ case 1: ++ /*read channel 2 3*/ ++ temp_data = wrap_readl(sadc, sadc_dout1); ++ break; ++ case 2: ++ /*read channel 4 5*/ ++ temp_data = wrap_readl(sadc, sadc_dout2); ++ break; ++ case 3: ++ /*read channel 6 7*/ ++ temp_data = wrap_readl(sadc, sadc_dout3); ++ break; ++ default: ++ break; ++ } ++ ++ if (channel % 2) ++ /*read low 16bit*/ ++ data = (temp_data & 0xfff); ++ else ++ /*read high 16bit*/ ++ data = (temp_data >> 16) & 0xfff; ++ data = (data*SADC_REF)/SADC_MAX_AD_VALUE; ++ if (g_sadc_debug) ++ printk(KERN_ERR "channel:%x data:%dmv\n", ++ channel, data); ++ if (waitqueue_active(&fh_sadc_obj.readqueue)) { ++ if (g_sadc_data[channel].flag) { ++ g_sadc_data[channel].usrdata.sadc_data = data; ++ g_sadc_data[channel].flag = 0; ++ wake_up(&fh_sadc_obj.readqueue); ++ } ++ } ++ wrap_writel(sadc, sadc_int_status, 0x10000); ++ } ++ if (isr_status & 0x100000) { ++ channel = wrap_readl(sadc, sadc_status2); ++ channel = ((channel>>12)&0x7); ++ switch (channel/2) { ++ case 0: ++ /*read channel 0 1*/ ++ temp_data1 = wrap_readl(sadc, sadc_dout0_all); ++ break; ++ case 1: ++ /*read channel 2 3*/ ++ temp_data1 = wrap_readl(sadc, sadc_dout1_all); ++ break; ++ case 2: ++ /*read channel 4 5*/ ++ temp_data1 = wrap_readl(sadc, sadc_dout2_all); ++ break; ++ case 3: ++ /*read channel 6 7*/ ++ temp_data1 = wrap_readl(sadc, sadc_dout3_all); ++ break; ++ default: ++ break; ++ } ++ ++ if (channel % 2) ++ /*read low 16bit*/ ++ data1 = (temp_data1 & 0xfff); ++ else ++ /*read high 16bit*/ ++ data1 = (temp_data1 >> 16) & 0xfff; ++ data1 = (data1*SADC_REF)/SADC_MAX_AD_VALUE; ++ if (g_sadc_debug) { ++ printk(KERN_ERR "glitch :%x data:%dmv\n", ++ channel, data1); ++ wrap_writel(sadc, sadc_int_status, 0x100000); ++ } ++ } ++#ifdef CONFIG_FH_SADC_V22 ++ if (isr_status & 0xff000000) { ++ channel = wrap_readl(sadc, sadc_status2); ++ channel = ((channel>>12)&0x7); ++ switch (channel) { ++ case 0: ++ case 1: ++ /*read channel 0 1*/ ++ temp_data = wrap_readl(sadc, sadc_hit_data0); ++ break; ++ ++ case 2: ++ case 3: ++ /*read channel 2 3*/ ++ temp_data = wrap_readl(sadc, sadc_hit_data1); ++ break; ++ ++ case 4: ++ case 5: ++ /*read channel 4 5*/ ++ temp_data = wrap_readl(sadc, sadc_hit_data2); ++ break; ++ ++ case 6: ++ case 7: ++ /*read channel 6 7*/ ++ temp_data = wrap_readl(sadc, sadc_hit_data3); ++ break; ++ default: ++ break; ++ } ++ ++ if (channel % 2) { ++ /*read low 16bit*/ ++ data = (temp_data & 0xfff); ++ } else { ++ /*read high 16bit*/ ++ data = (temp_data >> 16) & 0xfff; ++ } ++ ++ data = (data*SADC_REF)/SADC_MAX_AD_VALUE; ++ if (g_sadc_debug) ++ printk(KERN_ERR "hit value channel:%x data:%dmv isr_status:%x\n", ++ channel, data, isr_status); ++ if (waitqueue_active(&fh_sadc_obj.readqueue)) { ++ if (g_sadc_data[channel].flag) { ++ g_sadc_data[channel].usrdata.sadc_data = data; ++ g_sadc_data[channel].flag = 0; ++ wake_up(&fh_sadc_obj.readqueue); ++ } ++ } ++ wrap_writel(sadc, sadc_int_status, (isr_status & 0xff000000)); ++ ++ } ++#endif ++ return IRQ_HANDLED; ++} ++ ++long fh_sadc_get_value(int channel) ++{ ++ unsigned int ret; ++ long w = 0; ++ u16 ad_raw_data; ++ if (channel < 0) { ++ printk(KERN_ERR "ERROR: %s, sadc channel no %d is incorrect\n", ++ __func__, channel); ++ return 0; ++ } ++ ++ fh_sadc_enable(); ++ ++ ret = fh_sadc_isr_read_data(&fh_sadc_obj, channel, &ad_raw_data); ++ ++ if (ret != 0) { ++ printk(KERN_INFO "sadc error code:0x%x\n", ret); ++ } else { ++ w = ad_raw_data * SADC_REF / SADC_MAX_AD_VALUE; ++ printk(KERN_INFO "the value of sadc is: %ld\n", w); ++ } ++ ++ return w; ++} ++EXPORT_SYMBOL(fh_sadc_get_value); ++ ++static void del_char(char *str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) ++ *p++ = *q; ++ q++; ++ } ++ *p = '\0'; ++} ++ ++static ssize_t fh_sadc_proc_write(struct file *filp, const char *buf, ++ size_t len, loff_t *off) ++{ ++ char message[32] = {0}; ++ char * const delim = ","; ++ char *cur = message; ++ int i; ++ char *param_str[2]; ++ int reg; ++ int ret; ++ unsigned long param = 0; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ len = (len > 32) ? 32 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ for (i = 0; i < 2; i++) { ++ param_str[i] = strsep(&cur, delim); ++ if (!param_str[i]) { ++ pr_err("%s: ERROR: parameter[%d] is empty\n", ++ __func__, i); ++ pr_err("[debug],[channel],[pwr_down]\n"); ++ return -EINVAL; ++ } else { ++ del_char(param_str[i], ' '); ++ del_char(param_str[i], '\n'); ++ } ++ } ++ if (!strcmp(param_str[0], "debug")) { ++ ret = (u32)kstrtoul(param_str[1], 10, ¶m); ++ spin_lock_irq(&fh_sadc_obj.lock); ++ if (param) { ++ g_sadc_debug = 1; ++ reg = wrap_readl(sadc, sadc_ier); ++ reg |= 1<<20; ++ wrap_writel(sadc, sadc_ier, reg); ++ } else { ++ g_sadc_debug = 0; ++ reg = wrap_readl(sadc, sadc_ier); ++ reg &= (~(1<<20)); ++ wrap_writel(sadc, sadc_ier, reg); ++ } ++ spin_unlock_irq(&fh_sadc_obj.lock); ++ } ++ ++ if (!strcmp(param_str[0], "pwr_down")) { ++ ret = (u32)kstrtoul(param_str[1], 10, ¶m); ++ param ? fh_sadc_enable() : fh_sadc_disable(); ++ } ++ ++ return len; ++} ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter; ++ counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ int i; ++ u32 reg; ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ u32 ret; ++ ++ reg = (wrap_readl(sadc, sadc_control) & 0x1000); ++ ++ seq_printf(sfile, "\nSADC Status:\n"); ++ seq_printf(sfile, "Power %s\n\n", reg ? "up" : "down"); ++ ++ for (i = 0; i < 8; i++) { ++ u16 ad_raw_data; ++ ret = fh_sadc_isr_read_data(&fh_sadc_obj, i, &ad_raw_data); ++ if (ret != 0) ++ seq_printf(sfile, "sadc error code:0x%x\n", ret); ++ else ++ seq_printf(sfile, "channel: %d \tvalue: %u\n", i, ++ ad_raw_data * SADC_REF / SADC_MAX_AD_VALUE); ++ } ++ return 0; ++} ++ ++static const struct seq_operations isp_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_sadc_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &isp_seq_ops); ++} ++ ++static const struct file_operations fh_sadc_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_sadc_proc_open, ++ .read = seq_read, ++ .write = fh_sadc_proc_write, ++ .release = seq_release, ++}; ++ ++static int __devinit fh_sadc_probe(struct platform_device *pdev) ++{ ++ int err; ++ struct resource *res; ++ struct clk *sadc_clk; ++ ++ sadc_clk = clk_get(&pdev->dev, "sadc_clk"); ++ if (IS_ERR(sadc_clk)) { ++ err = PTR_ERR(sadc_clk); ++ return -EPERM; ++ } ++ clk_enable(sadc_clk); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "sadc get platform source error..\n"); ++ return -ENODEV; ++ } ++ ++ fh_sadc_obj.irq_no = platform_get_irq(pdev, 0); ++ if (fh_sadc_obj.irq_no < 0) { ++ dev_warn(&pdev->dev, "sadc interrupt is not available.\n"); ++ return fh_sadc_obj.irq_no; ++ } ++ ++ res = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "sadc region already claimed\n"); ++ return -EBUSY; ++ } ++ ++ fh_sadc_obj.regs = ioremap(res->start, resource_size(res)); ++ if (fh_sadc_obj.regs == NULL) { ++ err = -ENXIO; ++ goto fail_no_ioremap; ++ } ++ ++ init_completion(&fh_sadc_obj.done); ++ init_waitqueue_head(&fh_sadc_obj.readqueue); ++ mutex_init(&fh_sadc_obj.sadc_lock); ++ fh_sadc_obj.active_channel_no = 0; ++ ++ err = request_irq(fh_sadc_obj.irq_no, fh_sadc_isr, 0,\ ++ dev_name(&pdev->dev),\ ++ &fh_sadc_obj); ++ if (err) { ++ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err); ++ err = -ENXIO; ++ goto err_irq; ++ } ++ ++ err = misc_register(&fh_sadc_misc); ++ ++ if (err < 0) { ++ pr_err("%s: ERROR: %s registration failed", __func__, ++ FH_SADC_MISC_DEVICE_NAME); ++ err = -ENXIO; ++ goto misc_error; ++ } ++ ++ fh_sadc_obj.proc_file = create_proc_entry(FH_SADC_PROC_FILE, ++ 0644, NULL); ++ ++ if (fh_sadc_obj.proc_file) ++ fh_sadc_obj.proc_file->proc_fops = &fh_sadc_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, "SADC"); ++ ++ return 0; ++ ++misc_error: ++ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj); ++ ++err_irq: ++ iounmap(fh_sadc_obj.regs); ++ ++fail_no_ioremap: ++ release_mem_region(res->start, resource_size(res)); ++ ++ return err; ++} ++ ++static int __exit fh_sadc_remove(struct platform_device *pdev) ++{ ++ ++ struct resource *res; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ misc_deregister(&fh_sadc_misc); ++ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj); ++ iounmap(fh_sadc_obj.regs); ++ release_mem_region(res->start, resource_size(res)); ++ return 0; ++ ++} ++ ++ ++static int fh_sadc_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_sadc_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++static int fh_sadc_read(struct file *filp, char __user *buf, ++ size_t len, loff_t *off) ++{ ++ int ret; ++ struct sadc_info sadc_data; ++ ++ ret = copy_from_user((void *) &sadc_data, ++ (void __user *) buf, sizeof(struct sadc_info)); ++ ++ spin_lock_irq(&fh_sadc_obj.lock); ++ g_sadc_data[sadc_data.channel].usrdata.channel = sadc_data.channel; ++ g_sadc_data[sadc_data.channel].flag = 1; ++ spin_unlock_irq(&fh_sadc_obj.lock); ++ ++ /* wait for enough data*/ ++ if (!wait_event_timeout(fh_sadc_obj.readqueue, ++ !g_sadc_data[sadc_data.channel].flag, 100)) { ++ pr_err("%s: channel:%d read time out", ++ __func__, sadc_data.channel); ++ return -1; ++ } ++ spin_lock_irq(&fh_sadc_obj.lock); ++ ret = copy_to_user((void __user *)buf, ++ (void *)&g_sadc_data[sadc_data.channel].usrdata, ++ sizeof(struct sadc_info)); ++ spin_unlock_irq(&fh_sadc_obj.lock); ++ return len; ++} ++ ++static long fh_sadc_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) { ++ ++ u32 ad_data; ++ u32 control_reg; ++ u16 ad_raw_data; ++ struct sadc_info sadc_info; ++ struct sadc_continue_cfg sadc_continue_cfg; ++#ifdef CONFIG_FH_SADC_V22 ++ struct sadc_hit_data_cfg sadc_hit_data_cfg; ++#endif ++ struct wrap_sadc_obj *sadc = &fh_sadc_obj; ++ mutex_lock(&sadc->sadc_lock); ++ switch (cmd) { ++ case IOCTL_GET_SINGLE_SADC_DATA: ++ { ++ if (copy_from_user((void *) &sadc_info, (void __user*) arg, ++ sizeof(sadc_info))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ if ((wrap_readl(sadc, sadc_status2) & 0x10)) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EBUSY; ++ } ++ fh_sadc_mode_set(0); ++ ++ fh_sadc_isr_read_data(&fh_sadc_obj, sadc_info.channel,\ ++ &ad_raw_data); ++ ad_data = ad_raw_data * SADC_REF; ++ ad_data /= SADC_MAX_AD_VALUE; ++ sadc_info.sadc_data = ad_data; ++ if (put_user(sadc_info.sadc_data, ++ (int __user *)(&((struct sadc_info *)arg)\ ++ ->sadc_data))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ break; ++ } ++ case IOCTL_SADC_POWER_DOWN: ++ control_reg = wrap_readl(sadc, sadc_control); ++ control_reg &= ~(1 << 12); ++ wrap_writel(sadc, sadc_control, control_reg); ++ break; ++ case IOCTL_CONTINUE_SADC_CFG: ++ { ++ if (copy_from_user((void *) &sadc_continue_cfg, ++ (void __user *) arg, sizeof(sadc_continue_cfg))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ /*config continue model*/ ++ fh_sadc_mode_set(1); ++ ++ /*config channel cfg */ ++ control_reg = wrap_readl(sadc, sadc_chn_cfg); ++ control_reg |= (sadc_continue_cfg.channel_cfg & 0x7ffffff); ++ wrap_writel(sadc, sadc_chn_cfg, control_reg); ++ ++ /*config continue time */ ++ fh_sadc_set_continuous_time(sadc_continue_cfg.continue_time); ++ ++ fh_sadc_glitch_en_set(1); ++ ++ /*config glitch time */ ++ fh_sadc_set_glitch_time(sadc_continue_cfg.glitch_time); ++ ++ /*config scan delta */ ++ fh_sadc_scan_delta(sadc_continue_cfg.glitch_value); ++ ++ /*config zero value */ ++ fh_sadc_set_zero_value(sadc_continue_cfg.zero_value); ++ ++ /*config precision*/ ++ if (sadc_continue_cfg.precision) ++ fh_sadc_set_act_bit(sadc_continue_cfg.precision); ++ ++ /*config eq flag*/ ++ fh_sadc_cons_ch_eq_set(sadc_continue_cfg.eq_flag); ++ ++ /*default config*/ ++ fh_sadc_default_config(); ++ ++ /*glitch isr enable*/ ++ wrap_writel(sadc, sadc_ier, 1<<16); ++ break; ++ } ++ case IOCTL_CONTINUE_SADC_START: ++ fh_sadc_scan_start(); ++ break; ++ case IOCTL_CONTINUE_SADC_END: ++ fh_sadc_scan_end(); ++ break; ++#ifdef CONFIG_FH_SADC_V22 ++ case IOCTL_HIT_SADC_CFG: ++ if (copy_from_user((void *) &sadc_hit_data_cfg, ++ (void __user *) arg, sizeof(sadc_hit_data_cfg))) { ++ mutex_unlock(&sadc->sadc_lock); ++ return -EFAULT; ++ } ++ fh_sadc_hit_data_config(&sadc_hit_data_cfg); ++ break; ++#endif ++ } ++ mutex_unlock(&sadc->sadc_lock); ++ return 0; ++} ++ ++ ++/******************* ++ * ++ * ++ *add platform cause of i need the board info... ++ *in the probe function. i will register the sadc ++ *misc drive...then the app can open the sadc misc device.. ++ * ++ ******************/ ++static struct platform_driver fh_sadc_driver = { ++ .driver = { ++ .name = FH_SADC_PLAT_DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_sadc_probe, ++ .remove = __exit_p(fh_sadc_remove), ++}; ++ ++ ++ ++static int __init fh_sadc_init(void) ++{ ++ return platform_driver_register(&fh_sadc_driver); ++} ++ ++static void __exit fh_sadc_exit(void) ++{ ++ ++ platform_driver_unregister(&fh_sadc_driver); ++ ++} ++ ++module_init(fh_sadc_init); ++module_exit(fh_sadc_exit); ++ ++MODULE_DESCRIPTION("fh sadc driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("tangyh@fullhan.com"); ++MODULE_ALIAS("platform:FH_sadc"); +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index f85e4222..5606661c 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -675,6 +675,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) + struct mmc_card *card = md->queue.card; + struct mmc_blk_request brq; + int ret = 1, disable_multi = 0; ++ int re_write_count = 0; + + /* + * Reliable writes are used to implement Forced Unit Access and +@@ -688,7 +689,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) + do { + struct mmc_command cmd = {0}; + u32 readcmd, writecmd, status = 0; +- ++re_write: + memset(&brq, 0, sizeof(struct mmc_blk_request)); + brq.mrq.cmd = &brq.cmd; + brq.mrq.data = &brq.data; +@@ -894,7 +895,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) + spin_unlock_irq(&md->lock); + continue; + } +- goto cmd_err; ++ re_write_count++; ++ if (re_write_count < 4) ++ goto re_write; ++ else ++ goto cmd_err; + } + + /* +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 38089b25..2b645fbe 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1557,6 +1557,9 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) + } + EXPORT_SYMBOL(mmc_set_blocklen); + ++extern struct mmc_host *mmc_sd1; ++extern struct mmc_host *mmc_sd0; ++ + static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) + { + host->f_init = freq; +@@ -1631,6 +1634,14 @@ void mmc_rescan(struct work_struct *work) + if (host->ops->get_cd && host->ops->get_cd(host) == 0) + goto out; + ++ /* rescan 5 times when detect mmc */ ++ if (!(host->caps & MMC_CAP_NONREMOVABLE)) { ++ if (host->rescan_count > 5) ++ goto out; ++ else ++ host->rescan_count++; ++ } ++ + mmc_claim_host(host); + for (i = 0; i < ARRAY_SIZE(freqs); i++) { + if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) +diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h +index d9411ed2..01b3b3d3 100644 +--- a/drivers/mmc/core/core.h ++++ b/drivers/mmc/core/core.h +@@ -13,7 +13,7 @@ + + #include <linux/delay.h> + +-#define MMC_CMD_RETRIES 3 ++#define MMC_CMD_RETRIES 0 //FIXME, by PeterJiang, don't retry... + + struct mmc_bus_ops { + int (*awake)(struct mmc_host *); +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index aa7d1d79..2f002146 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -262,8 +262,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) + if (card->ext_csd.rev > 5) { + printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", + mmc_hostname(card->host), card->ext_csd.rev); +- err = -EINVAL; +- goto out; ++ /*err = -EINVAL;*/ ++ /*goto out;*/ + } + + card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index ff277412..c1649228 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -305,6 +305,8 @@ static int mmc_read_switch(struct mmc_card *card) + + goto out; + } ++ if (status[13] & 0x02) //modify by kernel 3.0.101 ++ card->sw_caps.hs_max_dtr = 50000000; + + if (card->scr.sda_spec3) { + card->sw_caps.sd3_bus_mode = status[13]; +@@ -348,11 +350,11 @@ static int mmc_read_switch(struct mmc_card *card) + } + + card->sw_caps.sd3_curr_limit = status[7]; +- } else { ++ } /*else {//modify by kernel 3.0.101 + if (status[13] & 0x02) + card->sw_caps.hs_max_dtr = 50000000; + } +- ++ */ + out: + kfree(status); + +diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c +index 262fff01..06dbfdde 100644 +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -111,7 +111,7 @@ static int sdio_read_cccr(struct mmc_card *card) + + cccr_vsn = data & 0x0f; + +- if (cccr_vsn > SDIO_CCCR_REV_1_20) { ++ if (cccr_vsn > SDIO_CCCR_REV_3_00) { /* to support SDIO 3.0 (luoc) */ + printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n", + mmc_hostname(card->host), cccr_vsn); + return -EINVAL; +@@ -881,3 +881,73 @@ err: + return err; + } + ++int sdio_reset_comm(struct mmc_card *card) ++{ ++ struct mmc_host *host = card->host; ++ u32 ocr; ++ int err; ++ printk("%s():\n", __func__); ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ mmc_claim_host(host); ++ mmc_go_idle(host); ++ mmc_set_clock(host, host->f_min); ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ err = mmc_send_io_op_cond(host, 0, &ocr); ++ if (err) ++ goto err; ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ host->ocr = mmc_select_voltage(host, ocr); ++ if (!host->ocr) { ++ err = -EINVAL; ++ goto err; ++ } ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ err = mmc_send_io_op_cond(host, host->ocr, &ocr); ++ if (err) ++ goto err; ++ if (mmc_host_is_spi(host)) { ++ err = mmc_spi_set_crc(host, use_spi_crc); ++ if (err) ++ goto err; ++ } ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ if (!mmc_host_is_spi(host)) { ++ err = mmc_send_relative_addr(host, &card->rca); ++ if (err) ++ goto err; ++ mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); ++ } ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ if (!mmc_host_is_spi(host)) { ++ err = mmc_select_card(card); ++ if (err) ++ goto err; ++ } ++ /* ++ * Switch to high-speed (if supported). ++ */ ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ err = sdio_enable_hs(card); ++ if (err > 0) ++ mmc_sd_go_highspeed(card); ++ else if (err) ++ goto err; ++ /* ++ * Change to the card's maximum speed. ++ */ ++ printk("%s line %d.\n", __FILE__, __LINE__); ++ mmc_set_clock(host, mmc_sdio_get_max_clock(card)); ++ err = sdio_enable_4bit_bus(card); ++ if (err > 0) ++ mmc_set_bus_width(host, MMC_BUS_WIDTH_4); ++ else if (err) ++ goto err; ++ mmc_release_host(host); ++ return 0; ++err: ++ printk("%s: Error resetting SDIO communications (%d)\n", ++ mmc_hostname(host), err); ++ mmc_release_host(host); ++ return err; ++} ++EXPORT_SYMBOL(sdio_reset_comm); +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 56dbf3f6..96361a63 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -518,6 +518,23 @@ config MMC_DW_IDMAC + Designware Mobile Storage IP block. This disables the external DMA + interface. + ++config MMC_FH ++ tristate "FH Memory Card Interface" ++ depends on ARM ++ help ++ This selects support for the Synopsys DesignWare Mobile Storage IP ++ block, this provides host support for SD and MMC interfaces, in both ++ PIO and external DMA modes. ++ ++config MMC_FH_IDMAC ++ bool "Internal DMAC interface" ++ depends on MMC_FH ++ help ++ This selects support for the internal DMAC block within the Synopsys ++ Designware Mobile Storage IP block. This disables the external DMA ++ interface. ++ ++ + config MMC_SH_MMCIF + tristate "SuperH Internal MMCIF support" + depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index 58a5cf73..e56cfa32 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_MMC_CB710) += cb710-mmc.o + obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o + obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o + obj-$(CONFIG_MMC_DW) += dw_mmc.o ++obj-$(CONFIG_MMC_FH) += fhmci/ + obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o + obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o + obj-$(CONFIG_MMC_VUB300) += vub300.o +diff --git a/drivers/mmc/host/fh_mmc.c b/drivers/mmc/host/fh_mmc.c +new file mode 100644 +index 00000000..151b5278 +--- /dev/null ++++ b/drivers/mmc/host/fh_mmc.c +@@ -0,0 +1,2150 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface driver ++ * (Based on NXP driver for lpc 31xx) ++ * ++ * Copyright (C) 2009 NXP Semiconductors ++ * Copyright (C) 2009, 2010 Imagination Technologies Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/blkdev.h> ++#include <linux/clk.h> ++#include <linux/debugfs.h> ++#define DEBUG ++#include <linux/device.h> ++#include <linux/dma-mapping.h> ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/scatterlist.h> ++#include <linux/seq_file.h> ++#include <linux/slab.h> ++#include <linux/stat.h> ++#include <linux/delay.h> ++#include <linux/irq.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/mmc.h> ++#include <linux/bitops.h> ++#include <linux/regulator/consumer.h> ++#include <linux/proc_fs.h> ++#include <linux/gpio.h> ++ ++#include "fh_mmc.h" ++#include "fh_mmc_reg.h" ++ ++#define TEST_GPIO 4 ++ ++#define SDC_DESC_SIZE (PAGE_SIZE * 2) ++#define T_END 10 ++ ++/* Common flag combinations */ ++#define FH_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \ ++ SDMMC_INT_HTO | SDMMC_INT_SBE | \ ++ SDMMC_INT_EBE) ++#define FH_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ ++ SDMMC_INT_RESP_ERR) ++#define FH_MCI_ERROR_FLAGS (FH_MCI_DATA_ERROR_FLAGS | \ ++ FH_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE) ++#define FH_MCI_SEND_STATUS 1 ++#define FH_MCI_RECV_STATUS 2 ++#define FH_MCI_DMA_THRESHOLD 16 ++ ++#ifdef CONFIG_MMC_FH_IDMAC ++struct idmac_desc { ++ u32 des0; /* Control Descriptor */ ++#define IDMAC_DES0_DIC BIT(1) ++#define IDMAC_DES0_LD BIT(2) ++#define IDMAC_DES0_FD BIT(3) ++#define IDMAC_DES0_CH BIT(4) ++#define IDMAC_DES0_ER BIT(5) ++#define IDMAC_DES0_CES BIT(30) ++#define IDMAC_DES0_OWN BIT(31) ++ ++ u32 des1; /* Buffer sizes */ ++#define IDMAC_SET_BUFFER1_SIZE(d, s) \ ++ ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) ++ ++ u32 des2; /* buffer 1 physical address */ ++ ++ u32 des3; /* buffer 2 physical address */ ++}; ++#endif /* CONFIG_MMC_FH_IDMAC */ ++ ++/** ++ * struct fh_mci_slot - MMC slot state ++ * @mmc: The mmc_host representing this slot. ++ * @host: The MMC controller this slot is using. ++ * @ctype: Card type for this slot. ++ * @mrq: mmc_request currently being processed or waiting to be ++ * processed, or NULL when the slot is idle. ++ * @queue_node: List node for placing this node in the @queue list of ++ * &struct fh_mci. ++ * @clock: Clock rate configured by set_ios(). Protected by host->lock. ++ * @flags: Random state bits associated with the slot. ++ * @id: Number of this slot. ++ * @last_detect_state: Most recently observed card detect state. ++ */ ++struct fh_mci_slot { ++ struct mmc_host *mmc; ++ struct fh_mci *host; ++ ++ u32 ctype; ++ ++ struct mmc_request *mrq; ++ struct list_head queue_node; ++ ++ unsigned int clock; ++ unsigned long flags; ++#define FH_MMC_CARD_PRESENT 0 ++#define FH_MMC_CARD_NEED_INIT 1 ++ int id; ++ int last_detect_state; ++}; ++ ++#if defined(CONFIG_DEBUG_FS) ++static int fh_mci_req_show(struct seq_file *s, void *v) ++{ ++ struct fh_mci_slot *slot = s->private; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_command *stop; ++ struct mmc_data *data; ++ ++ /* Make sure we get a consistent snapshot */ ++ spin_lock_bh(&slot->host->lock); ++ mrq = slot->mrq; ++ ++ if (mrq) { ++ cmd = mrq->cmd; ++ data = mrq->data; ++ stop = mrq->stop; ++ ++ if (cmd) ++ seq_printf(s, ++ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", ++ cmd->opcode, cmd->arg, cmd->flags, ++ cmd->resp[0], cmd->resp[1], cmd->resp[2], ++ cmd->resp[2], cmd->error); ++ if (data) ++ seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", ++ data->bytes_xfered, data->blocks, ++ data->blksz, data->flags, data->error); ++ if (stop) ++ seq_printf(s, ++ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", ++ stop->opcode, stop->arg, stop->flags, ++ stop->resp[0], stop->resp[1], stop->resp[2], ++ stop->resp[2], stop->error); ++ } ++ ++ spin_unlock_bh(&slot->host->lock); ++ ++ return 0; ++} ++ ++static int fh_mci_req_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, fh_mci_req_show, inode->i_private); ++} ++ ++static const struct file_operations fh_mci_req_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_mci_req_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int fh_mci_regs_show(struct seq_file *s, void *v) ++{ ++ seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS); ++ seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS); ++ seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD); ++ seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL); ++ seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK); ++ seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA); ++ ++ return 0; ++} ++ ++static int fh_mci_regs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, fh_mci_regs_show, inode->i_private); ++} ++ ++static const struct file_operations fh_mci_regs_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_mci_regs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void fh_mci_init_debugfs(struct fh_mci_slot *slot) ++{ ++ struct mmc_host *mmc = slot->mmc; ++ struct fh_mci *host = slot->host; ++ struct dentry *root; ++ struct dentry *node; ++ ++ root = mmc->debugfs_root; ++ if (!root) ++ return; ++ ++ node = debugfs_create_file("regs", S_IRUSR, root, host, ++ &fh_mci_regs_fops); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_file("req", S_IRUSR, root, slot, ++ &fh_mci_req_fops); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_x32("pending_events", S_IRUSR, root, ++ (u32 *)&host->pending_events); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_x32("completed_events", S_IRUSR, root, ++ (u32 *)&host->completed_events); ++ if (!node) ++ goto err; ++ ++ return; ++ ++err: ++ dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); ++} ++#endif /* defined(CONFIG_DEBUG_FS) */ ++ ++ ++ ++static void fh_mci_set_timeout(struct fh_mci *host) ++{ ++ /* timeout (maximum) */ ++ mci_writel(host, TMOUT, 0xffffffff); ++} ++ ++static u32 fh_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) ++{ ++ struct mmc_data *data; ++ u32 cmdr; ++ cmd->error = -EINPROGRESS; ++ ++ cmdr = cmd->opcode; ++ ++ if (cmdr == MMC_STOP_TRANSMISSION) ++ cmdr |= SDMMC_CMD_STOP; ++ else ++ cmdr |= SDMMC_CMD_PRV_DAT_WAIT; ++ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ /* We expect a response, so set this bit */ ++ cmdr |= SDMMC_CMD_RESP_EXP; ++ if (cmd->flags & MMC_RSP_136) ++ cmdr |= SDMMC_CMD_RESP_LONG; ++ } ++ ++ if (cmd->flags & MMC_RSP_CRC) ++ cmdr |= SDMMC_CMD_RESP_CRC; ++ ++ data = cmd->data; ++ if (data) { ++ cmdr |= SDMMC_CMD_DAT_EXP; ++ if (data->flags & MMC_DATA_STREAM) ++ cmdr |= SDMMC_CMD_STRM_MODE; ++ if (data->flags & MMC_DATA_WRITE) ++ cmdr |= SDMMC_CMD_DAT_WR; ++ } ++ cmdr |= SDMMC_CMD_USE_HOLD_REG; ++ return cmdr; ++} ++ ++ ++static void fh_mci_start_command(struct fh_mci *host, ++ struct mmc_command *cmd, u32 cmd_flags) ++{ ++ host->cmd = cmd; ++ dev_vdbg(&host->pdev->dev, ++ "start command: ARGR=0x%08x CMDR=0x%08x\n", ++ cmd->arg, cmd_flags); ++ mci_writel(host, CMDARG, cmd->arg); ++ wmb(); ++ ++ mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); ++} ++ ++static void send_stop_cmd(struct fh_mci *host, struct mmc_data *data) ++{ ++ fh_mci_start_command(host, data->stop, host->stop_cmdr); ++} ++ ++/* DMA interface functions */ ++static void fh_mci_stop_dma(struct fh_mci *host) ++{ ++ if (host->use_dma) { ++ host->dma_ops->stop(host); ++ host->dma_ops->cleanup(host); ++ } ++ ++ /* Data transfer was stopped by the interrupt handler */ ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++ ++} ++ ++#ifdef CONFIG_MMC_FH_IDMAC ++ ++ ++ ++static void fh_mci_idmac_reset(struct fh_mci *host) ++{ ++ u32 bmod = mci_readl(host, BMOD); ++ /* Software reset of DMA */ ++ bmod |= SDMMC_IDMAC_SWRESET; ++ mci_writel(host, BMOD, bmod); ++ ++} ++ ++static void fh_mci_dma_cleanup(struct fh_mci *host) ++{ ++ struct mmc_data *data = host->data; ++ ++ if (data && host->dma_data_mapped) ++ dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, ++ ((data->flags & MMC_DATA_WRITE) ++ ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); ++ ++ host->dma_data_mapped =0; ++} ++ ++static void fh_mci_idmac_stop_dma(struct fh_mci *host) ++{ ++ u32 temp; ++ ++ /* Disable and reset the IDMAC interface */ ++ temp = mci_readl(host, CTRL); ++ temp &= ~SDMMC_CTRL_USE_IDMAC; ++ temp |= SDMMC_CTRL_DMA_RESET; ++ mci_writel(host, CTRL, temp); ++ ++ /* Stop the IDMAC running */ ++ temp = mci_readl(host, BMOD); ++ temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); ++ temp |= SDMMC_IDMAC_SWRESET; ++ mci_writel(host, BMOD, temp); ++} ++ ++static void fh_mci_idmac_complete_dma(struct fh_mci *host) ++{ ++ struct mmc_data *data = host->data; ++ ++ dev_vdbg(&host->pdev->dev, "DMA complete\n"); ++ ++ host->dma_ops->cleanup(host); ++ ++ /* ++ * If the card was removed, data will be NULL. No point in trying to ++ * send the stop command or waiting for NBUSY in this case. ++ */ ++ if (data) { ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++ } ++} ++ ++static void fh_mci_translate_sglist(struct fh_mci *host, struct mmc_data *data, ++ unsigned int sg_len) ++{ ++ #define DMA_ONE_BUF_SIZE_MAX (0x2000 - 16) ++ ++ int i; ++ int num = 0; ++ u32 seglen; ++ struct idmac_desc *desc = host->sg_cpu; ++ struct idmac_desc *ldesc = NULL; ++ ++ for (i = 0; i < sg_len; i++) { ++ unsigned int length = sg_dma_len(&data->sg[i]); ++ u32 mem_addr = sg_dma_address(&data->sg[i]); ++ ++ while (length > 0) { ++ //FIXME ++ //this should not happen ++ if (++num > host->ring_size) { ++ panic("%s, line %d, too long DMA transfer!\n", ++ __FILE__, __LINE__); ++ } ++ ++ seglen = length; ++ if (seglen > DMA_ONE_BUF_SIZE_MAX) { ++ seglen = DMA_ONE_BUF_SIZE_MAX; ++ } ++ ++ /* Set the OWN bit and disable interrupts for this descriptor */ ++ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH; ++ /* Buffer length */ ++ IDMAC_SET_BUFFER1_SIZE(desc, seglen); ++ /* Physical address to DMA to/from */ ++ desc->des2 = mem_addr; ++ ++ mem_addr += seglen; ++ length -= seglen; ++ ++ ldesc = desc++; ++ } ++ } ++ ++ /* Set first descriptor */ ++ desc = host->sg_cpu; ++ desc->des0 |= IDMAC_DES0_FD; ++ ++ /* Set last descriptor */ ++ if (ldesc) { ++ ldesc->des0 |= IDMAC_DES0_LD; ++ ldesc->des0 &= ~IDMAC_DES0_DIC; ++ } ++ ++ wmb(); ++} ++ ++static void fh_mci_idmac_start_dma(struct fh_mci *host, unsigned int sg_len) ++{ ++ u32 temp; ++ ++ fh_mci_translate_sglist(host, host->data, sg_len); ++ ++ /* Select IDMAC interface */ ++ temp = mci_readl(host, CTRL); ++ temp |= SDMMC_CTRL_USE_IDMAC; ++ mci_writel(host, CTRL, temp); ++ ++ wmb(); ++ ++ /* Enable the IDMAC */ ++ temp = mci_readl(host, BMOD); ++ temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB; ++ mci_writel(host, BMOD, temp); ++ /* Start it running */ ++ mci_writel(host, PLDMND, 1); ++} ++ ++static int fh_mci_idmac_init(struct fh_mci *host) ++{ ++ struct idmac_desc *p; ++ int i; ++ ++ /* Number of descriptors in the ring buffer */ ++ //host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); ++ host->ring_size = SDC_DESC_SIZE / sizeof(struct idmac_desc); ++ ++ /* Forward link the descriptor list */ ++ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) ++ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); ++ ++ /* Set the last descriptor as the end-of-ring descriptor */ ++ p->des3 = host->sg_dma; ++ p->des0 = IDMAC_DES0_ER; ++ fh_mci_idmac_reset(host); ++ /* Mask out interrupts - get Tx & Rx complete only */ ++ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | ++ SDMMC_IDMAC_INT_TI); ++ ++ /* Set the descriptor base address */ ++ mci_writel(host, DBADDR, host->sg_dma); ++ return 0; ++} ++ ++static struct fh_mci_dma_ops fh_mci_idmac_ops = { ++ .init = fh_mci_idmac_init, ++ .start = fh_mci_idmac_start_dma, ++ .stop = fh_mci_idmac_stop_dma, ++ .complete = fh_mci_idmac_complete_dma, ++ .cleanup = fh_mci_dma_cleanup, ++}; ++#endif /* CONFIG_MMC_FH_IDMAC */ ++ ++static int fh_mci_pre_dma_transfer(struct fh_mci *host, ++ struct mmc_data *data, ++ bool next) ++{ ++ struct scatterlist *sg; ++ unsigned int i, direction, sg_len; ++ ++//#define SDIO_DMA ++//#define SDIO_PIO ++ ++#ifdef SDIO_PIO ++ return -EINVAL; ++#else ++#ifdef SDIO_DMA ++ ++#else ++ /* ++ * We don't do DMA on "complex" transfers, i.e. with ++ * non-word-aligned buffers or lengths. Also, we don't bother ++ * with all the DMA setup overhead for short transfers. ++ */ ++ if (data->blocks * data->blksz < FH_MCI_DMA_THRESHOLD) ++ return -EINVAL; ++ if (data->blksz & 3) ++ return -EINVAL; ++ for_each_sg(data->sg, sg, data->sg_len, i) { ++ if (sg->offset & 3 || sg->length & 3) ++ return -EINVAL; ++ } ++#endif ++#endif ++ if (data->flags & MMC_DATA_READ) ++ direction = DMA_FROM_DEVICE; ++ else ++ direction = DMA_TO_DEVICE; ++ ++ sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, ++ direction); ++ ++ host->dma_data_mapped = 1; ++ return sg_len; ++} ++ ++ ++ ++static int fh_mci_submit_data_dma(struct fh_mci *host, struct mmc_data *data) ++{ ++ int sg_len; ++ u32 temp; ++ ++ host->using_dma = 0; ++ ++ /* If we don't have a channel, we can't do DMA */ ++ if (!host->use_dma) ++ return -ENODEV; ++ ++ sg_len = fh_mci_pre_dma_transfer(host, data, 0); ++ if (sg_len < 0) { ++ host->dma_ops->stop(host); ++ return sg_len; ++ } ++ ++ host->using_dma = 1; ++ ++ dev_vdbg(&host->pdev->dev, ++ "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", ++ (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, ++ sg_len); ++ ++#if 0 ++ //test data blocksize ++ WARN((host->prev_blksz && (host->prev_blksz != data->blksz)), ++ "Block size changed, from %d to %d", ++ host->prev_blksz, ++ data->blksz); ++#endif ++ ++ /* Enable the DMA interface */ ++ temp = mci_readl(host, CTRL); ++ temp |= SDMMC_CTRL_DMA_ENABLE; ++ mci_writel(host, CTRL, temp); ++ ++ /* Disable RX/TX IRQs, let DMA handle it */ ++ temp = mci_readl(host, INTMASK); ++ temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); ++ mci_writel(host, INTMASK, temp); ++ host->dma_ops->start(host, sg_len); ++ return 0; ++} ++ ++static void fh_mci_submit_data(struct fh_mci *host, struct mmc_data *data) ++{ ++ u32 temp; ++ int ret; ++ data->error = -EINPROGRESS; ++ ++ WARN_ON(host->data); ++ host->sg = NULL; ++ host->data = data; ++ ++ if (data->flags & MMC_DATA_READ) ++ host->dir_status = FH_MCI_RECV_STATUS; ++ else ++ host->dir_status = FH_MCI_SEND_STATUS; ++ ++ ret = fh_mci_submit_data_dma(host, data); ++ if (ret) { ++ host->sg = data->sg; ++ host->pio_offset = 0; ++ ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); ++ ++ temp = mci_readl(host, INTMASK); ++ temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; ++ mci_writel(host, INTMASK, temp); ++ temp = mci_readl(host, CTRL); ++ temp &= ~SDMMC_CTRL_DMA_ENABLE; ++ mci_writel(host, CTRL, temp); ++ host->prev_blksz = 0; ++ }else { ++ /* ++ * Keep the current block size. ++ * It will be used to decide whether to update ++ * fifoth register next time. ++ */ ++ host->prev_blksz = data->blksz; ++ } ++} ++ ++static void mci_send_cmd(struct fh_mci_slot *slot, u32 cmd, u32 arg) ++{ ++ struct fh_mci *host = slot->host; ++ unsigned long timeout = jiffies + msecs_to_jiffies(500); ++ unsigned int cmd_status = 0; ++ ++ mci_writel(host, CMDARG, arg); ++ wmb(); ++ mci_writel(host, CMD, SDMMC_CMD_START | cmd); ++ ++ while (time_before(jiffies, timeout)) { ++ cmd_status = mci_readl(host, CMD); ++ if (!(cmd_status & SDMMC_CMD_START)) ++ return; ++ } ++ dev_err(&slot->mmc->class_dev, ++ "Timeout sending command (cmd %#x arg %#x status %#x)\n", ++ cmd, arg, cmd_status); ++} ++ ++static void fh_mci_setup_bus(struct fh_mci_slot *slot) ++{ ++ struct fh_mci *host = slot->host; ++ u32 div; ++ ++ if (slot->clock != host->current_speed) { ++ if (host->bus_hz % slot->clock) ++ /* ++ * move the + 1 after the divide to prevent ++ * over-clocking the card. ++ */ ++ div = ((host->bus_hz / slot->clock) >> 1) + 1; ++ else ++ div = (host->bus_hz / slot->clock) >> 1; ++ ++ dev_info(&slot->mmc->class_dev, ++ "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ" ++ " div = %d)\n", slot->id, host->bus_hz, slot->clock, ++ div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); ++ ++ /* disable clock */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, ++ SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); ++ ++ /* set clock to desired speed */ ++ mci_writel(host, CLKDIV, div); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, ++ SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); ++ ++ /* enable clock */ ++ mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE | ++ SDMMC_CLKEN_LOW_PWR); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, ++ SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); ++ ++ host->current_speed = slot->clock; ++ } ++ ++ /* Set the current slot bus width */ ++ mci_writel(host, CTYPE, slot->ctype); ++} ++ ++ ++static void fh_mci_start_request(struct fh_mci *host, ++ struct fh_mci_slot *slot) ++{ ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ u32 cmdflags; ++ ++ mrq = slot->mrq; ++ if (host->pdata->select_slot) ++ host->pdata->select_slot(slot->id); ++ /* Slot specific timing and width adjustment */ ++ // do_gettimeofday(&mrq->rq_times[3]); ++ fh_mci_setup_bus(slot); ++ host->cur_slot = slot; ++ host->mrq = mrq; ++ ++ host->pending_events = 0; ++ host->completed_events = 0; ++ host->data_status = 0; ++ // do_gettimeofday(&mrq->rq_times[4]); ++ host->data_error_flag = 0; ++ data = mrq->data; ++ if (data) { ++ fh_mci_set_timeout(host); ++ mci_writel(host, BYTCNT, data->blksz*data->blocks); ++ mci_writel(host, BLKSIZ, data->blksz); ++ } ++ // do_gettimeofday(&mrq->rq_times[5]); ++ cmd = mrq->cmd; ++ cmdflags = fh_mci_prepare_command(slot->mmc, cmd); ++ /* this is the first command, send the initialization clock */ ++ if (test_and_clear_bit(FH_MMC_CARD_NEED_INIT, &slot->flags)) ++ cmdflags |= SDMMC_CMD_INIT; ++ // do_gettimeofday(&mrq->rq_times[6]); ++ if (data) { ++ fh_mci_submit_data(host, data); ++ wmb(); ++ } ++ fh_mci_start_command(host, cmd, cmdflags); ++ if (mrq->stop){ ++ host->stop_cmdr = fh_mci_prepare_command(slot->mmc, mrq->stop); ++ } ++ ++} ++ ++ ++/* must be called with host->lock held */ ++static void fh_mci_queue_request(struct fh_mci *host, struct fh_mci_slot *slot, ++ struct mmc_request *mrq) ++{ ++ dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n", ++ host->state); ++ slot->mrq = mrq; ++ ++ if (host->state == STATE_IDLE) { ++ host->state = STATE_SENDING_CMD; ++ fh_mci_start_request(host, slot); ++ } else { ++ list_add_tail(&slot->queue_node, &host->queue); ++ ++ } ++} ++ ++static void fh_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct fh_mci_slot *slot = mmc_priv(mmc); ++ struct fh_mci *host = slot->host; ++ ++ WARN_ON(slot->mrq); ++ /* ++ * The check for card presence and queueing of the request must be ++ * atomic, otherwise the card could be removed in between and the ++ * request wouldn't fail until another card was inserted. ++ */ ++ spin_lock_bh(&host->lock); ++ if (!test_bit(FH_MMC_CARD_PRESENT, &slot->flags)) { ++ spin_unlock_bh(&host->lock); ++ mrq->cmd->error = -ENOMEDIUM; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ /* We don't support multiple blocks of weird lengths. */ ++ fh_mci_queue_request(host, slot, mrq); ++ spin_unlock_bh(&host->lock); ++} ++ ++static void fh_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ u32 regs; ++ struct fh_mci_slot *slot = mmc_priv(mmc); ++#if 0 ++ struct clk* sdc_clk; ++ int sdc_id = slot->host->pdev->id; ++ ++ ++ if(sdc_id) ++ { ++ printk("fh_mci_set_ios, clk: %lu\n", ios->clock); ++ sdc_clk = clk_get(NULL, "sdc1_clk"); ++ clk_set_rate(sdc_clk,ios->clock); ++ } ++ else ++ { ++ sdc_clk = clk_get(NULL, "sdc0_clk"); ++ clk_set_rate(sdc_clk,ios->clock); ++ } ++#endif ++ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_4: ++ slot->ctype = SDMMC_CTYPE_4BIT; ++ break; ++ case MMC_BUS_WIDTH_8: ++ slot->ctype = SDMMC_CTYPE_8BIT; ++ break; ++ default: ++ /* set default 1 bit mode */ ++ slot->ctype = SDMMC_CTYPE_1BIT; ++ } ++ /* DDR mode set */ ++ if (ios->ddr) { ++ regs = mci_readl(slot->host, UHS_REG); ++ regs |= (0x1 << slot->id) << 16; ++ mci_writel(slot->host, UHS_REG, regs); ++ } ++ ++ if (ios->clock) { ++ /* ++ * Use mirror of ios->clock to prevent race with mmc ++ * core ios update when finding the minimum. ++ */ ++ slot->clock = ios->clock; ++ } ++ ++ switch (ios->power_mode) { ++ case MMC_POWER_UP: ++ set_bit(FH_MMC_CARD_NEED_INIT, &slot->flags); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int fh_mci_get_ro(struct mmc_host *mmc) ++{ ++ int read_only; ++ struct fh_mci_slot *slot = mmc_priv(mmc); ++ struct fh_mci_board *brd = slot->host->pdata; ++ ++ /* Use platform get_ro function, else try on board write protect */ ++ if (brd->get_ro) ++ read_only = brd->get_ro(slot->id); ++ else ++ read_only = ++ mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; ++ ++ dev_dbg(&mmc->class_dev, "card is %s\n", ++ read_only ? "read-only" : "read-write"); ++ ++ return read_only; ++} ++ ++static int fh_mci_get_cd(struct mmc_host *mmc) ++{ ++ int present; ++ struct fh_mci_slot *slot = mmc_priv(mmc); ++ struct fh_mci_board *brd = slot->host->pdata; ++ struct fh_mci *host = slot->host; ++ ++ /* Use platform get_cd function, else try onboard card detect */ ++ if (brd->quirks & FH_MCI_QUIRK_BROKEN_CARD_DETECTION) ++ present = 1; ++ else if (brd->get_cd) ++ present = !brd->get_cd(slot->id); ++ else ++ present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) ++ == 0 ? 1 : 0; ++ ++ spin_lock_bh(&host->lock); ++ if (present) ++ dev_dbg(&mmc->class_dev, "card is present\n"); ++ else ++ dev_dbg(&mmc->class_dev, "card is not present\n"); ++ spin_unlock_bh(&host->lock); ++ ++ return present; ++} ++ ++/* ++ * Disable lower power mode. ++ * ++ * Low power mode will stop the card clock when idle. According to the ++ * description of the CLKENA register we should disable low power mode ++ * for SDIO cards if we need SDIO interrupts to work. ++ * ++ * This function is fast if low power mode is already disabled. ++ */ ++static void fh_mci_disable_low_power(struct fh_mci_slot *slot) ++{ ++ struct fh_mci *host = slot->host; ++ u32 clk_en_a; ++ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; ++ ++ clk_en_a = mci_readl(host, CLKENA); ++ ++ if (clk_en_a & clken_low_pwr) { ++ mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); ++ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | ++ SDMMC_CMD_PRV_DAT_WAIT, 0); ++ } ++} ++ ++static void fh_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) ++{ ++ struct fh_mci_slot *slot = mmc_priv(mmc); ++ struct fh_mci *host = slot->host; ++ u32 int_mask; ++ ++ /* Enable/disable Slot Specific SDIO interrupt */ ++ int_mask = mci_readl(host, INTMASK); ++ if (enb) { ++ /* ++ * Turn off low power mode if it was enabled. This is a bit of ++ * a heavy operation and we disable / enable IRQs a lot, so ++ * we'll leave low power mode disabled and it will get ++ * re-enabled again in fh_mci_setup_bus(). ++ */ ++ fh_mci_disable_low_power(slot); ++ ++ mci_writel(host, INTMASK, ++ (int_mask | SDMMC_INT_SDIO(slot->id))); ++ } else { ++ mci_writel(host, INTMASK, ++ (int_mask & ~SDMMC_INT_SDIO(slot->id))); ++ } ++} ++ ++ ++static const struct mmc_host_ops fh_mci_ops = { ++ .request = fh_mci_request, ++ .set_ios = fh_mci_set_ios, ++ .get_ro = fh_mci_get_ro, ++ .get_cd = fh_mci_get_cd, ++ ++ ++ .enable_sdio_irq = fh_mci_enable_sdio_irq, ++}; ++ ++static void fh_mci_request_end(struct fh_mci *host, struct mmc_request *mrq) ++ __releases(&host->lock) ++ __acquires(&host->lock) ++{ ++ struct fh_mci_slot *slot; ++ struct mmc_host *prev_mmc = host->cur_slot->mmc; ++ ++ if(host->data && host->data->error) ++ printk(KERN_ERR "fh SDC : func request_end\n"); ++ ++ WARN_ON(host->cmd || host->data); ++ ++ host->cur_slot->mrq = NULL; ++ host->mrq = NULL; ++ if (!list_empty(&host->queue)) { ++ slot = list_entry(host->queue.next, ++ struct fh_mci_slot, queue_node); ++ list_del(&slot->queue_node); ++ dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n", ++ mmc_hostname(slot->mmc)); ++ host->state = STATE_SENDING_CMD; ++ fh_mci_start_request(host, slot); ++ } else { ++ dev_vdbg(&host->pdev->dev, "list empty\n"); ++ host->state = STATE_IDLE; ++ } ++ ++ spin_unlock(&host->lock); ++ mmc_request_done(prev_mmc, mrq); ++ spin_lock(&host->lock); ++} ++ ++static void fh_mci_command_complete(struct fh_mci *host, struct mmc_command *cmd) ++{ ++ u32 status = host->cmd_status; ++ ++ host->cmd_status = 0; ++ ++ /* Read the response from the card (up to 16 bytes) */ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ if (cmd->flags & MMC_RSP_136) { ++ cmd->resp[3] = mci_readl(host, RESP0); ++ cmd->resp[2] = mci_readl(host, RESP1); ++ cmd->resp[1] = mci_readl(host, RESP2); ++ cmd->resp[0] = mci_readl(host, RESP3); ++ } else { ++ cmd->resp[0] = mci_readl(host, RESP0); ++ cmd->resp[1] = 0; ++ cmd->resp[2] = 0; ++ cmd->resp[3] = 0; ++ } ++ ++ } ++ ++ if (status & SDMMC_INT_RTO) ++ cmd->error = -ETIMEDOUT; ++ else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)) ++ cmd->error = -EILSEQ; ++ else if (status & SDMMC_INT_RESP_ERR) ++ cmd->error = -EIO; ++ else ++ cmd->error = 0; ++ ++ if (cmd->error) { ++ /* newer ip versions need a delay between retries */ ++ if (host->quirks & FH_MCI_QUIRK_RETRY_DELAY) ++ mdelay(20); ++ ++ if (cmd->data) { ++ host->data = NULL; ++ fh_mci_stop_dma(host); ++ } ++ } ++} ++ ++static void fh_mci_tasklet_func(unsigned long priv) ++{ ++ struct fh_mci *host = (struct fh_mci *)priv; ++ struct mmc_data *data; ++ struct mmc_command *cmd; ++ enum fh_mci_state state; ++ enum fh_mci_state prev_state; ++ u32 status; ++ ++ spin_lock(&host->lock); ++ ++ state = host->state; ++ data = host->data; ++ ++ do { ++ prev_state = state; ++ ++ switch (state) { ++ case STATE_IDLE: ++ break; ++ ++ case STATE_SENDING_CMD: ++ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ cmd = host->cmd; ++ host->cmd = NULL; ++ set_bit(EVENT_CMD_COMPLETE, &host->completed_events); ++ fh_mci_command_complete(host, host->mrq->cmd); ++ ++ ++ if (!host->mrq->data || cmd->error) { ++ fh_mci_request_end(host, host->mrq); ++ goto unlock; ++ } ++ ++ prev_state = state = STATE_SENDING_DATA; ++ /* fall through */ ++ ++ case STATE_SENDING_DATA: ++ if (test_and_clear_bit(EVENT_DATA_ERROR, ++ &host->pending_events)) { ++ printk(KERN_ERR "fh SDC : STATE_SENDING_DATA EVENT_DATA_ERROR\n"); ++ fh_mci_stop_dma(host); ++ if (data->stop) ++ send_stop_cmd(host, data); ++ state = STATE_DATA_ERROR; ++ break; ++ } ++ ++ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ set_bit(EVENT_XFER_COMPLETE, &host->completed_events); ++ prev_state = state = STATE_DATA_BUSY; ++ /* fall through */ ++ ++ case STATE_DATA_BUSY: ++ if (!test_and_clear_bit(EVENT_DATA_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ host->data = NULL; ++ set_bit(EVENT_DATA_COMPLETE, &host->completed_events); ++ status = host->data_status; ++ ++ if (status & FH_MCI_DATA_ERROR_FLAGS) { ++ printk(KERN_ERR "fh SDC : STATE_DATA_BUSY\n"); ++ if (status & SDMMC_INT_DTO) { ++ dev_err(&host->pdev->dev, ++ "data timeout error\n"); ++ data->error = -ETIMEDOUT; ++ } else if (status & SDMMC_INT_DCRC) { ++ dev_err(&host->pdev->dev, ++ "data CRC error\n"); ++ data->error = -EILSEQ; ++ } else { ++ dev_err(&host->pdev->dev, ++ "data FIFO error " ++ "(status=%08x)\n", ++ status); ++ data->error = -EIO; ++ } ++ } else { ++ data->bytes_xfered = data->blocks * data->blksz; ++ data->error = 0; ++ } ++ ++ if (!data->stop) { ++ fh_mci_request_end(host, host->mrq); ++ goto unlock; ++ } ++ ++ prev_state = state = STATE_SENDING_STOP; ++ if (!data->error) ++ send_stop_cmd(host, data); ++ /* fall through */ ++ ++ case STATE_SENDING_STOP: ++ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ host->cmd = NULL; ++ fh_mci_command_complete(host, host->mrq->stop); ++ fh_mci_request_end(host, host->mrq); ++ goto unlock; ++ ++ case STATE_DATA_ERROR: ++ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, ++ &host->pending_events)) ++ break; ++ printk(KERN_ERR "fh SDC : STATE_DATA_ERROR\n"); ++ ++ state = STATE_DATA_BUSY; ++ break; ++ } ++ } while (state != prev_state); ++ host->state = state; ++unlock: ++ spin_unlock(&host->lock); ++ ; ++ ++} ++ ++static void fh_mci_push_data16(struct fh_mci *host, void *buf, int cnt) ++{ ++ u16 *pdata = (u16 *)buf; ++ ++ WARN_ON(cnt % 2 != 0); ++ ++ cnt = cnt >> 1; ++ while (cnt > 0) { ++ mci_writew(host, DATA, *pdata++); ++ cnt--; ++ } ++} ++ ++static void fh_mci_pull_data16(struct fh_mci *host, void *buf, int cnt) ++{ ++ u16 *pdata = (u16 *)buf; ++ ++ WARN_ON(cnt % 2 != 0); ++ ++ cnt = cnt >> 1; ++ while (cnt > 0) { ++ *pdata++ = mci_readw(host, DATA); ++ cnt--; ++ } ++} ++ ++static void fh_mci_push_data32(struct fh_mci *host, void *buf, int cnt) ++{ ++ u32 *pdata = (u32 *)buf; ++ ++ WARN_ON(cnt % 4 != 0); ++ WARN_ON((unsigned long)pdata & 0x3); ++ ++ cnt = cnt >> 2; ++ while (cnt > 0) { ++ mci_writel(host, DATA, *pdata++); ++ cnt--; ++ } ++} ++ ++static void fh_mci_pull_data32(struct fh_mci *host, void *buf, int cnt) ++{ ++ u32 *pdata = (u32 *)buf; ++ ++ WARN_ON(cnt % 4 != 0); ++ WARN_ON((unsigned long)pdata & 0x3); ++ ++ cnt = cnt >> 2; ++ while (cnt > 0) { ++ *pdata++ = mci_readl(host, DATA); ++ cnt--; ++ } ++} ++ ++static void fh_mci_push_data64(struct fh_mci *host, void *buf, int cnt) ++{ ++ u64 *pdata = (u64 *)buf; ++ ++ WARN_ON(cnt % 8 != 0); ++ ++ cnt = cnt >> 3; ++ while (cnt > 0) { ++ mci_writeq(host, DATA, *pdata++); ++ cnt--; ++ } ++} ++ ++static void fh_mci_pull_data64(struct fh_mci *host, void *buf, int cnt) ++{ ++ u64 *pdata = (u64 *)buf; ++ ++ WARN_ON(cnt % 8 != 0); ++ ++ cnt = cnt >> 3; ++ while (cnt > 0) { ++ *pdata++ = mci_readq(host, DATA); ++ cnt--; ++ } ++} ++ ++static void fh_mci_read_data_pio(struct fh_mci *host) ++{ ++ struct scatterlist *sg = host->sg; ++ void *buf = sg_virt(sg); ++ unsigned int offset = host->pio_offset; ++ struct mmc_data *data = host->data; ++ int shift = host->data_shift; ++ u32 status; ++ unsigned int nbytes = 0, len=0; ++ ++ do { ++ len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift; ++ if (offset + len <= sg->length) { ++ ++ host->pull_data(host, (void *)(buf + offset), len); ++ offset += len; ++ nbytes += len; ++ ++ if (offset == sg->length) { ++ flush_dcache_page(sg_page(sg)); ++ host->sg = sg = sg_next(sg); ++ if (!sg) ++ goto done; ++ ++ offset = 0; ++ buf = sg_virt(sg); ++ } ++ } else { ++ unsigned int remaining = sg->length - offset; ++ host->pull_data(host, (void *)(buf + offset), ++ remaining); ++ nbytes += remaining; ++ ++ flush_dcache_page(sg_page(sg)); ++ host->sg = sg = sg_next(sg); ++ if (!sg) ++ goto done; ++ ++ offset = len - remaining; ++ buf = sg_virt(sg); ++ host->pull_data(host, buf, offset); ++ nbytes += offset; ++ } ++ ++ status = mci_readl(host, MINTSTS); ++ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); ++ if (status & FH_MCI_DATA_ERROR_FLAGS) { ++ host->data_status = status; ++ data->bytes_xfered += nbytes; ++ smp_wmb(); ++ printk("data error in read pio\n"); ++ set_bit(EVENT_DATA_ERROR, &host->pending_events); ++ ++ tasklet_schedule(&host->tasklet); ++ return; ++ } ++ } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ ++ len = SDMMC_GET_FCNT(mci_readl(host, STATUS)); ++ host->pio_offset = offset; ++ data->bytes_xfered += nbytes; ++ return; ++ ++done: ++ data->bytes_xfered += nbytes; ++ smp_wmb(); ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static void fh_mci_write_data_pio(struct fh_mci *host) ++{ ++ struct scatterlist *sg = host->sg; ++ void *buf = sg_virt(sg); ++ unsigned int offset = host->pio_offset; ++ struct mmc_data *data = host->data; ++ int shift = host->data_shift; ++ u32 status; ++ unsigned int nbytes = 0, len; ++ ++ do { ++ len = SDMMC_FIFO_SZ - ++ (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); ++ if (offset + len <= sg->length) { ++ host->push_data(host, (void *)(buf + offset), len); ++ ++ ++ offset += len; ++ nbytes += len; ++ if (offset == sg->length) { ++ host->sg = sg = sg_next(sg); ++ if (!sg) ++ goto done; ++ ++ offset = 0; ++ buf = sg_virt(sg); ++ } ++ } else { ++ unsigned int remaining = sg->length - offset; ++ ++ host->push_data(host, (void *)(buf + offset), ++ remaining); ++ nbytes += remaining; ++ host->sg = sg = sg_next(sg); ++ if (!sg) ++ goto done; ++ ++ offset = len - remaining; ++ buf = sg_virt(sg); ++ host->push_data(host, (void *)buf, offset); ++ nbytes += offset; ++ } ++ ++ status = mci_readl(host, MINTSTS); ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); ++ if (status & FH_MCI_DATA_ERROR_FLAGS) { ++ host->data_status = status; ++ data->bytes_xfered += nbytes; ++ ++ smp_wmb(); ++ printk("data error in write pio\n"); ++ set_bit(EVENT_DATA_ERROR, &host->pending_events); ++ ++ tasklet_schedule(&host->tasklet); ++ return; ++ } ++ } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ ++ ++ host->pio_offset = offset; ++ data->bytes_xfered += nbytes; ++ //flag_int = mci_readl(host, INTMASK); ++ //mci_writel(host, INTMASK, flag_int|0x4); ++ return; ++ ++done: ++ data->bytes_xfered += nbytes; ++ smp_wmb(); ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static void fh_mci_cmd_interrupt(struct fh_mci *host, u32 status) ++{ ++ if (!host->cmd_status) ++ host->cmd_status = status; ++ ++ smp_wmb(); ++ ++ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++} ++ ++ ++static irqreturn_t fh_mci_interrupt(int irq, void *dev_id) ++{ ++ struct fh_mci *host = dev_id; ++ u32 pending; ++ int i; ++ u32 cmd, arg, rint, resp0, resp1, resp2, resp3; ++ #ifdef SDC_CRC_TEST ++ struct clk *sdc_clk; ++ #endif ++ ++ pending = mci_readl(host, MINTSTS); /* read-only mask reg */ ++ ++ if (pending) { ++ if (pending & FH_MCI_CMD_ERROR_FLAGS) { ++ mci_writel(host, RINTSTS, FH_MCI_CMD_ERROR_FLAGS); ++ host->cmd_status = pending; ++ smp_wmb(); ++ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); ++ } ++ ++ if (pending & FH_MCI_DATA_ERROR_FLAGS) { ++#ifdef SDC_CRC_TEST ++ gpio_direction_output(TEST_GPIO, 1); ++ __gpio_set_value(TEST_GPIO, 1); ++#endif ++ host->data_error_flag = 1; ++ rint = mci_readl(host, RINTSTS); ++ /* if there is an error report DATA_ERROR */ ++ mci_writel(host, RINTSTS, FH_MCI_DATA_ERROR_FLAGS); ++ host->data_status = pending; ++ smp_wmb(); ++ cmd = mci_readl(host, CMD); ++ arg = mci_readl(host, CMDARG); ++ printk("data error in interrupt, cmd=0x%x, args=0x%x, rintsts=0x%x\n", ++ cmd, arg, rint); ++ ++ resp0 = mci_readl(host, RESP0); ++ resp1 = mci_readl(host, RESP1); ++ resp2 = mci_readl(host, RESP2); ++ resp3 = mci_readl(host, RESP3); ++ ++ printk("resp0=0x%x, resp1=0x%x, resp2=0x%x, resp3=0x%x\n", ++ resp0, resp1, resp2, resp3); ++ set_bit(EVENT_DATA_ERROR, &host->pending_events); ++ set_bit(EVENT_DATA_COMPLETE, &host->pending_events); ++#ifdef SDC_CRC_TEST ++ sdc_clk = clk_get(NULL, "sdc0_clk"); ++ clk_disable(sdc_clk); ++ ++ printk("!!!!!!!!!!!sdc stopped!!!!!!!!!!!!\n"); ++ panic("really terrible\n"); ++#endif ++ tasklet_schedule(&host->tasklet); ++ ++ } ++ ++ if (likely(pending & SDMMC_INT_DATA_OVER)) { ++ mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); ++ if (!host->data_status) ++ host->data_status = pending; ++ smp_wmb(); ++ if (host->dir_status == FH_MCI_RECV_STATUS) { ++ if (host->sg != NULL) ++ fh_mci_read_data_pio(host); ++ } ++ set_bit(EVENT_DATA_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++ } ++ ++ if (pending & SDMMC_INT_RXDR) { ++ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); ++ if (host->dir_status == FH_MCI_RECV_STATUS && host->sg) ++ fh_mci_read_data_pio(host); ++ } ++ ++ if (pending & SDMMC_INT_TXDR) { ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); ++ if (host->dir_status == FH_MCI_SEND_STATUS && host->sg) ++ fh_mci_write_data_pio(host); ++ } ++ ++ if (likely(pending & SDMMC_INT_CMD_DONE)) { ++ mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); ++ fh_mci_cmd_interrupt(host, pending); ++ } ++ ++ if (pending & SDMMC_INT_CD) { ++ mci_writel(host, RINTSTS, SDMMC_INT_CD); ++ tasklet_schedule(&host->card_tasklet); ++ } ++ ++ /* Handle SDIO Interrupts */ ++ for (i = 0; i < host->num_slots; i++) { ++ struct fh_mci_slot *slot = host->slot[i]; ++ if (pending & SDMMC_INT_SDIO(i)) { ++ mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i)); ++ mmc_signal_sdio_irq(slot->mmc); ++ } ++ } ++ ++ } ++#ifdef CONFIG_MMC_FH_IDMAC ++ /* Handle DMA interrupts */ ++ pending = mci_readl(host, IDSTS); ++ if (likely(pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI))) { ++ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_NI); ++ set_bit(EVENT_DATA_COMPLETE, &host->pending_events); ++ host->dma_ops->complete(host); ++ } ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++static void fh_mci_tasklet_card(unsigned long data) ++{ ++ struct fh_mci *host = (struct fh_mci *)data; ++ int i; ++ ++ for (i = 0; i < host->num_slots; i++) { ++ struct fh_mci_slot *slot = host->slot[i]; ++ struct mmc_host *mmc = slot->mmc; ++ struct mmc_request *mrq; ++ int present; ++ u32 ctrl; ++ present = fh_mci_get_cd(mmc); ++ while (present != slot->last_detect_state) { ++ dev_dbg(&slot->mmc->class_dev, "card %s\n", ++ present ? "inserted" : "removed"); ++ ++ spin_lock(&host->lock); ++ ++ /* Card change detected */ ++ slot->last_detect_state = present; ++ ++ /* Power up slot */ ++ if (present != 0) { ++ if (host->pdata->setpower) ++ host->pdata->setpower(slot->id, ++ mmc->ocr_avail); ++ ++ set_bit(FH_MMC_CARD_PRESENT, &slot->flags); ++ } ++ ++ /* Clean up queue if present */ ++ mrq = slot->mrq; ++ if (mrq) { ++ if (mrq == host->mrq) { ++ host->data = NULL; ++ host->cmd = NULL; ++ ++ switch (host->state) { ++ case STATE_IDLE: ++ break; ++ case STATE_SENDING_CMD: ++ mrq->cmd->error = -ENOMEDIUM; ++ if (!mrq->data) ++ break; ++ /* fall through */ ++ case STATE_SENDING_DATA: ++ mrq->data->error = -ENOMEDIUM; ++ fh_mci_stop_dma(host); ++ break; ++ case STATE_DATA_BUSY: ++ case STATE_DATA_ERROR: ++ printk("STATE_DATA_ERROR in tasklet card\n"); ++ if (mrq->data->error == -EINPROGRESS) ++ mrq->data->error = -ENOMEDIUM; ++ if (!mrq->stop) ++ break; ++ /* fall through */ ++ case STATE_SENDING_STOP: ++ mrq->stop->error = -ENOMEDIUM; ++ break; ++ } ++ ++ fh_mci_request_end(host, mrq); ++ } else { ++ list_del(&slot->queue_node); ++ mrq->cmd->error = -ENOMEDIUM; ++ if (mrq->data) ++ mrq->data->error = -ENOMEDIUM; ++ if (mrq->stop) ++ mrq->stop->error = -ENOMEDIUM; ++ ++ spin_unlock(&host->lock); ++ mmc_request_done(slot->mmc, mrq); ++ spin_lock(&host->lock); ++ } ++ } ++ ++ /* Power down slot */ ++ if (present == 0) { ++ if (host->pdata->setpower) ++ host->pdata->setpower(slot->id, 0); ++ clear_bit(FH_MMC_CARD_PRESENT, &slot->flags); ++ ++ /* ++ * Clear down the FIFO - doing so generates a ++ * block interrupt, hence setting the ++ * scatter-gather pointer to NULL. ++ */ ++ host->sg = NULL; ++ ++ ctrl = mci_readl(host, CTRL); ++ ctrl |= SDMMC_CTRL_FIFO_RESET; ++ mci_writel(host, CTRL, ctrl); ++ ++#ifdef CONFIG_MMC_FH_IDMAC ++ ctrl = mci_readl(host, BMOD); ++ ctrl |= SDMMC_IDMAC_SWRESET; /* Software reset of DMA */ ++ mci_writel(host, BMOD, ctrl); ++#endif ++ ++ } ++ ++ spin_unlock(&host->lock); ++ present = fh_mci_get_cd(mmc); ++ } ++ ++ mmc_detect_change(slot->mmc, ++ msecs_to_jiffies(host->pdata->detect_delay_ms)); ++ } ++} ++ ++static int __init fh_mci_init_slot(struct fh_mci *host, unsigned int id) ++{ ++ struct mmc_host *mmc; ++ struct fh_mci_slot *slot; ++ ++ mmc = mmc_alloc_host(sizeof(struct fh_mci_slot), &host->pdev->dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ slot = mmc_priv(mmc); ++ slot->id = id; ++ slot->mmc = mmc; ++ slot->host = host; ++ ++ mmc->ops = &fh_mci_ops; ++ mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); ++ mmc->f_max = 50000000;//12500000; ++ ++ if (host->pdata->get_ocr) ++ mmc->ocr_avail = host->pdata->get_ocr(id); ++ else ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ /* ++ * Start with slot power disabled, it will be enabled when a card ++ * is detected. ++ */ ++ if (host->pdata->setpower) ++ host->pdata->setpower(id, 0); ++ ++ if (host->pdata->caps) ++ mmc->caps = host->pdata->caps; ++ else ++ mmc->caps = 0; ++ ++ if (host->pdata->get_bus_wd) ++ if (host->pdata->get_bus_wd(slot->id) >= 4) ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ ++ if (host->pdata->quirks & FH_MCI_QUIRK_HIGHSPEED) ++ mmc->caps |= MMC_CAP_SD_HIGHSPEED; ++ ++#ifdef CONFIG_MMC_FH_IDMAC ++ /* Useful defaults if platform data is unset. */ ++ mmc->max_segs = 64; ++ mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ ++ mmc->max_blk_count = 512; ++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; ++ mmc->max_seg_size = mmc->max_req_size; ++#else ++ if (host->pdata->blk_settings) { ++ mmc->max_segs = host->pdata->blk_settings->max_segs; ++ mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; ++ mmc->max_blk_count = host->pdata->blk_settings->max_blk_count; ++ mmc->max_req_size = host->pdata->blk_settings->max_req_size; ++ mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; ++ } else { ++ /* Useful defaults if platform data is unset. */ ++ mmc->max_segs = 64; ++ mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ ++ mmc->max_blk_count = 512; ++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; ++ mmc->max_seg_size = mmc->max_req_size; ++ } ++#endif /* CONFIG_MMC_FH_IDMAC */ ++ ++ host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); ++ if (IS_ERR(host->vmmc)) { ++ host->vmmc = NULL; ++ } else ++ regulator_enable(host->vmmc); ++ ++ if (fh_mci_get_cd(mmc)) ++ set_bit(FH_MMC_CARD_PRESENT, &slot->flags); ++ else ++ clear_bit(FH_MMC_CARD_PRESENT, &slot->flags); ++ ++ host->slot[id] = slot; ++ mmc_add_host(mmc); ++ ++#if defined(CONFIG_DEBUG_FS) ++ fh_mci_init_debugfs(slot); ++#endif ++ ++ /* Card initially undetected */ ++ slot->last_detect_state = 0; ++ ++ /* ++ * Card may have been plugged in prior to boot so we ++ * need to run the detect tasklet ++ */ ++ tasklet_schedule(&host->card_tasklet); ++ ++ return 0; ++} ++ ++static void fh_mci_cleanup_slot(struct fh_mci_slot *slot, unsigned int id) ++{ ++ /* Shutdown detect IRQ */ ++ if (slot->host->pdata->exit) ++ slot->host->pdata->exit(id); ++ ++ /* Debugfs stuff is cleaned up by mmc core */ ++ mmc_remove_host(slot->mmc); ++ slot->host->slot[id] = NULL; ++ mmc_free_host(slot->mmc); ++} ++ ++static void fh_mci_init_dma(struct fh_mci *host) ++{ ++ /* Alloc memory for sg translation */ ++ host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, SDC_DESC_SIZE, ++ &host->sg_dma, GFP_KERNEL); ++ if (!host->sg_cpu) { ++ dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n", ++ __func__); ++ goto no_dma; ++ } ++ ++ /* Determine which DMA interface to use */ ++#ifdef CONFIG_MMC_FH_IDMAC ++ host->dma_ops = &fh_mci_idmac_ops; ++ dev_info(&host->pdev->dev, "Using internal DMA controller.\n"); ++#endif ++ ++ if (!host->dma_ops) ++ goto no_dma; ++ ++ if (host->dma_ops->init) { ++ if (host->dma_ops->init(host)) { ++ dev_err(&host->pdev->dev, "%s: Unable to initialize " ++ "DMA Controller.\n", __func__); ++ goto no_dma; ++ } ++ } else { ++ dev_err(&host->pdev->dev, "DMA initialization not found.\n"); ++ goto no_dma; ++ } ++ ++ host->use_dma = 1; ++ return; ++ ++no_dma: ++ dev_info(&host->pdev->dev, "Using PIO mode.\n"); ++ host->use_dma = 0; ++ return; ++} ++ ++static bool mci_wait_reset(struct device *dev, struct fh_mci *host) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(500); ++ unsigned int ctrl; ++ ++ mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | ++ SDMMC_CTRL_DMA_RESET)); ++ ++ /* wait till resets clear */ ++ do { ++ ctrl = mci_readl(host, CTRL); ++ if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | ++ SDMMC_CTRL_DMA_RESET))) ++ return true; ++ } while (time_before(jiffies, timeout)); ++ ++ dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl); ++ ++ return false; ++} ++ ++static int fh_mci_probe(struct platform_device *pdev) ++{ ++ struct fh_mci *host; ++ struct resource *regs; ++ struct fh_mci_board *pdata; ++ int irq, ret, i, width; ++ u32 fifo_size; ++ u32 reg; ++ struct clk *sdc_clk; ++ ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) ++ return -ENXIO; ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ host = kzalloc(sizeof(struct fh_mci), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ ++ host->pdev = pdev; ++ host->pdata = pdata = pdev->dev.platform_data; ++ if (!pdata || !pdata->init) { ++ dev_err(&pdev->dev, ++ "Platform data must supply init function\n"); ++ ret = -ENODEV; ++ goto err_freehost; ++ } ++ ++ if (!pdata->select_slot && pdata->num_slots > 1) { ++ dev_err(&pdev->dev, ++ "Platform data must supply select_slot function\n"); ++ ret = -ENODEV; ++ goto err_freehost; ++ } ++ ++ if (!pdata->bus_hz) { ++ dev_err(&pdev->dev, ++ "Platform data must supply bus speed\n"); ++ ret = -ENODEV; ++ goto err_freehost; ++ } ++ ++ host->bus_hz = pdata->bus_hz; ++ host->quirks = pdata->quirks; ++ ++ spin_lock_init(&host->lock); ++ INIT_LIST_HEAD(&host->queue); ++ ++ pdata->init(pdev->id, NULL, NULL); ++ ++ ret = -ENOMEM; ++ //enable clk ++ ++ if(pdev->id){ ++ ret = gpio_request(6, NULL); ++ if(ret){ ++ printk("gpio requset err\n"); ++ ret = -ENODEV; ++ return ret; ++ } ++ gpio_direction_output(6,0);//set power on ++ sdc_clk = clk_get(NULL, "sdc1_clk"); ++ clk_enable(sdc_clk); ++// *(int *)0xfe900020 =0x100000;//wait for modify ++ ++ clk_set_rate(sdc_clk,50000000); ++ reg = clk_get_clk_sel(); ++ reg |=1<<12; ++ reg &=~(1<<13); ++ clk_set_clk_sel(reg); ++ } ++ else ++ { ++ ret = gpio_request(5, NULL); ++ if(ret){ ++ printk("gpio requset err\n"); ++ ret = -ENODEV; ++ return ret; ++ } ++ gpio_direction_output(5,0);//set power on ++ sdc_clk = clk_get(NULL, "sdc0_clk"); ++ clk_enable(sdc_clk); ++ ++ clk_set_rate(sdc_clk,50000000); ++ reg = clk_get_clk_sel(); ++ reg |=1<<20; ++ reg &=~(1<<21); ++ ++#define SIMPLE_0 ++//#define SIMPLE_90 ++//#define SIMPLE_180 ++//#define SIMPLE_270 ++ ++#ifdef SIMPLE_0 ++ //0 ++ reg &=~(1<<17); ++ reg &=~(1<<16); ++#endif ++#ifdef SIMPLE_90 ++ //90 ++ reg |=(1<<16); ++ reg &=~(1<<17); ++#endif ++#ifdef SIMPLE_180 ++ //180 ++ reg &=~(1<<16); ++ reg |=(1<<17); ++#endif ++#ifdef SIMPLE_270 ++ //270 ++ reg |=(1<<17); ++ reg |=(1<<16); ++#endif ++ clk_set_clk_sel(reg); ++ ++ } ++ ++ //io_remap ++ host->regs = ioremap(regs->start, regs->end - regs->start + 1); ++ //host->regs = 0xfe700000; ++ if (!host->regs) ++ goto err_freehost; ++ ++ //host->dma_ops = pdata->dma_ops; ++ fh_mci_init_dma(host); ++ ++ /* ++ * Get the host data width - this assumes that HCON has been set with ++ * the correct values. ++ */ ++ i = (mci_readl(host, HCON) >> 7) & 0x7; ++ if (!i) { ++ host->push_data = fh_mci_push_data16; ++ host->pull_data = fh_mci_pull_data16; ++ width = 16; ++ host->data_shift = 1; ++ } else if (i == 2) { ++ host->push_data = fh_mci_push_data64; ++ host->pull_data = fh_mci_pull_data64; ++ width = 64; ++ host->data_shift = 3; ++ } else { ++ /* Check for a reserved value, and warn if it is */ ++ WARN((i != 1), ++ ++ "HCON reports a reserved host data width!\n" ++ "Defaulting to 32-bit access.\n"); ++ host->push_data = fh_mci_push_data32; ++ host->pull_data = fh_mci_pull_data32; ++ width = 32; ++ host->data_shift = 2; ++ } ++ ++ /* Reset all blocks */ ++ if (!mci_wait_reset(&pdev->dev, host)) { ++ ret = -ENODEV; ++ goto err_dmaunmap; ++ } ++ ++ /* Clear the interrupts for the host controller */ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ ++ ++ /* Put in max timeout */ ++ mci_writel(host, TMOUT, 0xFFFFFFFF); ++ ++ /* ++ * FIFO threshold settings RxMark = fifo_size / 2 - 1, ++ * Tx Mark = fifo_size / 2 DMA Size = 8 ++ */ ++ fifo_size = mci_readl(host, FIFOTH); ++ fifo_size = 1+((fifo_size >> 16) & 0x7ff); ++ host->fifoth_val = ++ SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ ++ /* disable clock to CIU */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ tasklet_init(&host->tasklet, fh_mci_tasklet_func, (unsigned long)host); ++ tasklet_init(&host->card_tasklet, ++ fh_mci_tasklet_card, (unsigned long)host); ++ ++ ret = request_irq(irq, fh_mci_interrupt, 0, "fh-mci", host); ++ if (ret) ++ goto err_dmaunmap; ++ ++ platform_set_drvdata(pdev, host); ++ ++ if (host->pdata->num_slots) ++ host->num_slots = host->pdata->num_slots; ++ else ++ host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; ++ ++ /* We need at least one slot to succeed */ ++ for (i = 0; i < host->num_slots; i++) { ++ ret = fh_mci_init_slot(host, i); ++ if (ret) { ++ ret = -ENODEV; ++ goto err_init_slot; ++ } ++ } ++ ++ /* ++ * Enable interrupts for command done, data over, data empty, card det, ++ * receive ready and error such as transmit, receive timeout, crc error ++ */ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |SDMMC_INT_RTO | SDMMC_INT_DTO | ++ SDMMC_INT_TXDR | SDMMC_INT_RXDR | ++ FH_MCI_ERROR_FLAGS | SDMMC_INT_CD); ++ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ ++ ++ dev_info(&pdev->dev, "FH MMC controller at irq %d, " ++ "%d bit host data width\n", irq, width); ++ if (host->quirks & FH_MCI_QUIRK_IDMAC_DTO) ++ dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n"); ++#ifdef SDC_CRC_TEST ++ ret = gpio_request(TEST_GPIO, "SDC_TEST"); ++ ++ if(ret) ++ { ++ printk("!!!!!!!!!!SDC gpio_request failed!!!!!!!!!\n"); ++ } ++ ++ gpio_direction_output(TEST_GPIO, 1); ++ __gpio_set_value(TEST_GPIO, 0); ++#endif ++ return 0; ++ ++err_init_slot: ++ /* De-init any initialized slots */ ++ while (i > 0) { ++ if (host->slot[i]) ++ fh_mci_cleanup_slot(host->slot[i], i); ++ i--; ++ } ++ free_irq(irq, host); ++ ++err_dmaunmap: ++ if (host->use_dma && host->dma_ops->exit) ++ host->dma_ops->exit(host); ++ dma_free_coherent(&host->pdev->dev, PAGE_SIZE, ++ host->sg_cpu, host->sg_dma); ++ //iounmap(host->regs); ++ ++ if (host->vmmc) { ++ regulator_disable(host->vmmc); ++ regulator_put(host->vmmc); ++ } ++ ++ ++err_freehost: ++ kfree(host); ++ return ret; ++} ++ ++static int __exit fh_mci_remove(struct platform_device *pdev) ++{ ++ struct fh_mci *host = platform_get_drvdata(pdev); ++ int i; ++ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ for (i = 0; i < host->num_slots; i++) { ++ dev_dbg(&pdev->dev, "remove slot %d\n", i); ++ if (host->slot[i]) ++ fh_mci_cleanup_slot(host->slot[i], i); ++ } ++ ++ /* disable clock to CIU */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ free_irq(platform_get_irq(pdev, 0), host); ++ dma_free_coherent(&pdev->dev, SDC_DESC_SIZE, host->sg_cpu, host->sg_dma); ++ ++ if (host->use_dma && host->dma_ops->exit) ++ host->dma_ops->exit(host); ++ ++ if (host->vmmc) { ++ regulator_disable(host->vmmc); ++ regulator_put(host->vmmc); ++ } ++ ++ //iounmap(host->regs); ++#ifdef SDC_CRC_TEST ++ gpio_free(TEST_GPIO); ++#endif ++ ++ kfree(host); ++ return 0; ++} ++ ++#if CONFIG_PM ++/* ++ * TODO: we should probably disable the clock to the card in the suspend path. ++ */ ++static int fh_mci_suspend(struct platform_device *pdev, pm_message_t mesg) ++{ ++ int i, ret; ++ struct fh_mci *host = platform_get_drvdata(pdev); ++ ++ for (i = 0; i < host->num_slots; i++) { ++ struct fh_mci_slot *slot = host->slot[i]; ++ if (!slot) ++ continue; ++ ret = mmc_suspend_host(slot->mmc); ++ if (ret < 0) { ++ while (--i >= 0) { ++ slot = host->slot[i]; ++ if (slot) ++ mmc_resume_host(host->slot[i]->mmc); ++ } ++ return ret; ++ } ++ } ++ ++ if (host->vmmc) ++ regulator_disable(host->vmmc); ++ ++ return 0; ++} ++ ++static int fh_mci_resume(struct platform_device *pdev) ++{ ++ int i, ret; ++ struct fh_mci *host = platform_get_drvdata(pdev); ++ ++ if (host->vmmc) ++ regulator_enable(host->vmmc); ++ ++ if (host->dma_ops->init) ++ host->dma_ops->init(host); ++ ++ if (!mci_wait_reset(&pdev->dev, host)) { ++ ret = -ENODEV; ++ return ret; ++ } ++ ++ /* Restore the old value at FIFOTH register */ ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |SDMMC_INT_RTO | SDMMC_INT_DTO | ++ SDMMC_INT_TXDR | SDMMC_INT_RXDR | ++ FH_MCI_ERROR_FLAGS | SDMMC_INT_CD); ++ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); ++ ++ for (i = 0; i < host->num_slots; i++) { ++ struct fh_mci_slot *slot = host->slot[i]; ++ if (!slot) ++ continue; ++ ret = mmc_resume_host(host->slot[i]->mmc); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++#else ++#define fh_mci_suspend NULL ++#define fh_mci_resume NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver fh_mci_driver = { ++ .remove = __exit_p(fh_mci_remove), ++ .suspend = fh_mci_suspend, ++ .resume = fh_mci_resume, ++ .driver = { ++ .name = "fh_mmc", ++ }, ++}; ++ ++static int __init fh_mci_init(void) ++{ ++ return platform_driver_probe(&fh_mci_driver, fh_mci_probe); ++} ++ ++static void __exit fh_mci_exit(void) ++{ ++ platform_driver_unregister(&fh_mci_driver); ++} ++ ++module_init(fh_mci_init); ++module_exit(fh_mci_exit); ++ ++MODULE_DESCRIPTION("FH Multimedia Card Interface driver"); ++MODULE_AUTHOR("NXP Semiconductor VietNam"); ++MODULE_AUTHOR("Imagination Technologies Ltd"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/mmc/host/fh_mmc.h b/drivers/mmc/host/fh_mmc.h +new file mode 100644 +index 00000000..ddb9a63d +--- /dev/null ++++ b/drivers/mmc/host/fh_mmc.h +@@ -0,0 +1,233 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface driver ++ * (Based on NXP driver for lpc 31xx) ++ * ++ * Copyright (C) 2009 NXP Semiconductors ++ * Copyright (C) 2009, 2010 Imagination Technologies Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_MMC_FH_MMC_H_ ++#define _LINUX_MMC_FH_MMC_H_ ++ ++#include <linux/scatterlist.h> ++#include <linux/compiler.h> ++#include <linux/types.h> ++#include <linux/io.h> ++#include <linux/mmc/host.h> ++ ++#define MAX_MCI_SLOTS 2 ++ ++enum fh_mci_state { ++ STATE_IDLE = 0, ++ STATE_SENDING_CMD, ++ STATE_SENDING_DATA, ++ STATE_DATA_BUSY, ++ STATE_SENDING_STOP, ++ STATE_DATA_ERROR, ++}; ++ ++enum { ++ EVENT_CMD_COMPLETE = 0, ++ EVENT_XFER_COMPLETE, ++ EVENT_DATA_COMPLETE, ++ EVENT_DATA_ERROR, ++ EVENT_XFER_ERROR ++}; ++ ++struct mmc_data; ++ ++/** ++ * struct fh_mci - MMC controller state shared between all slots ++ * @lock: Spinlock protecting the queue and associated data. ++ * @regs: Pointer to MMIO registers. ++ * @sg: Scatterlist entry currently being processed by PIO code, if any. ++ * @pio_offset: Offset into the current scatterlist entry. ++ * @cur_slot: The slot which is currently using the controller. ++ * @mrq: The request currently being processed on @cur_slot, ++ * or NULL if the controller is idle. ++ * @cmd: The command currently being sent to the card, or NULL. ++ * @data: The data currently being transferred, or NULL if no data ++ * transfer is in progress. ++ * @use_dma: Whether DMA channel is initialized or not. ++ * @sg_dma: Bus address of DMA buffer. ++ * @sg_cpu: Virtual address of DMA buffer. ++ * @dma_ops: Pointer to platform-specific DMA callbacks. ++ * @cmd_status: Snapshot of SR taken upon completion of the current ++ * command. Only valid when EVENT_CMD_COMPLETE is pending. ++ * @data_status: Snapshot of SR taken upon completion of the current ++ * data transfer. Only valid when EVENT_DATA_COMPLETE or ++ * EVENT_DATA_ERROR is pending. ++ * @stop_cmdr: Value to be loaded into CMDR when the stop command is ++ * to be sent. ++ * @dir_status: Direction of current transfer. ++ * @tasklet: Tasklet running the request state machine. ++ * @card_tasklet: Tasklet handling card detect. ++ * @pending_events: Bitmask of events flagged by the interrupt handler ++ * to be processed by the tasklet. ++ * @completed_events: Bitmask of events which the state machine has ++ * processed. ++ * @state: Tasklet state. ++ * @queue: List of slots waiting for access to the controller. ++ * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus ++ * rate and timeout calculations. ++ * @current_speed: Configured rate of the controller. ++ * @num_slots: Number of slots available. ++ * @pdev: Platform device associated with the MMC controller. ++ * @pdata: Platform data associated with the MMC controller. ++ * @slot: Slots sharing this MMC controller. ++ * @data_shift: log2 of FIFO item size. ++ * @push_data: Pointer to FIFO push function. ++ * @pull_data: Pointer to FIFO pull function. ++ * @quirks: Set of quirks that apply to specific versions of the IP. ++ * ++ * Locking ++ * ======= ++ * ++ * @lock is a softirq-safe spinlock protecting @queue as well as ++ * @cur_slot, @mrq and @state. These must always be updated ++ * at the same time while holding @lock. ++ * ++ * The @mrq field of struct fh_mci_slot is also protected by @lock, ++ * and must always be written at the same time as the slot is added to ++ * @queue. ++ * ++ * @pending_events and @completed_events are accessed using atomic bit ++ * operations, so they don't need any locking. ++ * ++ * None of the fields touched by the interrupt handler need any ++ * locking. However, ordering is important: Before EVENT_DATA_ERROR or ++ * EVENT_DATA_COMPLETE is set in @pending_events, all data-related ++ * interrupts must be disabled and @data_status updated with a ++ * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the ++ * CMDRDY interrupt must be disabled and @cmd_status updated with a ++ * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the ++ * bytes_xfered field of @data must be written. This is ensured by ++ * using barriers. ++ */ ++struct fh_mci { ++ spinlock_t lock; ++ void __iomem *regs; ++ ++ struct scatterlist *sg; ++ unsigned int pio_offset; ++ ++ struct fh_mci_slot *cur_slot; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ ++ /* DMA interface members*/ ++ int use_dma; ++ int using_dma; ++ unsigned int prev_blksz; ++ ++ dma_addr_t sg_dma; ++ void *sg_cpu; ++ struct fh_mci_dma_ops *dma_ops; ++#ifdef CONFIG_MMC_FH_IDMAC ++ unsigned int ring_size; ++#else ++ struct fh_mci_dma_data *dma_data; ++#endif ++ u32 cmd_status; ++ u32 data_status; ++ u32 stop_cmdr; ++ u32 dir_status; ++ struct tasklet_struct tasklet; ++ struct tasklet_struct card_tasklet; ++ unsigned long pending_events; ++ unsigned long completed_events; ++ enum fh_mci_state state; ++ struct list_head queue; ++ ++ u32 bus_hz; ++ u32 current_speed; ++ u32 num_slots; ++ u32 fifoth_val; ++ struct platform_device *pdev; ++ struct fh_mci_board *pdata; ++ struct fh_mci_slot *slot[MAX_MCI_SLOTS]; ++ ++ /* FIFO push and pull */ ++ int data_shift; ++ void (*push_data)(struct fh_mci *host, void *buf, int cnt); ++ void (*pull_data)(struct fh_mci *host, void *buf, int cnt); ++ ++ /* Workaround flags */ ++ u32 quirks; ++ ++ struct regulator *vmmc; /* Power regulator */ ++ ++ int dma_data_mapped; ++ int data_error_flag; ++}; ++ ++/* DMA ops for Internal/External DMAC interface */ ++struct fh_mci_dma_ops { ++ /* DMA Ops */ ++ int (*init)(struct fh_mci *host); ++ void (*start)(struct fh_mci *host, unsigned int sg_len); ++ void (*complete)(struct fh_mci *host); ++ void (*stop)(struct fh_mci *host); ++ void (*cleanup)(struct fh_mci *host); ++ void (*exit)(struct fh_mci *host); ++}; ++ ++/* IP Quirks/flags. */ ++/* DTO fix for command transmission with IDMAC configured */ ++#define FH_MCI_QUIRK_IDMAC_DTO BIT(0) ++/* delay needed between retries on some 2.11a implementations */ ++#define FH_MCI_QUIRK_RETRY_DELAY BIT(1) ++/* High Speed Capable - Supports HS cards (up to 50MHz) */ ++#define FH_MCI_QUIRK_HIGHSPEED BIT(2) ++/* Unreliable card detection */ ++#define FH_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) ++ ++ ++struct dma_pdata; ++ ++struct block_settings { ++ unsigned short max_segs; /* see blk_queue_max_segments */ ++ unsigned int max_blk_size; /* maximum size of one mmc block */ ++ unsigned int max_blk_count; /* maximum number of blocks in one req*/ ++ unsigned int max_req_size; /* maximum number of bytes in one req*/ ++ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ ++}; ++ ++/* Board platform data */ ++struct fh_mci_board { ++ u32 num_slots; ++ ++ u32 quirks; /* Workaround / Quirk flags */ ++ unsigned int bus_hz; /* Bus speed */ ++ ++ unsigned int caps; /* Capabilities */ ++ ++ /* delay in mS before detecting cards after interrupt */ ++ u32 detect_delay_ms; ++ ++ int (*init)(u32 slot_id,void* irq_handler_t , void *); ++ int (*get_ro)(u32 slot_id); ++ int (*get_cd)(u32 slot_id); ++ int (*get_ocr)(u32 slot_id); ++ int (*get_bus_wd)(u32 slot_id); ++ /* ++ * Enable power to selected slot and set voltage to desired level. ++ * Voltage levels are specified using MMC_VDD_xxx defines defined ++ * in linux/mmc/host.h file. ++ */ ++ void (*setpower)(u32 slot_id, u32 volt); ++ void (*exit)(u32 slot_id); ++ void (*select_slot)(u32 slot_id); ++ ++ struct fh_mci_dma_ops *dma_ops; ++ struct dma_pdata *data; ++ struct block_settings *blk_settings; ++}; ++ ++#endif /* _LINUX_MMC_FH_MMC_H_ */ +diff --git a/drivers/mmc/host/fh_mmc_reg.h b/drivers/mmc/host/fh_mmc_reg.h +new file mode 100644 +index 00000000..8153d4d6 +--- /dev/null ++++ b/drivers/mmc/host/fh_mmc_reg.h +@@ -0,0 +1,174 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface driver ++ * (Based on NXP driver for lpc 31xx) ++ * ++ * Copyright (C) 2009 NXP Semiconductors ++ * Copyright (C) 2009, 2010 Imagination Technologies Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef _DW_MMC_H_ ++#define _DW_MMC_H_ ++ ++#define SDMMC_CTRL 0x000 ++#define SDMMC_PWREN 0x004 ++#define SDMMC_CLKDIV 0x008 ++#define SDMMC_CLKSRC 0x00c ++#define SDMMC_CLKENA 0x010 ++#define SDMMC_TMOUT 0x014 ++#define SDMMC_CTYPE 0x018 ++#define SDMMC_BLKSIZ 0x01c ++#define SDMMC_BYTCNT 0x020 ++#define SDMMC_INTMASK 0x024 ++#define SDMMC_CMDARG 0x028 ++#define SDMMC_CMD 0x02c ++#define SDMMC_RESP0 0x030 ++#define SDMMC_RESP1 0x034 ++#define SDMMC_RESP2 0x038 ++#define SDMMC_RESP3 0x03c ++#define SDMMC_MINTSTS 0x040 ++#define SDMMC_RINTSTS 0x044 ++#define SDMMC_STATUS 0x048 ++#define SDMMC_FIFOTH 0x04c ++#define SDMMC_CDETECT 0x050 ++#define SDMMC_WRTPRT 0x054 ++#define SDMMC_GPIO 0x058 ++#define SDMMC_TCBCNT 0x05c ++#define SDMMC_TBBCNT 0x060 ++#define SDMMC_DEBNCE 0x064 ++#define SDMMC_USRID 0x068 ++#define SDMMC_VERID 0x06c ++#define SDMMC_HCON 0x070 ++#define SDMMC_UHS_REG 0x074 ++#define SDMMC_RST_n 0x78 ++#define SDMMC_BMOD 0x080 ++#define SDMMC_PLDMND 0x084 ++#define SDMMC_DBADDR 0x088 ++#define SDMMC_IDSTS 0x08c ++#define SDMMC_IDINTEN 0x090 ++#define SDMMC_DSCADDR 0x094 ++#define SDMMC_BUFADDR 0x098 ++#define SDMMC_DATA 0x200 ++ ++/* shift bit field */ ++#define _SBF(f, v) ((v) << (f)) ++ ++/* Control register defines */ ++#define SDMMC_CTRL_USE_IDMAC BIT(25) ++#define SDMMC_CTRL_CEATA_INT_EN BIT(11) ++#define SDMMC_CTRL_SEND_AS_CCSD BIT(10) ++#define SDMMC_CTRL_SEND_CCSD BIT(9) ++#define SDMMC_CTRL_ABRT_READ_DATA BIT(8) ++#define SDMMC_CTRL_SEND_IRQ_RESP BIT(7) ++#define SDMMC_CTRL_READ_WAIT BIT(6) ++#define SDMMC_CTRL_DMA_ENABLE BIT(5) ++#define SDMMC_CTRL_INT_ENABLE BIT(4) ++#define SDMMC_CTRL_DMA_RESET BIT(2) ++#define SDMMC_CTRL_FIFO_RESET BIT(1) ++#define SDMMC_CTRL_RESET BIT(0) ++/* Clock Enable register defines */ ++#define SDMMC_CLKEN_LOW_PWR BIT(16) ++#define SDMMC_CLKEN_ENABLE BIT(0) ++/* time-out register defines */ ++#define SDMMC_TMOUT_DATA(n) _SBF(8, (n)) ++#define SDMMC_TMOUT_DATA_MSK 0xFFFFFF00 ++#define SDMMC_TMOUT_RESP(n) ((n) & 0xFF) ++#define SDMMC_TMOUT_RESP_MSK 0xFF ++/* card-type register defines */ ++#define SDMMC_CTYPE_8BIT BIT(16) ++#define SDMMC_CTYPE_4BIT BIT(0) ++#define SDMMC_CTYPE_1BIT 0 ++/* Interrupt status & mask register defines */ ++//#define SDMMC_INT_SDIO BIT(16) ++#define SDMMC_INT_SDIO(n) BIT(16 + (n)) ++#define SDMMC_INT_EBE BIT(15) ++#define SDMMC_INT_ACD BIT(14) ++#define SDMMC_INT_SBE BIT(13) ++#define SDMMC_INT_HLE BIT(12) ++#define SDMMC_INT_FRUN BIT(11) ++#define SDMMC_INT_HTO BIT(10) ++#define SDMMC_INT_DTO BIT(9) ++#define SDMMC_INT_RTO BIT(8) ++#define SDMMC_INT_DCRC BIT(7) ++#define SDMMC_INT_RCRC BIT(6) ++#define SDMMC_INT_RXDR BIT(5) ++#define SDMMC_INT_TXDR BIT(4) ++#define SDMMC_INT_DATA_OVER BIT(3) ++#define SDMMC_INT_CMD_DONE BIT(2) ++#define SDMMC_INT_RESP_ERR BIT(1) ++#define SDMMC_INT_CD BIT(0) ++#define SDMMC_INT_ERROR 0xbfc2 ++/* Command register defines */ ++#define SDMMC_CMD_START BIT(31) ++#define SDMMC_CMD_USE_HOLD_REG BIT(29) ++#define SDMMC_CMD_CCS_EXP BIT(23) ++#define SDMMC_CMD_CEATA_RD BIT(22) ++#define SDMMC_CMD_UPD_CLK BIT(21) ++#define SDMMC_CMD_INIT BIT(15) ++#define SDMMC_CMD_STOP BIT(14) ++#define SDMMC_CMD_PRV_DAT_WAIT BIT(13) ++#define SDMMC_CMD_SEND_STOP BIT(12) ++#define SDMMC_CMD_STRM_MODE BIT(11) ++#define SDMMC_CMD_DAT_WR BIT(10) ++#define SDMMC_CMD_DAT_EXP BIT(9) ++#define SDMMC_CMD_RESP_CRC BIT(8) ++#define SDMMC_CMD_RESP_LONG BIT(7) ++#define SDMMC_CMD_RESP_EXP BIT(6) ++#define SDMMC_CMD_INDX(n) ((n) & 0x1F) ++/* Status register defines */ ++#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF) ++#define SDMMC_FIFO_SZ 32 ++/* Internal DMAC interrupt defines */ ++#define SDMMC_IDMAC_INT_AI BIT(9) ++#define SDMMC_IDMAC_INT_NI BIT(8) ++#define SDMMC_IDMAC_INT_CES BIT(5) ++#define SDMMC_IDMAC_INT_DU BIT(4) ++#define SDMMC_IDMAC_INT_FBE BIT(2) ++#define SDMMC_IDMAC_INT_RI BIT(1) ++#define SDMMC_IDMAC_INT_TI BIT(0) ++/* Internal DMAC bus mode bits */ ++#define SDMMC_IDMAC_ENABLE BIT(7) ++#define SDMMC_IDMAC_FB BIT(1) ++#define SDMMC_IDMAC_SWRESET BIT(0) ++#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ ++ ((r) & 0xFFF) << 16 | \ ++ ((t) & 0xFFF)) ++ ++/* Register access macros */ ++#define mci_readl(dev, reg) \ ++ __raw_readl(dev->regs + SDMMC_##reg) ++#define mci_writel(dev, reg, value) \ ++ __raw_writel((value), dev->regs + SDMMC_##reg) ++ ++/* 16-bit FIFO access macros */ ++#define mci_readw(dev, reg) \ ++ __raw_readw(dev->regs + SDMMC_##reg) ++#define mci_writew(dev, reg, value) \ ++ __raw_writew((value), dev->regs + SDMMC_##reg) ++ ++/* 64-bit FIFO access macros */ ++#ifdef readq ++#define mci_readq(dev, reg) \ ++ __raw_readq(dev->regs + SDMMC_##reg) ++#define mci_writeq(dev, reg, value) \ ++ __raw_writeq((value), dev->regs + SDMMC_##reg) ++#else ++/* ++ * Dummy readq implementation for architectures that don't define it. ++ * ++ * We would assume that none of these architectures would configure ++ * the IP block with a 64bit FIFO width, so this code will never be ++ * executed on those machines. Defining these macros here keeps the ++ * rest of the code free from ifdefs. ++ */ ++#define mci_readq(dev, reg) \ ++ (*(volatile u64 __force *)(dev->regs + SDMMC_##reg)) ++#define mci_writeq(dev, reg, value) \ ++ (*(volatile u64 __force *)(dev->regs + SDMMC_##reg) = value) ++#endif ++ ++#endif /* _DW_MMC_H_ */ +diff --git a/drivers/mmc/host/fhmci/Makefile b/drivers/mmc/host/fhmci/Makefile +new file mode 100644 +index 00000000..bc3ffd2c +--- /dev/null ++++ b/drivers/mmc/host/fhmci/Makefile +@@ -0,0 +1,3 @@ ++ ++obj-$(CONFIG_MMC) += fh_mci.o ++fh_mci-y := fhmci.o +diff --git a/drivers/mmc/host/fhmci/fhmci.c b/drivers/mmc/host/fhmci/fhmci.c +new file mode 100644 +index 00000000..3f0f1ef6 +--- /dev/null ++++ b/drivers/mmc/host/fhmci/fhmci.c +@@ -0,0 +1,1541 @@ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/mm.h> ++#include <linux/interrupt.h> ++#include <linux/dma-mapping.h> ++#include <linux/scatterlist.h> ++#include <linux/regulator/consumer.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/mmc.h> ++#include <linux/mmc/sd.h> ++#include <linux/mmc/card.h> ++#include <linux/slab.h> ++ ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/gpio.h> ++ ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/kthread.h> ++#include <linux/workqueue.h> ++#include <linux/freezer.h> ++#include <asm/dma.h> ++#include <linux/io.h> ++#include <asm/irq.h> ++#include <asm/sizes.h> ++#include <linux/uaccess.h> ++#include <mach/hardware.h> ++#include <linux/mmc/card.h> ++#include <linux/clk.h> ++#include "fhmci_reg.h" ++#include <mach/fhmci.h> ++ ++#include <mach/pmu.h> ++ ++ ++#ifndef FALSE ++#define FALSE (0) ++#endif ++ ++#ifndef TRUE ++#define TRUE (!(FALSE)) ++#endif ++ ++#define SD_POWER_ON 1 ++#define SD_POWER_OFF 0 ++#define DRIVER_NAME "fh_mci" ++ ++static unsigned int retry_count = MAX_RETRY_COUNT; ++static unsigned int request_timeout = FH_MCI_REQUEST_TIMEOUT; ++int trace_level = FHMCI_TRACE_LEVEL; ++struct mmc_host *mmc_sd1; ++struct mmc_host *mmc_sd0; ++ ++#ifdef MODULE ++ ++MODULE_PARM_DESC(detect_timer, "card detect time (default:500ms))"); ++ ++module_param(retry_count, uint, 0600); ++MODULE_PARM_DESC(retry_count, "retry count times (default:100))"); ++ ++module_param(request_timeout, uint, 0600); ++MODULE_PARM_DESC(request_timeout, "Request timeout time (default:3s))"); ++ ++module_param(trace_level, int, 0600); ++MODULE_PARM_DESC(trace_level, "FHMCI_TRACE_LEVEL"); ++ ++#endif ++ ++/* reset MMC host controler */ ++static void fh_mci_sys_reset(struct fhmci_host *host) ++{ ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ fhmci_trace(2, "reset"); ++ ++ local_irq_save(flags); ++ ++ reg_value = fhmci_readl(host->base + MCI_BMOD); ++ reg_value |= BMOD_SWR; ++ fhmci_writel(reg_value, host->base + MCI_BMOD); ++ udelay(50); ++ ++ reg_value = fhmci_readl(host->base + MCI_BMOD); ++ reg_value |= BURST_INCR; ++ fhmci_writel(reg_value, host->base + MCI_BMOD); ++ ++ reg_value = fhmci_readl(host->base + MCI_CTRL); ++ reg_value |= CTRL_RESET | FIFO_RESET | DMA_RESET; ++ fhmci_writel(reg_value, host->base + MCI_CTRL); ++ ++ local_irq_restore(flags); ++} ++ ++static void fh_mci_sys_undo_reset(struct fhmci_host *host) ++{ ++ unsigned long flags; ++ ++ fhmci_trace(2, "undo reset"); ++ ++ local_irq_save(flags); ++ local_irq_restore(flags); ++} ++ ++static void fh_mci_ctrl_power(struct fhmci_host *host, unsigned int flag) ++{ ++ fhmci_trace(2, "begin"); ++ ++} ++ ++/********************************************** ++ *1: card off ++ *0: card on ++ ***********************************************/ ++static unsigned int fh_mci_sys_card_detect(struct fhmci_host *host) ++{ ++ unsigned int card_status = readl(host->base + MCI_CDETECT); ++ return card_status & FHMCI_CARD0; ++} ++ ++/********************************************** ++ *1: card readonly ++ *0: card read/write ++ ***********************************************/ ++static unsigned int fh_mci_ctrl_card_readonly(struct fhmci_host *host) ++{ ++ unsigned int card_value = fhmci_readl(host->base + MCI_WRTPRT); ++ return card_value & FHMCI_CARD0; ++} ++ ++static int fh_mci_wait_cmd(struct fhmci_host *host) ++{ ++ int wait_retry_count = 0; ++ unsigned int reg_data = 0; ++ unsigned long flags; ++ ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ ++ while (1) { ++ /* ++ * Check if CMD::start_cmd bit is clear. ++ * start_cmd = 0 means MMC Host controller has loaded registers ++ * and next command can be loaded in. ++ */ ++ reg_data = readl(host->base + MCI_CMD); ++ if ((reg_data & START_CMD) == 0) ++ return 0; ++ ++ /* Check if Raw_Intr_Status::HLE bit is set. */ ++ spin_lock_irqsave(&host->lock, flags); ++ reg_data = readl(host->base + MCI_RINTSTS); ++ if (reg_data & HLE_INT_STATUS) { ++ reg_data &= (~SDIO_INT_STATUS); ++ fhmci_writel(reg_data, host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ fhmci_trace(3, "Other CMD is running," \ ++ "please operate cmd again!"); ++ return 1; ++ } ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ udelay(100); ++ ++ /* Check if number of retries for this are over. */ ++ wait_retry_count++; ++ if (wait_retry_count >= retry_count) { ++ fhmci_trace(3, "send cmd is timeout!"); ++ return -1; ++ } ++ } ++} ++ ++static void fh_mci_control_cclk(struct fhmci_host *host, unsigned int flag) ++{ ++ unsigned int reg; ++ union cmd_arg_s cmd_reg; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ ++ reg = fhmci_readl(host->base + MCI_CLKENA); ++ if (flag == ENABLE) ++ reg |= CCLK_ENABLE; ++ else ++ reg &= 0xffff0000; ++ fhmci_writel(reg, host->base + MCI_CLKENA); ++ ++ cmd_reg.cmd_arg = fhmci_readl(host->base + MCI_CMD); ++ cmd_reg.bits.start_cmd = 1; ++ cmd_reg.bits.update_clk_reg_only = 1; ++ fhmci_writel(cmd_reg.cmd_arg, host->base + MCI_CMD); ++ if (fh_mci_wait_cmd(host) != 0) ++ fhmci_trace(3, "disable or enable clk is timeout!"); ++} ++ ++static void fh_mci_set_cclk(struct fhmci_host *host, unsigned int cclk) ++{ ++ unsigned int reg_value; ++ union cmd_arg_s clk_cmd; ++ struct fh_mci_board *pdata; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(cclk); ++ ++ pdata = host->pdata; ++ ++ /* ++ * set card clk divider value, ++ * clk_divider = Fmmcclk/(Fmmc_cclk * 2) ++ */ ++ ++ if (0 == host->id) { ++ if (pdata->bus_hz <= cclk) ++ reg_value = 0; ++ else { ++ reg_value = pdata->bus_hz / (cclk * 2); ++ if (pdata->bus_hz % (cclk * 2)) ++ reg_value++; ++ } ++ } else if (1 == host->id) { ++ if (pdata->bus_hz <= cclk) ++ reg_value = 0; ++ else { ++ reg_value = pdata->bus_hz / (cclk * 2); ++ if (pdata->bus_hz % (cclk * 2)) ++ reg_value++; ++ } ++ } else { ++ fhmci_error("fhmci host id error!"); ++ return; ++ } ++ ++ fhmci_writel(reg_value, host->base + MCI_CLKDIV); ++ ++ ++ clk_cmd.cmd_arg = fhmci_readl(host->base + MCI_CMD); ++ clk_cmd.bits.start_cmd = 1; ++ clk_cmd.bits.update_clk_reg_only = 1; ++ fhmci_writel(clk_cmd.cmd_arg, host->base + MCI_CMD); ++ ++ if (fh_mci_wait_cmd(host) != 0) ++ fhmci_trace(3, "set card clk divider is failed!"); ++} ++ ++static void fh_mci_init_card(struct fhmci_host *host) ++{ ++ unsigned int tmp_reg, tmp; ++ unsigned long flags; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ tmp = fhmci_readl(host->base + MCI_PWREN); ++ fh_mci_sys_reset(host); ++ fh_mci_ctrl_power(host, POWER_OFF); ++ udelay(500); ++ /* card power on */ ++ fh_mci_ctrl_power(host, POWER_ON); ++ udelay(200); ++ ++ fh_mci_sys_undo_reset(host); ++ ++ /* set phase shift */ ++ /* set card read threshold */ ++ ++ /* clear MMC host intr */ ++ fhmci_writel(ALL_INT_CLR, host->base + MCI_RINTSTS); ++ ++ spin_lock_irqsave(&host->lock, flags); ++ host->pending_events = 0; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ /* MASK MMC host intr */ ++ tmp_reg = fhmci_readl(host->base + MCI_INTMASK); ++ tmp_reg &= ~ALL_INT_MASK; ++ tmp_reg |= DATA_INT_MASK; ++ fhmci_writel(tmp_reg, host->base + MCI_INTMASK); ++ ++ /* enable inner DMA mode and close intr of MMC host controler */ ++ tmp_reg = fhmci_readl(host->base + MCI_CTRL); ++ tmp_reg &= ~INTR_EN; ++ tmp_reg |= USE_INTERNAL_DMA | INTR_EN; ++ fhmci_writel(tmp_reg, host->base + MCI_CTRL); ++ ++ /* set timeout param */ ++ fhmci_writel(DATA_TIMEOUT | RESPONSE_TIMEOUT, host->base + MCI_TIMEOUT); ++ ++ /* set FIFO param */ ++ if (host->pdata->fifo_depth > 15) ++ tmp = 0x5; ++ else ++ tmp = 0x2; ++ ++ tmp_reg = ((tmp << 28) | ((host->pdata->fifo_depth / 2) << 16) ++ | (((host->pdata->fifo_depth / 2) + 1) << 0)); ++ fhmci_writel(tmp_reg, host->base + MCI_FIFOTH); ++} ++ ++int read_mci_ctrl_states(int id_mmc_sd) ++{ ++ if ((id_mmc_sd == ID_SD0) && (mmc_sd0 != NULL)) ++ return mmc_sd0->rescan_disable; ++ else if ((id_mmc_sd == ID_SD1) && (mmc_sd1 != NULL)) ++ return mmc_sd1->rescan_disable; ++ ++ return -1; ++} ++ ++int storage_dev_set_mmc_rescan(struct mmc_ctrl *m_ctrl) ++{ ++ unsigned int tmp; ++ struct mmc_host *mmc_sd = NULL; ++ tmp = m_ctrl->mmc_ctrl_state; ++ ++ if (m_ctrl->slot_idx == 1) { ++ if (mmc_sd1 != NULL) ++ mmc_sd = mmc_sd1; ++ } else if (m_ctrl->slot_idx == 0) { ++ if (mmc_sd0 != NULL) ++ mmc_sd = mmc_sd0; ++ } ++ if ((tmp != TRUE) && (tmp != FALSE)) ++ return -1; ++ ++ if (tmp == TRUE) { ++ if (mmc_sd != NULL) { ++ mmc_sd->rescan_disable = TRUE; ++ mmc_detect_change(mmc_sd, 0); ++ } ++ } else { ++ if (mmc_sd != NULL) { ++ mmc_sd->rescan_disable = FALSE; ++ mmc_detect_change(mmc_sd, 0); ++ } ++ } ++ return 0; ++} ++ ++static void fh_mci_idma_start(struct fhmci_host *host) ++{ ++ unsigned int tmp; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_writel(host->dma_paddr, host->base + MCI_DBADDR); ++ tmp = fhmci_readl(host->base + MCI_BMOD); ++ tmp |= BMOD_DMA_EN; ++ tmp |= BURST_INCR; ++ fhmci_writel(tmp, host->base + MCI_BMOD); ++} ++ ++static void fh_mci_idma_stop(struct fhmci_host *host) ++{ ++ unsigned int tmp_reg; ++ ++ fhmci_trace(2, "begin"); ++ tmp_reg = fhmci_readl(host->base + MCI_BMOD); ++ tmp_reg &= ~BMOD_DMA_EN; ++ tmp_reg |= BMOD_SWR; ++ fhmci_writel(tmp_reg, host->base + MCI_BMOD); ++} ++ ++static int fh_mci_setup_data(struct fhmci_host *host, struct mmc_data *data) ++{ ++ unsigned int sg_phyaddr, sg_length; ++ unsigned int i, ret = 0; ++ unsigned int data_size; ++ unsigned int max_des, des_cnt; ++ struct fhmci_des *des; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(data); ++ ++ host->data = data; ++ ++ if (data->flags & MMC_DATA_READ) ++ host->dma_dir = DMA_FROM_DEVICE; ++ else ++ host->dma_dir = DMA_TO_DEVICE; ++ ++ host->dma_sg = data->sg; ++ host->dma_sg_num = dma_map_sg(mmc_dev(host->mmc), ++ data->sg, data->sg_len, host->dma_dir); ++ fhmci_assert(host->dma_sg_num); ++ fhmci_trace(2, "host->dma_sg_num is %d\n", host->dma_sg_num); ++ data_size = data->blksz * data->blocks; ++ ++ if (data_size > (DMA_BUFFER * MAX_DMA_DES)) { ++ fhmci_error("mci request data_size is too big!\n"); ++ ret = -1; ++ goto out; ++ } ++ ++ fhmci_trace(2, "host->dma_paddr is 0x%08X,host->dma_vaddr is 0x%08X\n", ++ (unsigned int)host->dma_paddr, ++ (unsigned int)host->dma_vaddr); ++ ++ max_des = (PAGE_SIZE/sizeof(struct fhmci_des)); ++ des = (struct fhmci_des *)host->dma_vaddr; ++ des_cnt = 0; ++ ++ for (i = 0; i < host->dma_sg_num; i++) { ++ sg_length = sg_dma_len(&data->sg[i]); ++ sg_phyaddr = sg_dma_address(&data->sg[i]); ++ fhmci_trace(2, "sg[%d] sg_length is 0x%08X, " \ ++ "sg_phyaddr is 0x%08X\n", \ ++ i, (unsigned int)sg_length, \ ++ (unsigned int)sg_phyaddr); ++ while (sg_length) { ++ des[des_cnt].idmac_des_ctrl = DMA_DES_OWN ++ | DMA_DES_NEXT_DES; ++ des[des_cnt].idmac_des_buf_addr = sg_phyaddr; ++ /* idmac_des_next_addr is paddr for dma */ ++ des[des_cnt].idmac_des_next_addr = host->dma_paddr ++ + (des_cnt + 1) * sizeof(struct fhmci_des); ++ ++ if (sg_length >= 0x1F00) { ++ des[des_cnt].idmac_des_buf_size = 0x1F00; ++ sg_length -= 0x1F00; ++ sg_phyaddr += 0x1F00; ++ } else { ++ /* FIXME:data alignment */ ++ des[des_cnt].idmac_des_buf_size = sg_length; ++ sg_length = 0; ++ } ++ ++ fhmci_trace(2, "des[%d] vaddr is 0x%08X", i, ++ (unsigned int)&des[i]); ++ fhmci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_ctrl); ++ fhmci_trace(2, "des[%d].idmac_des_buf_size is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_buf_size); ++ fhmci_trace(2, "des[%d].idmac_des_buf_addr 0x%08X", ++ i, (unsigned int)des[i].idmac_des_buf_addr); ++ fhmci_trace(2, "des[%d].idmac_des_next_addr is 0x%08X", ++ i, (unsigned int)des[i].idmac_des_next_addr); ++ des_cnt++; ++ } ++ ++ fhmci_assert(des_cnt < max_des); ++ } ++ des[0].idmac_des_ctrl |= DMA_DES_FIRST_DES; ++ des[des_cnt - 1].idmac_des_ctrl |= DMA_DES_LAST_DES; ++ des[des_cnt - 1].idmac_des_next_addr = 0; ++out: ++ return ret; ++} ++ ++static int fh_mci_exec_cmd(struct fhmci_host *host, struct mmc_command *cmd, ++ struct mmc_data *data) ++{ ++ union cmd_arg_s cmd_regs; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(cmd); ++ ++ host->cmd = cmd; ++ ++ fhmci_writel(cmd->arg, host->base + MCI_CMDARG); ++ fhmci_trace(2, "arg_reg 0x%x, val 0x%x\n", MCI_CMDARG, cmd->arg); ++ cmd_regs.cmd_arg = fhmci_readl(host->base + MCI_CMD); ++ if (data) { ++ cmd_regs.bits.data_transfer_expected = 1; ++ if (data->flags & (MMC_DATA_WRITE | MMC_DATA_READ)) ++ cmd_regs.bits.transfer_mode = 0; ++ ++ if (data->flags & MMC_DATA_STREAM) ++ cmd_regs.bits.transfer_mode = 1; ++ ++ if (data->flags & MMC_DATA_WRITE) ++ cmd_regs.bits.read_write = 1; ++ else if (data->flags & MMC_DATA_READ) ++ cmd_regs.bits.read_write = 0; ++ } else { ++ cmd_regs.bits.data_transfer_expected = 0; ++ cmd_regs.bits.transfer_mode = 0; ++ cmd_regs.bits.read_write = 0; ++ } ++ cmd_regs.bits.send_auto_stop = 0; ++#ifdef CONFIG_SEND_AUTO_STOP ++ if ((host->mrq->stop) && (!(host->is_tuning))) ++ cmd_regs.bits.send_auto_stop = 1; ++#endif ++ ++ if (cmd == host->mrq->stop) { ++ cmd_regs.bits.stop_abort_cmd = 1; ++ cmd_regs.bits.wait_prvdata_complete = 0; ++ } else { ++ cmd_regs.bits.stop_abort_cmd = 0; ++ cmd_regs.bits.wait_prvdata_complete = 1; ++ } ++ ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_NONE: ++ cmd_regs.bits.response_expect = 0; ++ cmd_regs.bits.response_length = 0; ++ cmd_regs.bits.check_response_crc = 0; ++ break; ++ case MMC_RSP_R1: ++ case MMC_RSP_R1B: ++ cmd_regs.bits.response_expect = 1; ++ cmd_regs.bits.response_length = 0; ++ cmd_regs.bits.check_response_crc = 1; ++ break; ++ case MMC_RSP_R2: ++ cmd_regs.bits.response_expect = 1; ++ cmd_regs.bits.response_length = 1; ++ cmd_regs.bits.check_response_crc = 1; ++ break; ++ case MMC_RSP_R3: ++ cmd_regs.bits.response_expect = 1; ++ cmd_regs.bits.response_length = 0; ++ cmd_regs.bits.check_response_crc = 0; ++ break; ++ default: ++ fhmci_error("fh_mci: unhandled response type %02x\n", ++ mmc_resp_type(cmd)); ++ return -EINVAL; ++ } ++ ++ fhmci_trace(2, "send cmd of card is cmd->opcode = %d ", cmd->opcode); ++ if (cmd->opcode == MMC_GO_IDLE_STATE) ++ cmd_regs.bits.send_initialization = 1; ++ else ++ cmd_regs.bits.send_initialization = 0; ++ /* CMD 11 check switch voltage */ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) ++ cmd_regs.bits.volt_switch = 1; ++ else ++ cmd_regs.bits.volt_switch = 0; ++ ++ ++ cmd_regs.bits.card_number = 0; ++ cmd_regs.bits.cmd_index = cmd->opcode; ++ cmd_regs.bits.start_cmd = 1; ++ cmd_regs.bits.update_clk_reg_only = 0; ++ fhmci_writel(DATA_INT_MASK, host->base + MCI_RINTSTS); ++ fhmci_writel(cmd_regs.cmd_arg, host->base + MCI_CMD); ++ fhmci_trace(2, "cmd_reg 0x%x, val 0x%x\n", MCI_CMD, cmd_regs.cmd_arg); ++ ++ if (fh_mci_wait_cmd(host) != 0) { ++ fhmci_trace(3, "send card cmd is failed!"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void fh_mci_finish_request(struct fhmci_host *host, ++ struct mmc_request *mrq) ++{ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(mrq); ++ ++ host->mrq = NULL; ++ host->cmd = NULL; ++ host->data = NULL; ++ ++ mmc_request_done(host->mmc, mrq); ++} ++ ++static void fh_mci_cmd_done(struct fhmci_host *host, unsigned int stat) ++{ ++ unsigned int i; ++ struct mmc_command *cmd = host->cmd; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(cmd); ++ ++ ++ for (i = 0; i < 4; i++) { ++ if (mmc_resp_type(cmd) == MMC_RSP_R2) { ++ cmd->resp[i] = fhmci_readl(host->base + ++ MCI_RESP3 - i * 0x4); ++ /* R2 must delay some time here ,when use UHI card, ++ need check why */ ++ udelay(1000); ++ } else ++ cmd->resp[i] = fhmci_readl(host->base + ++ MCI_RESP0 + i * 0x4); ++ } ++ ++ if (stat & RTO_INT_STATUS) { ++ cmd->error = -ETIMEDOUT; ++ fhmci_trace(3, "irq cmd status stat = 0x%x is timeout error!", ++ stat); ++ } else if (stat & (RCRC_INT_STATUS | RE_INT_STATUS)) { ++ cmd->error = -EILSEQ; ++ fhmci_trace(3, "irq cmd status stat = 0x%x is response error!", ++ stat); ++ } ++ host->cmd = NULL; ++} ++ ++ ++static void fh_mci_data_done(struct fhmci_host *host, unsigned int stat) ++{ ++ struct mmc_data *data = host->data; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(data); ++ ++ ++ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); ++ ++ if (stat & (HTO_INT_STATUS | DRTO_INT_STATUS)) { ++ data->error = -ETIMEDOUT; ++ fhmci_trace(3, "irq data status stat = 0x%x is timeout error!", ++ stat); ++ } else if (stat & (EBE_INT_STATUS | SBE_INT_STATUS | FRUN_INT_STATUS ++ | DCRC_INT_STATUS)) { ++ data->error = -EILSEQ; ++ fhmci_trace(3, "irq data status stat = 0x%x is data error!", ++ stat); ++ } ++ ++ if (!data->error) ++ data->bytes_xfered = data->blocks * data->blksz; ++ else ++ data->bytes_xfered = 0; ++ ++ host->data = NULL; ++} ++ ++ ++static int fh_mci_wait_cmd_complete(struct fhmci_host *host) ++{ ++ unsigned int cmd_retry_count = 0; ++ unsigned long cmd_jiffies_timeout; ++ unsigned int cmd_irq_reg = 0; ++ struct mmc_command *cmd = host->cmd; ++ unsigned long flags; ++ unsigned int cmd_done = 0; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(cmd); ++ ++ cmd_jiffies_timeout = jiffies + request_timeout; ++ while (1) { ++ ++ do { ++ spin_lock_irqsave(&host->lock, flags); ++ cmd_irq_reg = readl(host->base + MCI_RINTSTS); ++ ++ if (cmd_irq_reg & CD_INT_STATUS) { ++ fhmci_writel((CD_INT_STATUS | RTO_INT_STATUS ++ | RCRC_INT_STATUS | RE_INT_STATUS), ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ cmd_done = 1; ++ break; ++/* fh_mci_cmd_done(host, cmd_irq_reg); ++ return 0;*/ ++ } else if (cmd_irq_reg & VOLT_SWITCH_INT_STATUS) { ++ fhmci_writel(VOLT_SWITCH_INT_STATUS, \ ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ cmd_done = 1; ++ break; ++/* fh_mci_cmd_done(host, cmd_irq_reg); ++ return 0;*/ ++ } ++ spin_unlock_irqrestore(&host->lock, flags); ++ cmd_retry_count++; ++ } while (cmd_retry_count < retry_count && ++ host->get_cd(host) != CARD_UNPLUGED); ++ ++ cmd_retry_count = 0; ++ ++ if ((host->card_status == CARD_UNPLUGED) ++ || (host->get_cd(host) == CARD_UNPLUGED)) { ++ cmd->error = -ETIMEDOUT; ++ return -1; ++ } ++ if (cmd_done) { ++ fh_mci_cmd_done(host, cmd_irq_reg); ++ return 0; ++ } ++ ++ if (!time_before(jiffies, cmd_jiffies_timeout)) { ++ unsigned int i = 0; ++ for (i = 0; i < 4; i++) { ++ cmd->resp[i] = fhmci_readl(host->base \ ++ + MCI_RESP0 + i * 0x4); ++ printk(KERN_ERR "voltage switch read MCI_RESP"); ++ printk(KERN_ERR "%d : 0x%x\n", i, cmd->resp[i]); ++ } ++ cmd->error = -ETIMEDOUT; ++ fhmci_trace(3, "wait cmd request complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++} ++/* ++ * designware support send stop command automatically when ++ * read or wirte multi blocks ++ */ ++#ifdef CONFIG_SEND_AUTO_STOP ++static int fh_mci_wait_auto_stop_complete(struct fhmci_host *host) ++{ ++ unsigned int cmd_retry_count = 0; ++ unsigned long cmd_jiffies_timeout; ++ unsigned int cmd_irq_reg = 0; ++ unsigned long flags; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ ++ cmd_jiffies_timeout = jiffies + request_timeout; ++ while (1) { ++ ++ do { ++ spin_lock_irqsave(&host->lock, flags); ++ cmd_irq_reg = readl(host->base + MCI_RINTSTS); ++ if (cmd_irq_reg & ACD_INT_STATUS) { ++ fhmci_writel((ACD_INT_STATUS | RTO_INT_STATUS ++ | RCRC_INT_STATUS | RE_INT_STATUS), ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ return 0; ++ } ++ spin_unlock_irqrestore(&host->lock, flags); ++ cmd_retry_count++; ++ } while (cmd_retry_count < retry_count); ++ ++ cmd_retry_count = 0; ++ if (host->card_status == CARD_UNPLUGED) ++ return -1; ++ ++ if (!time_before(jiffies, cmd_jiffies_timeout)) { ++ fhmci_trace(3, "wait auto stop complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++ ++} ++#endif ++static int fh_mci_wait_data_complete(struct fhmci_host *host) ++{ ++ unsigned int tmp_reg; ++ struct mmc_data *data = host->data; ++ long time = request_timeout; ++ unsigned long flags; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ fhmci_assert(data); ++ ++ time = wait_event_timeout(host->intr_wait, ++ test_bit(FHMCI_PEND_DTO_b, &host->pending_events), ++ time); ++ ++ /* Mask MMC host data intr */ ++ spin_lock_irqsave(&host->lock, flags); ++ tmp_reg = fhmci_readl(host->base + MCI_INTMASK); ++ tmp_reg &= ~DATA_INT_MASK; ++ fhmci_writel(tmp_reg, host->base + MCI_INTMASK); ++ host->pending_events &= ~FHMCI_PEND_DTO_m; ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ if (((time <= 0) ++ && (!test_bit(FHMCI_PEND_DTO_b, &host->pending_events))) ++ || (host->card_status == CARD_UNPLUGED)) { ++ ++ data->error = -ETIMEDOUT; ++ fhmci_trace(3, "wait data request complete is timeout! 0x%08X", ++ host->irq_status); ++ fh_mci_idma_stop(host); ++ fh_mci_data_done(host, host->irq_status); ++ return -1; ++ } ++ ++ fh_mci_idma_stop(host); ++ fh_mci_data_done(host, host->irq_status); ++ return 0; ++} ++ ++ ++static int fh_mci_wait_card_complete(struct fhmci_host *host, ++ struct mmc_data *data) ++{ ++ unsigned int card_retry_count = 0; ++ unsigned long card_jiffies_timeout; ++ unsigned int card_status_reg = 0; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(host); ++ /* fhmci_assert(data); */ ++ ++ card_jiffies_timeout = jiffies + FH_MCI_DETECT_TIMEOUT; ++ while (1) { ++ ++ do { ++ card_status_reg = readl(host->base + MCI_STATUS); ++ if (!(card_status_reg & DATA_BUSY)) { ++ fhmci_trace(2, "end"); ++ return 0; ++ } ++ card_retry_count++; ++ } while (card_retry_count < retry_count); ++ card_retry_count = 0; ++ ++ if (host->card_status == CARD_UNPLUGED) { ++ data->error = -ETIMEDOUT; ++ return -1; ++ } ++ ++ if (!time_before(jiffies, card_jiffies_timeout)) { ++ if (data != NULL) ++ data->error = -ETIMEDOUT; ++ fhmci_trace(3, "wait card ready complete is timeout!"); ++ return -1; ++ } ++ ++ schedule(); ++ } ++} ++ ++static unsigned long t; ++static unsigned long cmds; ++static unsigned long long send_byte_count; ++static struct timeval in_cmd, out_cmd; ++static struct timeval *x = &out_cmd, *y = &in_cmd; ++static unsigned long max, sum; ++static unsigned long called, ended; ++ ++static void fh_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct fhmci_host *host = mmc_priv(mmc); ++ int byte_cnt = 0; ++ #ifdef CONFIG_SEND_AUTO_STOP ++ int trans_cnt; ++ #endif ++ int fifo_count = 0, tmp_reg; ++ int ret = 0; ++ unsigned long flags; ++ ++ if (host->id == 1) { ++ called++; ++ memset(x, 0, sizeof(struct timeval)); ++ memset(y, 0, sizeof(struct timeval)); ++ do_gettimeofday(y); ++ } ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(mmc); ++ fhmci_assert(mrq); ++ fhmci_assert(host); ++ ++ host->mrq = mrq; ++ host->irq_status = 0; ++ ++ ++ if (host->card_status == CARD_UNPLUGED) { ++ mrq->cmd->error = -ENODEV; ++ goto request_end; ++ } ++#if 1 ++ ret = fh_mci_wait_card_complete(host, mrq->data); ++ ++ if (ret) { ++ mrq->cmd->error = ret; ++ goto request_end; ++ } ++#endif ++ /* prepare data */ ++ if (mrq->data) { ++ ret = fh_mci_setup_data(host, mrq->data); ++ if (ret) { ++ mrq->data->error = ret; ++ fhmci_trace(3, "data setup is error!"); ++ goto request_end; ++ } ++ ++ byte_cnt = mrq->data->blksz * mrq->data->blocks; ++ fhmci_writel(byte_cnt, host->base + MCI_BYTCNT); ++ fhmci_writel(mrq->data->blksz, host->base + MCI_BLKSIZ); ++ ++ tmp_reg = fhmci_readl(host->base + MCI_CTRL); ++ tmp_reg |= FIFO_RESET; ++ fhmci_writel(tmp_reg, host->base + MCI_CTRL); ++ ++ do { ++ tmp_reg = fhmci_readl(host->base + MCI_CTRL); ++ fifo_count++; ++ if (fifo_count >= retry_count) { ++ printk(KERN_INFO "fifo reset is timeout!"); ++ return; ++ } ++ } while (tmp_reg&FIFO_RESET); ++ ++ /* start DMA */ ++ fh_mci_idma_start(host); ++ } else { ++ fhmci_writel(0, host->base + MCI_BYTCNT); ++ fhmci_writel(0, host->base + MCI_BLKSIZ); ++ } ++ ++ /* send command */ ++ ret = fh_mci_exec_cmd(host, mrq->cmd, mrq->data); ++ if (ret) { ++ mrq->cmd->error = ret; ++ fh_mci_idma_stop(host); ++ fhmci_trace(3, "can't send card cmd! ret = %d", ret); ++ goto request_end; ++ } ++ ++ /* wait command send complete */ ++ ret = fh_mci_wait_cmd_complete(host); ++ ++ /* start data transfer */ ++ if (mrq->data) { ++ if (!(mrq->cmd->error)) { ++ /* Open MMC host data intr */ ++ spin_lock_irqsave(&host->lock, flags); ++ tmp_reg = fhmci_readl(host->base + MCI_INTMASK); ++ tmp_reg |= DATA_INT_MASK; ++ fhmci_writel(tmp_reg, host->base + MCI_INTMASK); ++ spin_unlock_irqrestore(&host->lock, flags); ++ /* wait data transfer complete */ ++ ret = fh_mci_wait_data_complete(host); ++ } else { ++ /* CMD error in data command */ ++ fh_mci_idma_stop(host); ++ } ++ ++ if (mrq->stop) { ++#ifdef CONFIG_SEND_AUTO_STOP ++ trans_cnt = fhmci_readl(host->base + MCI_TCBCNT); ++ /* send auto stop */ ++ if ((trans_cnt == byte_cnt) && (!(host->is_tuning))) { ++ fhmci_trace(3, "byte_cnt = %d, trans_cnt = %d", ++ byte_cnt, trans_cnt); ++ ret = fh_mci_wait_auto_stop_complete(host); ++ if (ret) { ++ mrq->stop->error = -ETIMEDOUT; ++ goto request_end; ++ } ++ } else { ++#endif ++ /* send soft stop command */ ++ fhmci_trace(3, "this time, send soft stop"); ++ ret = fh_mci_exec_cmd(host, host->mrq->stop, ++ host->data); ++ if (ret) { ++ mrq->stop->error = ret; ++ goto request_end; ++ } ++ ret = fh_mci_wait_cmd_complete(host); ++ if (ret) ++ goto request_end; ++#ifdef CONFIG_SEND_AUTO_STOP ++ } ++#endif ++ } ++ } ++ ++request_end: ++ /* clear MMC host intr */ ++ spin_lock_irqsave(&host->lock, flags); ++ fhmci_writel(ALL_INT_CLR & (~SDIO_INT_STATUS), ++ host->base + MCI_RINTSTS); ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ fh_mci_finish_request(host, mrq); ++ ++ ++ if (host->id == 1) { ++ ended++; ++ do_gettimeofday(x); ++ ++ /* Perform the carry for the later subtraction by updating y. */ ++ if (x->tv_usec < y->tv_usec) { ++ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; ++ y->tv_usec -= 1000000 * nsec; ++ y->tv_sec += nsec; ++ } ++ if (x->tv_usec - y->tv_usec > 1000000) { ++ int nsec = (x->tv_usec - y->tv_usec) / 1000000; ++ y->tv_usec += 1000000 * nsec; ++ y->tv_sec -= nsec; ++ } ++ /* Compute the time remaining to wait. ++ * tv_usec is certainly positive. */ ++ if (((x->tv_sec - y->tv_sec) * 1000 ++ + x->tv_usec - y->tv_usec) > max) { ++ max = (x->tv_sec - y->tv_sec) ++ * 1000 + x->tv_usec - y->tv_usec; ++ } ++ ++ sum += (x->tv_sec - y->tv_sec) * 1000 + x->tv_usec - y->tv_usec; ++ ++ send_byte_count += byte_cnt; ++ cmds++; ++ ++ if (jiffies - t > HZ) { ++ /* ++ * pr_info("SDIO HOST send_byte_count: ++ * %llu in %u cmds, max cost time: %lu, ++ * sum: %lu, ave: %lu\ncalled: %lu, ended: %lu\n", ++ * send_byte_count, cmds, max, sum, ++ * sum / cmds, called, ended); ++ */ ++ t = jiffies; ++ send_byte_count = 0; ++ cmds = 0; ++ max = 0; ++ sum = 0; ++ called = 0; ++ ended = 0; ++ } ++ } ++} ++ ++static void fh_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct fhmci_host *host = mmc_priv(mmc); ++ unsigned int tmp_reg; ++ u32 ctrl; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(mmc); ++ fhmci_assert(ios); ++ fhmci_assert(host); ++ ++ fhmci_trace(3, "ios->power_mode = %d ", ios->power_mode); ++ switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ /* ++ * Set controller working voltage as 3.3V before power off. ++ */ ++ ctrl = fhmci_readl(host->base + MCI_UHS_REG); ++ ctrl &= ~FH_SDXC_CTRL_VDD_180; ++ fhmci_trace(3, "set voltage %d[addr 0x%x]", ctrl, MCI_UHS_REG); ++ fhmci_writel(ctrl, host->base + MCI_UHS_REG); ++ ++ fh_mci_ctrl_power(host, POWER_OFF); ++ break; ++ case MMC_POWER_UP: ++ case MMC_POWER_ON: ++ fh_mci_ctrl_power(host, POWER_ON); ++ break; ++ } ++ fhmci_trace(3, "ios->clock = %d ", ios->clock); ++ if (ios->clock) { ++ ++ fh_mci_control_cclk(host, DISABLE); ++ fh_mci_set_cclk(host, ios->clock); ++ fh_mci_control_cclk(host, ENABLE); ++ ++ /* speed mode check ,if it is DDR50 set DDR mode*/ ++ if ((ios->timing == MMC_TIMING_UHS_DDR50)) { ++ ctrl = fhmci_readl(host->base + MCI_UHS_REG); ++ if (!(FH_SDXC_CTRL_DDR_REG & ctrl)) { ++ ctrl |= FH_SDXC_CTRL_DDR_REG; ++ fhmci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ } else { ++ fh_mci_control_cclk(host, DISABLE); ++ if ((ios->timing != MMC_TIMING_UHS_DDR50)) { ++ ctrl = fhmci_readl(host->base + MCI_UHS_REG); ++ if (FH_SDXC_CTRL_DDR_REG & ctrl) { ++ ctrl &= ~FH_SDXC_CTRL_DDR_REG; ++ fhmci_writel(ctrl, host->base + MCI_UHS_REG); ++ } ++ } ++ } ++ ++ /* set bus_width */ ++ fhmci_trace(3, "ios->bus_width = %d ", ios->bus_width); ++ if (ios->bus_width == MMC_BUS_WIDTH_4) { ++ tmp_reg = fhmci_readl(host->base + MCI_CTYPE); ++ tmp_reg |= CARD_WIDTH; ++ fhmci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } else { ++ tmp_reg = fhmci_readl(host->base + MCI_CTYPE); ++ tmp_reg &= ~CARD_WIDTH; ++ fhmci_writel(tmp_reg, host->base + MCI_CTYPE); ++ } ++} ++ ++static void fhmci_enable_sdio_irq(struct mmc_host *host, int enable) ++{ ++ struct fhmci_host *fh_host = mmc_priv(host); ++ unsigned int reg_value; ++ unsigned long flags; ++ ++ if (enable) { ++ local_irq_save(flags); ++ ++ reg_value = fhmci_readl(fh_host->base + MCI_INTMASK); ++ reg_value |= 0x10000; ++ fhmci_writel(reg_value, fh_host->base + MCI_INTMASK); ++ local_irq_restore(flags); ++ } else { ++ reg_value = fhmci_readl(fh_host->base + MCI_INTMASK); ++ reg_value &= ~0xffff0000; ++ fhmci_writel(reg_value, fh_host->base + MCI_INTMASK); ++ } ++ ++} ++ ++ ++static int fh_mci_get_ro(struct mmc_host *mmc) ++{ ++ unsigned ret; ++ struct fhmci_host *host = mmc_priv(mmc); ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(mmc); ++ ++ ret = host->get_ro(host); ++ ++ return ret; ++} ++ ++/** ++ * @brief get the status of SD card's CD pin ++ * ++ * @param [in] mmc host struct ++ * ++ * @return "1": sd card in the slot, "0": sd card is not in the slot, "2":status of sd card no changed ++ */ ++static int fh_mci_get_cd(struct mmc_host *mmc) ++{ ++ unsigned int i, curr_status, status[3] = {0}, detect_retry_count = 0; ++ struct fhmci_host *host = mmc_priv(mmc); ++ ++ while (1) { ++ for (i = 0; i < 3; i++) { ++ status[i] = host->get_cd(host); ++ udelay(10); ++ } ++ if ((status[0] == status[1]) && (status[0] == status[2])) ++ break; ++ ++ detect_retry_count++; ++ if (detect_retry_count >= retry_count) { ++ fhmci_error("this is a dithering,card detect error!"); ++ goto err; ++ } ++ } ++ curr_status = status[0]; ++ if (curr_status != host->card_status) { ++ host->card_status = curr_status; ++ if (curr_status != CARD_UNPLUGED) { ++ fh_mci_init_card(host); ++ printk(KERN_INFO "card%d connected!\n", host->id); ++ mmc->rescan_count = 0; ++ return 1; ++ } else { ++ printk(KERN_INFO "card%d disconnected!\n", host->id); ++ return 0; ++ } ++ } ++ if (mmc->card == NULL) ++ fh_mci_init_card(host); ++err: ++ return 2; ++} ++ ++static const struct mmc_host_ops fh_mci_ops = { ++ .request = fh_mci_request, ++ .set_ios = fh_mci_set_ios, ++ .get_ro = fh_mci_get_ro, ++ .enable_sdio_irq = fhmci_enable_sdio_irq, ++ .get_cd = fh_mci_get_cd, ++}; ++ ++static irqreturn_t hisd_irq(int irq, void *dev_id) ++{ ++ struct fhmci_host *host = dev_id; ++ u32 state = 0; ++ int handle = 0; ++ ++ state = fhmci_readl(host->base + MCI_RINTSTS); ++ ++#ifndef CONFIG_SEND_AUTO_STOP ++ /* bugfix: when send soft stop to SD Card, Host will report ++ sdio interrupt, This situation needs to be avoided */ ++ if ((host->mmc->card != NULL) ++ && (host->mmc->card->type == MMC_TYPE_SDIO)) { ++#endif ++ if (state & SDIO_INT_STATUS) { ++ if (fhmci_readl(host->base + MCI_INTMASK) ++ & SDIO_INT_STATUS) { ++ fhmci_writel(SDIO_INT_STATUS, ++ host->base + MCI_RINTSTS); ++ mmc_signal_sdio_irq(host->mmc); ++ handle = 1; ++ } ++ } ++#ifndef CONFIG_SEND_AUTO_STOP ++ } ++#endif ++ ++ if (state & DATA_INT_MASK) { ++ handle = 1; ++ host->pending_events |= FHMCI_PEND_DTO_m; ++ ++ host->irq_status = fhmci_readl(host->base + MCI_RINTSTS); ++ if (host->irq_status ++ & (DCRC_INT_STATUS|SBE_INT_STATUS|EBE_INT_STATUS)) { ++ printk(KERN_ERR "SDC CRC error:%08x,.\n", ++ host->irq_status); ++ } ++ fhmci_writel(DATA_INT_MASK , host->base + MCI_RINTSTS); ++ ++ wake_up(&host->intr_wait); ++ } ++ ++ /*if (state & 0x10000) { ++ handle = 1; ++ fhmci_writel(0x10000, host->base + MCI_RINTSTS); ++ mmc_signal_sdio_irq(host->mmc); ++ }*/ ++ ++ if (handle) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++static int __devinit fh_mci_probe(struct platform_device *pdev) ++{ ++ struct resource *regs; ++ struct mmc_host *mmc; ++ struct fhmci_host *host = NULL; ++ int ret = 0, irq; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(pdev); ++ ++ mmc = mmc_alloc_host(sizeof(struct fhmci_host), &pdev->dev); ++ if (!mmc) { ++ fhmci_error("no mem for hi mci host controller!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ host = mmc_priv(mmc); ++ host->pdata = pdev->dev.platform_data; ++ mmc->ops = &fh_mci_ops; ++ mmc->rescan_disable = FALSE; ++ mmc->f_min = DIV_ROUND_UP(host->pdata->bus_hz, 510); ++ mmc->f_max = host->pdata->bus_hz; ++ ++ if (host->pdata->caps) ++ mmc->caps = host->pdata->caps; ++ else ++ mmc->caps = 0; ++ ++ mmc->caps |= MMC_CAP_SDIO_IRQ; ++ ++ if (0 == pdev->id) { ++ mmc_sd0 = mmc; ++ } else if (1 == pdev->id) { ++ mmc_sd1 = mmc; ++ } else { ++ fhmci_error("fhmci host id error!"); ++ goto out; ++ } ++ /* reload by this controller */ ++ mmc->max_blk_count = 2048; ++ mmc->max_segs = 1024; ++ mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; ++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; ++ ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ mmc->ocr = mmc->ocr_avail; ++ ++ host->dma_vaddr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, ++ &host->dma_paddr, GFP_KERNEL); ++ if (!host->dma_vaddr) { ++ fhmci_error("no mem for fhmci dma!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ host->mmc = mmc; ++ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!regs) { ++ fhmci_error("request resource error!\n"); ++ ret = -ENXIO; ++ goto out; ++ } ++ ++ host->id = pdev->id; ++ host->base = ioremap_nocache(regs->start, regs->end - regs->start + 1); ++ if (!host->base) { ++ fhmci_error("no mem for fhmci base!\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ if (host->pdata->init) ++ host->pdata->init(pdev->id, NULL, NULL); ++ ++ if (host->pdata->get_cd) ++ host->get_cd = host->pdata->get_cd; ++ else ++ host->get_cd = fh_mci_sys_card_detect; ++ ++ if (host->pdata->get_ro) ++ host->get_ro = host->pdata->get_ro; ++ else ++ host->get_ro = fh_mci_ctrl_card_readonly; ++ ++ /* config fifo depth */ ++ host->pdata->fifo_depth = ++ (fhmci_readl(host->base + MCI_FIFOTH) & 0xfff0000) >> 16; ++ ++ /* enable card */ ++ spin_lock_init(&host->lock); ++ platform_set_drvdata(pdev, mmc); ++ mmc_add_host(mmc); ++ ++ fhmci_writel(SD_POWER_ON, host->base + MCI_PWREN); ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ printk(KERN_ERR "no IRQ defined!\n"); ++ goto out; ++ } ++ ++ init_waitqueue_head(&host->intr_wait); ++ ++ host->irq = irq; ++ ret = request_irq(irq, hisd_irq, 0, ++ dev_name(&pdev->dev), host); ++ if (ret) { ++ printk(KERN_ERR "request_irq error!\n"); ++ goto out; ++ } ++ ++ ++ return 0; ++out: ++ if (host) { ++ ++ if (host->base) ++ iounmap(host->base); ++ ++ if (host->dma_vaddr) ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, ++ host->dma_vaddr, host->dma_paddr); ++ } ++ if (mmc) ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++/* for wifi Cypress 43438/43455 ++ * (Note: sd_id is the sdio index used by wifi) ++ */ ++void fh_sdio_card_scan(int sd_id) ++{ ++ if ((NULL != mmc_sd1) && (sd_id == 1)) { ++ printk(KERN_ERR "%s-%d(mmc_sd1->caps 0x%lx), enter\n", ++ __func__, __LINE__, mmc_sd1->caps); ++ mmc_sd1->caps &= ~MMC_CAP_NEEDS_POLL; ++ mmc_sd1->caps &= ~MMC_CAP_NONREMOVABLE; ++ /* mmc_host中rescan_count清0以触发 mmc_rescan() */ ++ mmc_sd1->rescan_count = 0; ++ mmc_detect_change(mmc_sd1, 0); ++ msleep(100); ++ mmc_sd1->caps |= MMC_CAP_NONREMOVABLE; ++ printk(KERN_ERR "%s-%d mmc_sd1->caps 0x%lx\n", __func__, ++ __LINE__, mmc_sd1->caps); ++ } else if ((NULL != mmc_sd0) && (sd_id == 0)) { ++ printk(KERN_ERR "%s-%d(mmc_sd0->caps 0x%lx), enter\n", ++ __func__, __LINE__, mmc_sd0->caps); ++ mmc_sd0->caps &= ~MMC_CAP_NEEDS_POLL; ++ mmc_sd0->caps &= ~MMC_CAP_NONREMOVABLE; ++ /* mmc_host中rescan_count清0以触发 mmc_rescan() */ ++ mmc_sd0->rescan_count = 0; ++ mmc_detect_change(mmc_sd0, 0); ++ msleep(100); ++ mmc_sd0->caps |= MMC_CAP_NONREMOVABLE; ++ printk(KERN_ERR "%s-%d mmc_sd0->caps 0x%lx\n", ++ __func__, __LINE__, mmc_sd0->caps); ++ } else { ++ printk(KERN_ERR "%s-%d, sd_id invalid!\n", __func__, __LINE__); ++ } ++ ++ return; ++} ++EXPORT_SYMBOL_GPL(fh_sdio_card_scan); ++ ++static int __devexit fh_mci_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (mmc) { ++ struct fhmci_host *host = mmc_priv(mmc); ++ ++ free_irq(host->irq, host); ++ mmc_remove_host(mmc); ++ fh_mci_ctrl_power(host, POWER_OFF); ++ fh_mci_control_cclk(host, DISABLE); ++ iounmap(host->base); ++ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->dma_vaddr, ++ host->dma_paddr); ++ mmc_free_host(mmc); ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int fh_mci_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(dev); ++ struct fhmci_host *host; ++ int ret = 0; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(dev); ++ ++ if (mmc) { ++ ret = mmc_suspend_host(mmc); ++ ++ host = mmc_priv(mmc); ++ } ++ ++ fhmci_trace(2, "end"); ++ ++ return ret; ++} ++ ++static int fh_mci_resume(struct platform_device *dev) ++{ ++ struct mmc_host *mmc = platform_get_drvdata(dev); ++ struct fhmci_host *host; ++ int ret = 0; ++ ++ fhmci_trace(2, "begin"); ++ fhmci_assert(dev); ++ ++ if (mmc) { ++ host = mmc_priv(mmc); ++ ++ /* enable card */ ++ fh_mci_init_card(host); ++ ++ ret = mmc_resume_host(mmc); ++ } ++ ++ fhmci_trace(2, "end"); ++ ++ return ret; ++} ++#else ++#define fh_mci_suspend NULL ++#define fh_mci_resume NULL ++#endif ++ ++ ++static struct platform_driver fh_mci_driver = { ++ .probe = fh_mci_probe, ++ .remove = fh_mci_remove, ++ .suspend = fh_mci_suspend, ++ .resume = fh_mci_resume, ++ .driver = { ++ .name = DRIVER_NAME, ++ }, ++}; ++ ++ ++static ssize_t fh_mci_rescan_control(struct class *cls, ++ struct class_attribute *attr, const char *_buf, size_t _count) ++{ ++ int cmd = 0; ++ int err = 0; ++ ++ err = kstrtoint(_buf, 10, &cmd); ++ if (err) ++ return _count; ++ ++ if (cmd) { ++ if (mmc_sd0) ++ mmc_sd0->rescan_count = 0; ++ if (mmc_sd1) ++ mmc_sd1->rescan_count = 0; ++ } ++ return _count; ++} ++ ++static struct class *fhmci_rescan_class; ++ ++static CLASS_ATTR(mmc_rescan, 0666, NULL, fh_mci_rescan_control); ++ ++static void fh_mci_rescan_init(void) ++{ ++ int err = 0; ++ ++ fhmci_rescan_class = class_create(THIS_MODULE, "fhmci"); ++ err = class_create_file(fhmci_rescan_class, &class_attr_mmc_rescan); ++ if (err) ++ fhmci_error("fhmci_rescan_class: create class file failed!"); ++} ++ ++static int __init fh_mci_init(void) ++{ ++ int ret = 0; ++ ++ fhmci_trace(2, "mci init begin"); ++ fh_mci_rescan_init(); ++ ++ ret = platform_driver_register(&fh_mci_driver); ++ if (ret) ++ fhmci_error("Platform driver register is failed!"); ++ ++ return ret; ++} ++ ++static void __exit fh_mci_exit(void) ++{ ++ fhmci_trace(2, "begin"); ++ platform_driver_unregister(&fh_mci_driver); ++} ++module_init(fh_mci_init); ++module_exit(fh_mci_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mmc/host/fhmci/fhmci_reg.h b/drivers/mmc/host/fhmci/fhmci_reg.h +new file mode 100644 +index 00000000..b4a215cf +--- /dev/null ++++ b/drivers/mmc/host/fhmci/fhmci_reg.h +@@ -0,0 +1,182 @@ ++#ifndef _FH_MCI_REG_H_ ++#define _FH_MCI_REG_H_ ++ ++#define MCI_CTRL 0x00 ++#define MCI_PWREN 0x04 ++#define MCI_CLKDIV 0x08 ++#define MCI_CLKSRC 0x0C ++#define MCI_CLKENA 0x10 ++#define MCI_TIMEOUT 0x14 ++#define MCI_CTYPE 0x18 ++#define MCI_BLKSIZ 0x1c ++#define MCI_BYTCNT 0x20 ++#define MCI_INTMASK 0x24 ++#define MCI_CMDARG 0x28 ++#define MCI_CMD 0x2C ++#define MCI_RESP0 0x30 ++#define MCI_RESP1 0x34 ++#define MCI_RESP2 0x38 ++#define MCI_RESP3 0x3C ++#define MCI_MINTSTS 0x40 ++#define MCI_RINTSTS 0x44 ++#define MCI_STATUS 0x48 ++#define MCI_FIFOTH 0x4C ++#define MCI_CDETECT 0x50 ++#define MCI_WRTPRT 0x54 ++#define MCI_GPIO 0x58 ++#define MCI_TCBCNT 0x5C ++#define MCI_TBBCNT 0x60 ++#define MCI_DEBNCE 0x64 ++#define MCI_USRID 0x68 ++#define MCI_VERID 0x6C ++#define MCI_HCON 0x70 ++#define MCI_UHS_REG 0x74 ++#define MCI_BMOD 0x80 ++#define MCI_DBADDR 0x88 ++#define MCI_IDSTS 0x8C ++#define MCI_IDINTEN 0x90 ++#define MCI_DSCADDR 0x94 ++#define MCI_BUFADDR 0x98 ++#define MCI_READ_THRESHOLD_SIZE 0x100 ++#define MCI_UHS_EXT 0x108 ++/* MCI_UHS_REG(0x74) details */ ++#define FH_SDXC_CTRL_VDD_180 (1<<0) ++#define FH_SDXC_CTRL_DDR_REG (1<<16) ++ ++/* MCI_BMOD(0x80) details */ ++#define BMOD_SWR (1<<0) ++#define BURST_INCR (1<<1) ++#define BURST_8 (0x2<<8) ++ ++/* MCI_CTRL(0x00) details */ ++#define CTRL_RESET (1<<0) ++#define FIFO_RESET (1<<1) ++#define DMA_RESET (1<<2) ++#define INTR_EN (1<<4) ++#define USE_INTERNAL_DMA (1<<25) ++ ++/* IDMAC DEST1 details */ ++#define DMA_BUFFER 0x2000 ++#define MAX_DMA_DES (20480) ++ ++/* MCI_CDETECT(0x50) details */ ++#define FHMCI_CARD0 (1<<0) ++ ++/* MCI_TIMEOUT(0x14) details: */ ++/*bit 31-8: data read timeout param*/ ++#define DATA_TIMEOUT (0xffffff<<8) ++ ++/* bit 7-0: response timeout param */ ++#define RESPONSE_TIMEOUT 0xff ++ ++/* bit 0: enable of card clk*/ ++#define CCLK_ENABLE (1<<0) ++ ++/* IDMAC DEST0 details */ ++#define DMA_DES_OWN (1<<31) ++#define DMA_DES_NEXT_DES (1<<4) ++#define DMA_DES_FIRST_DES (1<<3) ++#define DMA_DES_LAST_DES (1<<2) ++ ++/* MCI_BMOD(0x80) details */ ++#define BMOD_DMA_EN (1<<7) ++ ++/* MCI_CTYPE(0x18) details */ ++#define CARD_WIDTH (0x1<<0) ++ ++/* MCI_INTMASK(0x24) details: ++ bit 16-1: mask MMC host controller each interrupt ++*/ ++#define ALL_INT_MASK 0x1ffff ++#define DTO_INT_MASK (1<<3) ++ ++/* bit[18:16] sampling phase */ ++#define CLK_SMPL_PHS_MASK (7<<16) ++ ++/* MCI_CMD(0x2c) details: ++ bit 31: cmd execute or load start param of interface clk bit ++*/ ++#define START_CMD (1<<31) ++ ++ ++/* MCI_INTSTS(0x44) details */ ++/***************************************************************/ ++/* bit 16: sdio interrupt status */ ++#define SDIO_INT_STATUS (0x1<<16) ++ ++/* bit 15: end-bit error (read)/write no CRC interrupt status */ ++#define EBE_INT_STATUS (0x1<<15) ++ ++/* bit 14: auto command done interrupt status */ ++#define ACD_INT_STATUS (0x1<<14) ++ ++/* bit 13: start bit error interrupt status */ ++#define SBE_INT_STATUS (0x1<<13) ++ ++/* bit 12: hardware locked write error interrupt status */ ++#define HLE_INT_STATUS (0x1<<12) ++ ++/* bit 11: FIFO underrun/overrun error interrupt status */ ++#define FRUN_INT_STATUS (0x1<<11) ++ ++/* bit 10: data starvation-by-host timeout interrupt status */ ++#define HTO_INT_STATUS (0x1<<10) ++ ++/* bit 10: volt_switch to 1.8v for sdxc */ ++#define VOLT_SWITCH_INT_STATUS (0x1<<10) ++ ++/* bit 9: data read timeout interrupt status */ ++#define DRTO_INT_STATUS (0x1<<9) ++ ++/* bit 8: response timeout interrupt status */ ++#define RTO_INT_STATUS (0x1<<8) ++ ++/* bit 7: data CRC error interrupt status */ ++#define DCRC_INT_STATUS (0x1<<7) ++ ++/* bit 6: response CRC error interrupt status */ ++#define RCRC_INT_STATUS (0x1<<6) ++ ++/* bit 5: receive FIFO data request interrupt status */ ++#define RXDR_INT_STATUS (0x1<<5) ++ ++/* bit 4: transmit FIFO data request interrupt status */ ++#define TXDR_INT_STATUS (0x1<<4) ++ ++/* bit 3: data transfer Over interrupt status */ ++#define DTO_INT_STATUS (0x1<<3) ++ ++/* bit 2: command done interrupt status */ ++#define CD_INT_STATUS (0x1<<2) ++ ++/* bit 1: response error interrupt status */ ++#define RE_INT_STATUS (0x1<<1) ++#define DATA_INT_MASK (DTO_INT_STATUS | DCRC_INT_STATUS \ ++ | SBE_INT_STATUS | EBE_INT_STATUS) ++/***************************************************************/ ++ ++/* MCI_RINTSTS(0x44) details:bit 16-1: clear ++ MMC host controller each interrupt but ++ hardware locked write error interrupt ++*/ ++#define ALL_INT_CLR 0x1efff ++ ++#define PHASE_SHIFT 0x1030000 ++#define READ_THRESHOLD_SIZE 0x2000001 ++ ++/* MCI_STATUS(0x48) details */ ++#define DATA_BUSY (0x1<<9) ++ ++/* MCI_FIFOTH(0x4c) details */ ++ ++#define BURST_SIZE (0x2<<28) ++#define RX_WMARK (0x7<<16) ++#define TX_WMARK 0x8 ++ ++/* ++#define BURST_SIZE (0x6<<28) ++#define RX_WMARK (0x7f<<16) ++#define TX_WMARK 0x80 ++*/ ++ ++#endif +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index 4be8373d..98f2b8b0 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -330,6 +330,8 @@ source "drivers/mtd/onenand/Kconfig" + + source "drivers/mtd/lpddr/Kconfig" + ++source "drivers/mtd/spi-nand/Kconfig" ++ + source "drivers/mtd/ubi/Kconfig" + + endif # MTD +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 39664c42..baf5b647 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -31,4 +31,5 @@ inftl-objs := inftlcore.o inftlmount.o + + obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ + ++obj-$(CONFIG_MTD_SPI_NAND) += spi-nand/ + obj-$(CONFIG_MTD_UBI) += ubi/ +diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c +index e790f388..398cd61a 100644 +--- a/drivers/mtd/cmdlinepart.c ++++ b/drivers/mtd/cmdlinepart.c +@@ -48,7 +48,7 @@ + #define ERRP "mtd: " + + /* debug macro */ +-#if 0 ++#if 1 + #define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0) + #else + #define dbg(x) +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +old mode 100644 +new mode 100755 +index 35180e47..8536355d +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -47,10 +47,15 @@ + #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define OPCODE_RDID 0x9f /* Read JEDEC ID */ + ++#define OPCODE_DUAL_READ_3_ADR 0x3b ++#define OPCODE_QUAD_READ_3_ADR 0x6b ++#define OPCODE_DUAL_READ_4_ADR 0x3c ++#define OPCODE_QUAD_READ_4_ADR 0x6c ++ + /* Used for SST flashes only. */ + #define OPCODE_BP 0x02 /* Byte program */ + #define OPCODE_WRDI 0x04 /* Write disable */ +-#define OPCODE_AAI_WP 0xad /* Auto address increment word program */ ++#define OPCODE_AAI_WP 0xad /* Auto address increment word program */ + + /* Used for Macronix flashes only. */ + #define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ +@@ -161,15 +166,103 @@ static inline int write_disable(struct m25p *flash) + return spi_write_then_read(flash->spi, &code, 1, NULL, 0); + } + ++ ++/* ++ * Enable/disable QE. ++ */ ++static inline int set_qe(struct m25p *flash, u32 jedec_id, int enable) ++{ ++ int ret = 0; ++ struct spi_device *spi = flash->spi; ++ u8 send_cmd[5] = {0}; ++ u8 get_data[5] = {0}; ++ ++ switch (JEDEC_MFR(jedec_id)) { ++ case CFI_MFR_MACRONIX: ++ send_cmd[0] = 0x05; ++ ret = spi_write_then_read(spi, send_cmd, 1, get_data, 1); ++ if(ret < 0) ++ return -1; ++ get_data[0] &= ~(1 << 6); ++ get_data[0] |= (enable << 6); ++ send_cmd[0] = 0x01; ++ send_cmd[1] = get_data[0]; ++ write_enable(flash); ++ ret = spi_write(spi, send_cmd, 2); ++ if (ret < 0) ++ return -1; ++ break; ++ case 0xC8 /* GD */ : ++ send_cmd[0] = 0x35; ++ ret = spi_write_then_read(spi, send_cmd, 1, get_data, 1); ++ if (ret < 0) ++ return -1; ++ get_data[0] &= ~(1 << 1); ++ get_data[0] |= (enable << 1); ++ send_cmd[0] = 0x31; ++ send_cmd[1] = get_data[0]; ++ write_enable(flash); ++ ret = spi_write(spi, send_cmd, 2); ++ if (ret < 0) ++ return -1; ++ break; ++ case 0xEF /* winbond */: ++ /* status 0 */ ++ send_cmd[0] = 0x05; ++ ret = spi_write_then_read(spi, send_cmd, 1, get_data, 1); ++ if (ret < 0) ++ return -1; ++ /* status 1 */ ++ send_cmd[0] = 0x35; ++ ret = spi_write_then_read(spi, send_cmd, 1, &get_data[1], 1); ++ if (ret < 0) ++ return -1; ++ get_data[1] &= ~(1 << 1); ++ get_data[1] |= (enable << 1); ++ send_cmd[0] = 0x01; ++ send_cmd[1] = get_data[0]; ++ send_cmd[2] = get_data[1]; ++ write_enable(flash); ++ ret = spi_write(spi, send_cmd, 3); ++ if (ret < 0) ++ return -1; ++ break; ++ case 0x20 /* xmc */: ++ /* 16MB and 8MB default support multi wire*/ ++ break; ++ default: ++ ret = -1; ++ dev_err(&spi->dev, "%s : %d default not support multi wire..\n", __func__, __LINE__); ++ break; ++ } ++ return ret; ++ ++} + /* + * Enable/disable 4-byte addressing mode. + */ + static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + { ++ int ret; + switch (JEDEC_MFR(jedec_id)) { + case CFI_MFR_MACRONIX: ++ case CFI_MFR_ST: /* Micron, actually */ ++ case 0xC8 /* GD */ : ++ flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; ++ ret = spi_write(flash->spi, flash->command, 1); ++ return ret; ++ case 0xEF /* winbond */: + flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; +- return spi_write(flash->spi, flash->command, 1); ++ ret = spi_write(flash->spi, flash->command, 1); ++ if (!enable) ++ { ++ flash->command[0] = 0x06; ++ spi_write(flash->spi, flash->command, 1); ++ flash->command[0] = 0xc5; ++ flash->command[1] = 0x00; ++ ret = spi_write(flash->spi, flash->command, 2); ++ } ++ return ret; + default: + /* Spansion style */ + flash->command[0] = OPCODE_BRWR; +@@ -178,6 +271,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) + } + } + ++ + /* + * Service routine to read status register until ready, or timeout occurs. + * Returns non-zero if error. +@@ -192,7 +286,7 @@ static int wait_till_ready(struct m25p *flash) + do { + if ((sr = read_sr(flash)) < 0) + break; +- else if (!(sr & SR_WIP)) ++ else if (!(sr & (SR_WIP | SR_WEL))) + return 0; + + cond_resched(); +@@ -202,6 +296,43 @@ static int wait_till_ready(struct m25p *flash) + return 1; + } + ++ ++static int reset_chip(struct m25p *flash, u32 jedec_id) ++{ ++ int ret; ++ mutex_lock(&flash->lock); ++ ++ /* Wait till previous write/erase is done. */ ++ if (wait_till_ready(flash)) { ++ mutex_unlock(&flash->lock); ++ return 1; ++ } ++ ++ switch (JEDEC_MFR(jedec_id)) { ++ case 0x9F: /* S25FL128/256S spansion */ ++ flash->command[0] = 0xFF; ++ ret = spi_write(flash->spi, flash->command, 1); ++ flash->command[0] = 0xF0; ++ ret = spi_write(flash->spi, flash->command, 1); ++ mutex_unlock(&flash->lock); ++ return ret; ++ case 0xef: /*winbond*/ ++ case 0xc8: /*GD*/ ++ flash->command[0] = 0x66; ++ ret = spi_write(flash->spi, flash->command, 1); ++ flash->command[0] = 0x99; ++ ret = spi_write(flash->spi, flash->command, 1); ++ udelay(100); ++ mutex_unlock(&flash->lock); ++ return ret; ++ case CFI_MFR_MACRONIX: ++ case CFI_MFR_ST: /* Micron, actually */ ++ default: ++ mutex_unlock(&flash->lock); ++ return 0; ++ } ++} ++ + /* + * Erase the whole flash memory + * +@@ -283,7 +414,7 @@ static int erase_sector(struct m25p *flash, u32 offset) + static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) + { + struct m25p *flash = mtd_to_m25p(mtd); +- u32 addr,len; ++ u32 addr, len; + uint32_t rem; + + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n", +@@ -341,13 +472,49 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) + * Read an address range from the flash chip. The address range + * may be any size provided it is within the physical boundaries. + */ ++ ++void fix_read_cmd(struct m25p *p_m25p, struct spi_transfer *p_trans) ++{ ++ struct spi_device *spi; ++ struct m25p *flash; ++ flash = p_m25p; ++ spi = flash->spi; ++ /*if spi dev open as multi wire..check cmd data.*/ ++ if (spi->dev_open_multi_wire_flag & MULTI_WIRE_SUPPORT) { ++ p_trans[0].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ if (spi->dev_open_multi_wire_flag & QUAD_WIRE_SUPPORT) { ++ p_trans[1].xfer_wire_mode = QUAD_WIRE_SUPPORT; ++ p_trans[1].xfer_dir = SPI_DATA_DIR_IN; ++ if (flash->addr_width == 4) ++ flash->command[0] = OPCODE_QUAD_READ_4_ADR; ++ else ++ flash->command[0] = OPCODE_QUAD_READ_3_ADR; ++ } else if (spi->dev_open_multi_wire_flag & DUAL_WIRE_SUPPORT) { ++ p_trans[1].xfer_wire_mode = DUAL_WIRE_SUPPORT; ++ p_trans[1].xfer_dir = SPI_DATA_DIR_IN; ++ if (flash->addr_width == 4) ++ flash->command[0] = OPCODE_DUAL_READ_4_ADR; ++ else ++ flash->command[0] = OPCODE_DUAL_READ_3_ADR; ++ } else { ++ /*p_trans[0].xfer_wire_mode = ONE_WIRE_SUPPORT;*/ ++ p_trans[1].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ p_trans[1].xfer_dir = SPI_DATA_DIR_IN; ++ flash->command[0] = OPCODE_READ; } ++ } else ++ flash->command[0] = OPCODE_READ; ++} ++ + static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) + { + struct m25p *flash = mtd_to_m25p(mtd); + struct spi_transfer t[2]; + struct spi_message m; +- ++ struct spi_device *spi; ++ struct spi_master *master; ++ spi = flash->spi; ++ master = spi->master; + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + dev_name(&flash->spi->dev), __func__, "from", + (u32)from, len); +@@ -392,13 +559,19 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, + */ + + /* Set up the write data buffer. */ +- flash->command[0] = OPCODE_READ; ++ /*fix cmd here...*/ ++ fix_read_cmd(flash, t); + m25p_addr2cmd(flash, from, flash->command); + + spi_sync(flash->spi, &m); + + *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE; +- ++ /*back to one wire..*/ ++ if (spi->dev_open_multi_wire_flag & MULTI_WIRE_SUPPORT) { ++ /*change to one wire here first.....*/ ++ /*printk("back to one wire..\n");*/ ++ master->ctl_multi_wire_info.change_to_1_wire(master); ++ } + mutex_unlock(&flash->lock); + + return 0; +@@ -425,7 +598,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, + + /* sanity checks */ + if (!len) +- return(0); ++ return 0; + + if (to + len > flash->mtd.size) + return -EINVAL; +@@ -630,9 +803,11 @@ struct flash_info { + u16 flags; + #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ + #define M25P_NO_ERASE 0x02 /* No erase command needed */ ++ ++ u32 multi_wire_open; + }; + +-#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags, _multi_wire_flag) \ + ((kernel_ulong_t)&(struct flash_info) { \ + .jedec_id = (_jedec_id), \ + .ext_id = (_ext_id), \ +@@ -640,135 +815,162 @@ struct flash_info { + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), \ ++ .multi_wire_open = (_multi_wire_flag),\ + }) + +-#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \ ++#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _multi_wire_flag) \ + ((kernel_ulong_t)&(struct flash_info) { \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = (_page_size), \ + .addr_width = (_addr_width), \ + .flags = M25P_NO_ERASE, \ ++ .multi_wire_open = (_multi_wire_flag),\ + }) + + /* NOTE: double check command sets and memory organization when you add + * more flash chips. This current list focusses on newer chips, which + * have been converging on command sets which including JEDEC ID. + */ ++#define M25P80_4_WIRE_ALL_SUPPORT (ONE_WIRE_SUPPORT | \ ++DUAL_WIRE_SUPPORT | QUAD_WIRE_SUPPORT | MULTI_WIRE_SUPPORT) ++#define M25P80_2_WIRE_ALL_SUPPORT (ONE_WIRE_SUPPORT | \ ++DUAL_WIRE_SUPPORT | MULTI_WIRE_SUPPORT) + static const struct spi_device_id m25p_ids[] = { + /* Atmel -- some are (confusingly) marketed as "DataFlash" */ +- { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, +- { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, ++ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K, 0) }, ++ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K, 0) }, + +- { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, +- { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, ++ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K, 0) }, ++ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K, 0) }, + +- { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, +- { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, +- { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, +- { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, ++ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K, 0) }, ++ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K, 0) }, ++ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K, 0) }, ++ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K, 0) }, + + /* EON -- en25xxx */ +- { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, +- { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, +- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, ++ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0, 0) }, ++ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0, 0) }, + + /* Intel/Numonyx -- xxxs33b */ +- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, +- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, +- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, ++ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0, 0) }, ++ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0, 0) }, ++ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0, 0) }, + + /* Macronix */ +- { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, +- { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, +- { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, +- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, +- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, +- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, +- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, +- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, +- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, ++ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K, 0) }, ++ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0, 0) }, ++ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K, 0) }, ++ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0, 0) }, ++ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0, 0) }, ++ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0, 0) }, ++ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0, 0) }, + + /* Spansion -- single (large) sector size only, at least + * for the chips listed here (without boot sectors). + */ +- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, +- { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, +- { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, +- { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, +- { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, +- { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, +- { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, +- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, +- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, +- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, +- { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, +- { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, +- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, +- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, +- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, +- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, +- ++ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0, 0) }, ++ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0, 0) }, ++ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0, 0) }, ++ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0, 0) }, ++ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K, 0) }, ++ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0, 0) }, ++ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0, 0) }, ++ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0, 0) }, ++ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0, 0) }, ++ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0, 0) }, ++ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0, 0) }, ++ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0, 0) }, ++ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0, 0) }, ++ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0, 0) }, + /* SST -- large erase sizes are "overlays", "sectors" are 4K */ +- { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, +- { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) }, +- { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) }, +- { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) }, +- { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K) }, +- { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K) }, +- { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K) }, +- { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K) }, ++ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K, 0) }, ++ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K, 0) }, ++ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K, 0) }, ++ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K, 0) }, ++ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K, 0) }, ++ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K, 0) }, ++ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K, 0) }, + + /* ST Microelectronics -- newer production may have feature updates */ +- { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, +- { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, +- { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, +- { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, +- { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, +- { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, +- { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, +- { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, +- { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, +- +- { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, +- { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, +- { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, +- { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, +- { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, +- { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, +- { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, +- { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, +- { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, +- +- { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, +- { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, +- { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, +- +- { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, +- { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, +- +- { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, +- { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, +- { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, +- { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, ++ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0, 0) }, ++ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0, 0) }, ++ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0, 0) }, ++ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0, 0) }, ++ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0, 0) }, ++ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0, 0) }, ++ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0, 0) }, ++ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0, 0) }, ++ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0, 0) }, ++ ++ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0, 0) }, ++ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0, 0) }, ++ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0, 0) }, ++ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0, 0) }, ++ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0, 0) }, ++ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0, 0) }, ++ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0, 0) }, ++ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0, 0) }, ++ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0, 0) }, ++ ++ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0, 0) }, ++ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0, 0) }, ++ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0, 0) }, ++ ++ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0, 0) }, ++ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K, 0) }, ++ ++ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0, 0) }, + + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ +- { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, +- { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, +- { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, +- { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, +- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, +- { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, +- { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, +- { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, +- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, +- ++ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K, 0) }, ++ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K, 0) }, ++ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K, 0) }, ++ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K, 0) }, ++ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K, 0) }, ++ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K, 0) }, ++ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K, 0) }, ++ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K, 0) }, ++ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K, 0) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "w25q16", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K, ++ M25P80_4_WIRE_ALL_SUPPORT) }, + /* Catalyst / On Semiconductor -- non-JEDEC */ +- { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, +- { "cat25c03", CAT25_INFO( 32, 8, 16, 2) }, +- { "cat25c09", CAT25_INFO( 128, 8, 32, 2) }, +- { "cat25c17", CAT25_INFO( 256, 8, 32, 2) }, +- { "cat25128", CAT25_INFO(2048, 8, 64, 2) }, ++ { "cat25c11", CAT25_INFO(16, 8, 16, 1, 0) }, ++ { "cat25c03", CAT25_INFO(32, 8, 16, 2, 0) }, ++ { "cat25c09", CAT25_INFO(128, 8, 32, 2, 0) }, ++ { "cat25c17", CAT25_INFO(256, 8, 32, 2, 0) }, ++ { "cat25128", CAT25_INFO(2048, 8, 64, 2, 0) }, ++ ++ /*for GD flash..*/ ++ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ /*for xmc flash..*/ ++ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, ++ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, 0, ++ M25P80_4_WIRE_ALL_SUPPORT) }, + { }, + }; + MODULE_DEVICE_TABLE(spi, m25p_ids); +@@ -827,12 +1029,19 @@ static int __devinit m25p_probe(struct spi_device *spi) + unsigned i; + struct mtd_partition *parts = NULL; + int nr_parts = 0; +- ++ struct spi_master *p_master; ++ int ret; + /* Platform data helps sort out which chip type we have, as + * well as how this board partitions it. If we don't have + * a chip ID, try the JEDEC id commands; they'll work for most + * newer chips, even if we don't recognize the particular chip. + */ ++ p_master = spi->master; ++ if (p_master->ctl_multi_wire_info.ctl_wire_support ++ & MULTI_WIRE_SUPPORT) { ++ /*if master support multi wire, set one wire here..*/ ++ p_master->ctl_multi_wire_info.change_to_1_wire(p_master); ++ } + data = spi->dev.platform_data; + if (data && data->type) { + const struct spi_device_id *plat_id; +@@ -876,7 +1085,8 @@ static int __devinit m25p_probe(struct spi_device *spi) + flash = kzalloc(sizeof *flash, GFP_KERNEL); + if (!flash) + return -ENOMEM; +- flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL); ++ flash->command = ++ kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL); + if (!flash->command) { + kfree(flash); + return -ENOMEM; +@@ -909,6 +1119,7 @@ static int __devinit m25p_probe(struct spi_device *spi) + flash->mtd.size = info->sector_size * info->n_sectors; + flash->mtd.erase = m25p80_erase; + flash->mtd.read = m25p80_read; ++ flash->mtd.priv = (void *)info->jedec_id; + + /* sst flash chips use AAI word program */ + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) +@@ -941,6 +1152,12 @@ static int __devinit m25p_probe(struct spi_device *spi) + } else + flash->addr_width = 3; + } ++ /* add set qe bit here.. */ ++ ret = set_qe(flash, info->jedec_id, 1); ++ if (ret != 0) ++ info->multi_wire_open = 0; ++ spi->dev_open_multi_wire_flag = info->multi_wire_open; ++ spi_dev_set_multi_data(p_master, spi); + + dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, + (long long)flash->mtd.size >> 10); +@@ -1005,6 +1222,20 @@ static int __devinit m25p_probe(struct spi_device *spi) + -ENODEV : 0; + } + ++static void m25p_shutdown(struct spi_device *spi) ++{ ++ struct m25p *flash = dev_get_drvdata(&spi->dev); ++ u32 jedec = (u32)flash->mtd.priv; ++ dev_err(&spi->dev, "[m25] shutdown here? \n"); ++ if (flash->addr_width == 4) { ++ set_4byte(flash, jedec, 0); ++ flash->addr_width = 3; ++ } ++ ++ if (reset_chip(flash, jedec)) ++ dev_err(&spi->dev, "[m25] reset chip error...\n"); ++} ++ + + static int __devexit m25p_remove(struct spi_device *spi) + { +@@ -1030,7 +1261,7 @@ static struct spi_driver m25p80_driver = { + .id_table = m25p_ids, + .probe = m25p_probe, + .remove = __devexit_p(m25p_remove), +- ++ .shutdown = m25p_shutdown, + /* REVISIT: many of these chips have deep power-down modes, which + * should clearly be entered on suspend() to minimize power use. + * And also when they're otherwise idle... +diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c +old mode 100644 +new mode 100755 +index 3326615a..757cb7a9 +--- a/drivers/mtd/mtdblock.c ++++ b/drivers/mtd/mtdblock.c +@@ -268,7 +268,8 @@ static int mtdblock_writesect(struct mtd_blktrans_dev *dev, + { + struct mtdblk_dev *mtdblk = container_of(dev, struct mtdblk_dev, mbd); + if (unlikely(!mtdblk->cache_data && mtdblk->cache_size)) { +- mtdblk->cache_data = vmalloc(mtdblk->mbd.mtd->erasesize); ++ mtdblk->cache_data = kmalloc(mtdblk->mbd.mtd->erasesize, ++ GFP_KERNEL); + if (!mtdblk->cache_data) + return -EINTR; + /* -EINTR is not really correct, but it is the best match +@@ -324,7 +325,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) + /* It was the last usage. Free the cache */ + if (mbd->mtd->sync) + mbd->mtd->sync(mbd->mtd); +- vfree(mtdblk->cache_data); ++ kfree(mtdblk->cache_data); + } + + mutex_unlock(&mtdblks_lock); +diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c +index 630be3e7..6b89835f 100644 +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -72,6 +72,12 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, + len = mtd->size - from; + res = part->master->read(part->master, from + part->offset, + len, retlen, buf); ++ ++ if ((part->master->bitflip_threshold != 0) && ++ (res >= part->master->bitflip_threshold)) ++ res = -EUCLEAN; ++ ++ + if (unlikely(res)) { + if (res == -EUCLEAN) + mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; +diff --git a/drivers/mtd/spi-nand/Kconfig b/drivers/mtd/spi-nand/Kconfig +new file mode 100644 +index 00000000..b4da8f5b +--- /dev/null ++++ b/drivers/mtd/spi-nand/Kconfig +@@ -0,0 +1,7 @@ ++menuconfig MTD_SPI_NAND ++ tristate "SPI-NAND device Support" ++ depends on MTD_NAND && SPI ++ help ++ This is the framework for the SPI NAND which can be used by the SPI ++ device drivers and the SPI-NAND device drivers. ++ +diff --git a/drivers/mtd/spi-nand/Makefile b/drivers/mtd/spi-nand/Makefile +new file mode 100644 +index 00000000..971e7a9d +--- /dev/null ++++ b/drivers/mtd/spi-nand/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-$(CONFIG_MTD_SPI_NAND) += spi-nand-base.o spi-nand-bbt.o spi-nand-device.o spi-nand-ids.o +diff --git a/drivers/mtd/spi-nand/spi-nand-base.c b/drivers/mtd/spi-nand/spi-nand-base.c +new file mode 100644 +index 00000000..e96cb71d +--- /dev/null ++++ b/drivers/mtd/spi-nand/spi-nand-base.c +@@ -0,0 +1,2150 @@ ++/** ++* spi-nand-base.c ++* ++* Copyright (c) 2009-2014 Micron Technology, Inc. ++* ++* Derived from nand_base.c ++* ++* This program is free software; you can redistribute it and/or ++* modify it under the terms of the GNU General Public License ++* as published by the Free Software Foundation; either version 2 ++* of the License, or (at your option) any later version. ++* ++* This program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++*/ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/jiffies.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/mtd/spi-nand.h> ++#include <linux/mtd/bbm.h> ++#include <linux/spi/spi.h> ++#include <linux/slab.h> ++#include "spi-nand-ids.h" ++ ++int fh_start_debug = 0; ++/*#define SPINAND_BBT_DEBUG*/ ++#ifdef SPINAND_BBT_DEBUG ++#define fh_dev_debug dev_err ++#else ++#define fh_dev_debug(...) ++#endif ++ ++static int spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo); ++ ++/** ++ * spi_nand_get_device - [GENERIC] Get chip for selected access ++ * @mtd: MTD device structure ++ * @new_state: the state which is requested ++ * ++ * Get the device and lock it for exclusive access ++ */ ++static int spi_nand_get_device(struct mtd_info *mtd, int new_state) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ /* ++ * Grab the lock and see if the device is available ++ */ ++ while (1) { ++ spin_lock(&this->chip_lock); ++ if (this->state == FL_READY) { ++ this->state = new_state; ++ spin_unlock(&this->chip_lock); ++ break; ++ } ++ if (new_state == FL_PM_SUSPENDED) { ++ spin_unlock(&this->chip_lock); ++ return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; ++ } ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&this->wq, &wait); ++ spin_unlock(&this->chip_lock); ++ schedule(); ++ remove_wait_queue(&this->wq, &wait); ++ } ++ return 0; ++} ++ ++/** ++ * spi_nand_release_device - [GENERIC] release chip ++ * @mtd: MTD device structure ++ * ++ * Deselect, release chip lock and wake up anyone waiting on the device ++ */ ++static void spi_nand_release_device(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ ++ /* Release the chip */ ++ spin_lock(&this->chip_lock); ++ this->state = FL_READY; ++ wake_up(&this->wq); ++ spin_unlock(&this->chip_lock); ++} ++ ++/** ++ * __spi_nand_do_read_page - [INTERN] read data from flash to buffer ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @column :column address ++ * @raw: without ecc or not ++ * @corrected: how many bit error corrected ++ * ++ * read a page to buffer pointed by chip->buf ++ */ ++static int __spi_nand_do_read_page(struct mtd_info *mtd, u32 page_addr, ++ u32 colunm, bool raw, int *corrected) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int ret, ecc_error; ++ u8 status; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ /*read data from chip*/ ++ memset(chip->buf, 0, chip->page_size + chip->page_spare_size); ++ if (raw) { ++ ret = chip->disable_ecc(chip); ++ if (ret < 0) { ++ pr_debug("disable ecc failed\n"); ++ return ret; ++ } ++ } ++ ret = chip->load_page(chip, page_addr); ++ if (ret < 0) { ++ pr_debug("error %d loading page 0x%x to cache\n", ++ ret, page_addr); ++ return ret; ++ } ++ ret = chip->waitfunc(chip, &status); ++ if (ret < 0) { ++ pr_debug("error %d waiting page 0x%x to cache\n", ++ ret, page_addr); ++ return ret; ++ } ++ chip->get_ecc_status(chip, status, corrected, &ecc_error); ++ /* ++ * If there's an ECC error, print a message and notify MTD ++ * about it. Then complete the read, to load actual data on ++ * the buffer (instead of the status result). ++ */ ++ if (ecc_error) { ++ pr_warn("internal ECC error reading page 0x%x with status 0x%02x\n", ++ page_addr, status); ++ mtd->ecc_stats.failed++; ++ } else if (*corrected) ++ mtd->ecc_stats.corrected += *corrected; ++ /* Get page from the device cache into our internal buffer */ ++ ret = chip->read_cache(chip, page_addr, colunm, ++ chip->page_size + chip->page_spare_size - colunm, ++ chip->buf + colunm); ++ if (ret < 0) { ++ pr_debug("error %d reading page 0x%x from cache\n", ++ ret, page_addr); ++ return ret; ++ } ++ if (raw) { ++ ret = chip->enable_ecc(chip); ++ if (ret < 0) { ++ pr_debug("enable ecc failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * spi_nand_do_read_page - [INTERN] read a page from flash to buffer ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @raw: without ecc or not ++ * @corrected: how many bit error corrected ++ * ++ * read a page to buffer pointed by chip->buf ++ */ ++static int spi_nand_do_read_page(struct mtd_info *mtd, u32 page_addr, ++ bool raw, int *corrected) ++{ ++ return __spi_nand_do_read_page(mtd, page_addr, 0, raw, corrected); ++} ++ ++/** ++ * spi_nand_do_read_page_oob - [INTERN] read page oob from flash to buffer ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @raw: without ecc or not ++ * @corrected: how many bit error corrected ++ * ++ * read page oob to buffer pointed by chip->oobbuf ++ */ ++static int spi_nand_do_read_page_oob(struct mtd_info *mtd, u32 page_addr, ++ bool raw, int *corrected) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ return __spi_nand_do_read_page(mtd, page_addr, chip->page_size, ++ raw, corrected); ++} ++ ++ ++/** ++ * __spi_nand_do_write_page - [INTERN] write data from buffer to flash ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @column :column address ++ * @raw: without ecc or not ++ * ++ * write data from buffer pointed by chip->buf to flash ++ */ ++static int __spi_nand_do_write_page(struct mtd_info *mtd, u32 page_addr, ++ u32 column, bool raw) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ u8 status; ++ bool p_fail = false; ++ bool p_timeout = false; ++ int ret = 0; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s, with buf \n", __func__); ++ ++ if (raw) { ++ ret = chip->disable_ecc(chip); ++ if (ret < 0) { ++ pr_debug("disable ecc failed\n"); ++ return ret; ++ } ++ } ++ ret = chip->write_enable(chip); ++ if (ret < 0) { ++ pr_debug("write enable command failed\n"); ++ return ret; ++ } ++ /* Store the page to cache */ ++ ret = chip->store_cache(chip, page_addr, column, ++ chip->page_size + chip->page_spare_size - column, ++ chip->buf + column); ++ if (ret < 0) { ++ pr_debug("error %d storing page 0x%x to cache\n", ++ ret, page_addr); ++ return ret; ++ } ++ /* Get page from the device cache into our internal buffer */ ++ ret = chip->write_page(chip, page_addr); ++ if (ret < 0) { ++ pr_debug("error %d reading page 0x%x from cache\n", ++ ret, page_addr); ++ return ret; ++ } ++ ret = chip->waitfunc(chip, &status); ++ if (ret < 0) { ++ pr_info("error %d write page 0x%x timeout\n", ++ ret, page_addr); ++ return ret; ++ } ++ if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) { ++ pr_debug("program page 0x%x failed\n", page_addr); ++ p_fail = true; ++ } ++ ++ if ((status & STATUS_OIP_MASK) == STATUS_BUSY) { ++ pr_debug("program page 0x%x timeout\n", page_addr); ++ p_timeout = true; ++ } ++ if (raw) { ++ ret = chip->enable_ecc(chip); ++ if (ret < 0) { ++ pr_debug("enable ecc failed\n"); ++ return ret; ++ } ++ } ++ if ((p_fail == true)||(p_timeout == true)) ++ ret = -EIO; ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_do_write_page - [INTERN] write page from buffer to flash ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @raw: without ecc or not ++ * ++ * write page from buffer pointed by chip->buf to flash ++ */ ++static int spi_nand_do_write_page(struct mtd_info *mtd, u32 page_addr, ++ bool raw) ++{ ++ return __spi_nand_do_write_page(mtd, page_addr, 0, raw); ++} ++ ++/** ++ * spi_nand_do_write_page_oob - [INTERN] write oob from buffer to flash ++ * @mtd: MTD device structure ++ * @page_addr: page address/raw address ++ * @raw: without ecc or not ++ * ++ * write oob from buffer pointed by chip->oobbuf to flash ++ */ ++static int spi_nand_do_write_page_oob(struct mtd_info *mtd, u32 page_addr, ++ bool raw) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ return __spi_nand_do_write_page(mtd, page_addr, chip->page_size, raw); ++} ++ ++ ++/** ++ * spi_nand_transfer_oob - [INTERN] Transfer oob to client buffer ++ * @chip: SPI-NAND device structure ++ * @oob: oob destination address ++ * @ops: oob ops structure ++ * @len: size of oob to transfer ++ */ ++static void spi_nand_transfer_oob(struct spi_nand_chip *chip, u8 *oob, ++ struct mtd_oob_ops *ops, size_t len) ++{ ++ switch (ops->mode) { ++ ++ case MTD_OOB_PLACE: /*MTD_OPS_PLACE_OOB:*/ ++ case MTD_OOB_RAW: /*MTD_OPS_RAW:*/ ++ memcpy(oob, chip->oobbuf + ops->ooboffs, len); ++ return; ++ ++ case MTD_OOB_AUTO: { /*MTD_OPS_AUTO_OOB:*/ ++ struct nand_oobfree *free = chip->ecclayout->oobfree; ++ uint32_t boffs = 0, roffs = ops->ooboffs; ++ size_t bytes = 0; ++ ++ for (; free->length && len; free++, len -= bytes) { ++ /* Read request not from offset 0? */ ++ if (unlikely(roffs)) { ++ if (roffs >= free->length) { ++ roffs -= free->length; ++ continue; ++ } ++ boffs = free->offset + roffs; ++ bytes = min_t(size_t, len, ++ (free->length - roffs)); ++ roffs = 0; ++ } else { ++ bytes = min_t(size_t, len, free->length); ++ boffs = free->offset; ++ } ++ memcpy(oob, chip->oobbuf + boffs, bytes); ++ oob += bytes; ++ } ++ return; ++ } ++ default: ++ BUG(); ++ } ++} ++ ++/** ++ * spi_nand_fill_oob - [INTERN] Transfer client buffer to oob ++ * @chip: SPI-NAND device structure ++ * @oob: oob data buffer ++ * @len: oob data write length ++ * @ops: oob ops structure ++ */ ++static void spi_nand_fill_oob(struct spi_nand_chip *chip, uint8_t *oob, ++ size_t len, struct mtd_oob_ops *ops) ++{ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ memset(chip->oobbuf, 0xff, chip->page_spare_size); ++ ++ switch (ops->mode) { ++ ++ case MTD_OOB_PLACE: ++ case MTD_OOB_RAW: ++ memcpy(chip->oobbuf + ops->ooboffs, oob, len); ++ return; ++ ++ case MTD_OOB_AUTO: { ++ struct nand_oobfree *free = chip->ecclayout->oobfree; ++ uint32_t boffs = 0, woffs = ops->ooboffs; ++ size_t bytes = 0; ++ ++ for (; free->length && len; free++, len -= bytes) { ++ /* Write request not from offset 0? */ ++ if (unlikely(woffs)) { ++ if (woffs >= free->length) { ++ woffs -= free->length; ++ continue; ++ } ++ boffs = free->offset + woffs; ++ bytes = min_t(size_t, len, ++ (free->length - woffs)); ++ woffs = 0; ++ } else { ++ bytes = min_t(size_t, len, free->length); ++ boffs = free->offset; ++ } ++ memcpy(chip->oobbuf + boffs, oob, bytes); ++ oob += bytes; ++ } ++ return; ++ } ++ default: ++ BUG(); ++ } ++} ++ ++/** ++ * spi_nand_do_read_ops - [INTERN] Read data with ECC ++ * @mtd: MTD device structure ++ * @from: offset to read from ++ * @ops: oob ops structure ++ * ++ * Internal function. Called with chip held. ++ */ ++static int spi_nand_do_read_ops(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int page_addr, page_offset, size; ++ int ret; ++ unsigned int corrected = 0; ++ struct mtd_ecc_stats stats; ++ unsigned int max_bitflips = 0; ++ int readlen = ops->len; ++ int oobreadlen = ops->ooblen; ++ int ooblen = ops->mode == MTD_OOB_AUTO ? ++ mtd->oobavail : mtd->oobsize; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ /* Do not allow reads past end of device */ ++ if (unlikely(from >= mtd->size)) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ stats = mtd->ecc_stats; ++ ++ page_addr = from >> chip->page_shift; ++ ++ /* for main data */ ++ page_offset = from & chip->page_mask; ++ ops->retlen = 0; ++ ++ /* for oob */ ++ if (oobreadlen > 0) { ++ if (unlikely(ops->ooboffs >= ooblen)) { ++ pr_debug("%s: attempt to start read outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(ops->ooboffs + oobreadlen > ++ ((mtd->size >> chip->page_shift) - (from >> chip->page_shift)) ++ * ooblen)) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ooblen -= ops->ooboffs; ++ ops->oobretlen = 0; ++ } ++ ++ while (1) { ++ if (page_addr != chip->pagebuf || oobreadlen > 0) { ++ ret = spi_nand_do_read_page(mtd, page_addr, ++ ops->mode == MTD_OOB_RAW, &corrected); ++ if (ret) { ++ pr_debug("error %d reading page 0x%x\n", ++ ret, page_addr); ++ return ret; ++ } ++ chip->pagebuf_bitflips = corrected; ++ chip->pagebuf = page_addr; ++ } ++ max_bitflips = max(max_bitflips, chip->pagebuf_bitflips); ++ size = min(readlen, chip->page_size - page_offset); ++ memcpy(ops->datbuf + ops->retlen, ++ chip->buf + page_offset, size); ++ ++ ops->retlen += size; ++ readlen -= size; ++ page_offset = 0; ++ ++ if (unlikely(ops->oobbuf)) { ++ size = min(oobreadlen, ooblen); ++ spi_nand_transfer_oob(chip, ++ ops->oobbuf + ops->oobretlen, ops, size); ++ ++ ops->oobretlen += size; ++ oobreadlen -= size; ++ } ++ if (!readlen) ++ break; ++ ++ page_addr++; ++ } ++ ++ if (mtd->ecc_stats.failed - stats.failed) ++ return -EBADMSG; ++ ++ return max_bitflips; ++} ++ ++/** ++ * spi_nand_do_write_ops - [INTERN] SPI-NAND write with ECC ++ * @mtd: MTD device structure ++ * @to: offset to write to ++ * @ops: oob operations description structure ++ * ++ */ ++static int spi_nand_do_write_ops(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int page_addr, page_offset, size; ++ int writelen = ops->len; ++ int oobwritelen = ops->ooblen; ++ int ret; ++ int ooblen = ops->mode == MTD_OOB_AUTO ? ++ mtd->oobavail : mtd->oobsize; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ /* Do not allow reads past end of device */ ++ if (unlikely(to >= mtd->size)) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ page_addr = to >> chip->page_shift; ++ ++ /* for main data */ ++ page_offset = to & chip->page_mask; ++ ops->retlen = 0; ++ ++ /* for oob */ ++ if (oobwritelen > 0) { ++ /* Do not allow write past end of page */ ++ if ((ops->ooboffs + oobwritelen) > ooblen) { ++ pr_debug("%s: attempt to write past end of page\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(ops->ooboffs >= ooblen)) { ++ pr_debug("%s: attempt to start write outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(ops->ooboffs + oobwritelen > ++ ((mtd->size >> chip->page_shift) - (to >> chip->page_shift)) ++ * ooblen)) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ooblen -= ops->ooboffs; ++ ops->oobretlen = 0; ++ } ++ ++ chip->pagebuf = -1; ++ ++ while (1) { ++ memset(chip->buf, 0xFF, ++ chip->page_size + chip->page_spare_size); ++ ++ size = min(writelen, chip->page_size - page_offset); ++ memcpy(chip->buf + page_offset, ++ ops->datbuf + ops->retlen, size); ++ ++ ops->retlen += size; ++ writelen -= size; ++ page_offset = 0; ++ ++ if (unlikely(ops->oobbuf)) { ++ size = min(oobwritelen, ooblen); ++ ++ spi_nand_fill_oob(chip, ops->oobbuf + ops->oobretlen, ++ size, ops); ++ ++ ops->oobretlen += size; ++ oobwritelen -= size; ++ } ++ ret = spi_nand_do_write_page(mtd, page_addr, ++ ops->mode == MTD_OOB_RAW); ++ if (ret) { ++ pr_debug("error %d writing page 0x%x\n", ++ ret, page_addr); ++ return ret; ++ } ++ if (!writelen) ++ break; ++ page_addr++; ++ } ++ return 0; ++} ++ ++/** ++ * nand_read - [MTD Interface] SPI-NAND read ++ * @mtd: MTD device structure ++ * @from: offset to read from ++ * @len: number of bytes to read ++ * @retlen: pointer to variable to store the number of read bytes ++ * @buf: the databuffer to put data ++ * ++ */ ++static int spi_nand_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ struct mtd_oob_ops ops = { 0 }; ++ int ret; ++ ++ spi_nand_get_device(mtd, FL_READING); ++ ++ ops.len = len; ++ ops.datbuf = buf; ++ ret = spi_nand_do_read_ops(mtd, from, &ops); ++ ++ *retlen = ops.retlen; ++ ++ spi_nand_release_device(mtd); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_write - [MTD Interface] SPI-NAND write ++ * @mtd: MTD device structure ++ * @to: offset to write to ++ * @len: number of bytes to write ++ * @retlen: pointer to variable to store the number of written bytes ++ * @buf: the data to write ++ * ++ */ ++static int spi_nand_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ struct mtd_oob_ops ops = {0}; ++ int ret; ++ ++ spi_nand_get_device(mtd, FL_WRITING); ++ ++ ops.len = len; ++ ops.datbuf = (uint8_t *)buf; ++ ++ ++ ret = spi_nand_do_write_ops(mtd, to, &ops); ++ ++ *retlen = ops.retlen; ++ ++ spi_nand_release_device(mtd); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_do_read_oob - [INTERN] SPI-NAND read out-of-band ++ * @mtd: MTD device structure ++ * @from: offset to read from ++ * @ops: oob operations description structure ++ * ++ * SPI-NAND read out-of-band data from the spare area. ++ */ ++static int spi_nand_do_read_oob(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int page_addr; ++ int corrected = 0; ++ struct mtd_ecc_stats stats; ++ int readlen = ops->ooblen; ++ int len; ++ int ret = 0; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ pr_debug("%s: from = 0x%08Lx, len = %i\n", ++ __func__, (unsigned long long)from, readlen); ++ ++ stats = mtd->ecc_stats; ++ ++ len = ops->mode == MTD_OOB_AUTO ? mtd->oobavail : mtd->oobsize; ++ ++ if (unlikely(ops->ooboffs >= len)) { ++ pr_debug("%s: attempt to start read outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ /* Do not allow reads past end of device */ ++ if (unlikely(from >= mtd->size || ++ ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) - ++ (from >> chip->page_shift)) * len)) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ /* Shift to get page */ ++ page_addr = (from >> chip->page_shift); ++ len -= ops->ooboffs; ++ ops->oobretlen = 0; ++ ++ while (1) { ++ /*read data from chip*/ ++ ret = spi_nand_do_read_page_oob(mtd, page_addr, ++ ops->mode == MTD_OOB_RAW, &corrected); ++ if (ret) { ++ pr_debug("error %d reading page 0x%x\n", ++ ret, page_addr); ++ return ret; ++ } ++ if (page_addr == chip->pagebuf) ++ chip->pagebuf = -1; ++ ++ len = min(len, readlen); ++ spi_nand_transfer_oob(chip, ops->oobbuf + ops->oobretlen, ++ ops, len); ++ ++ readlen -= len; ++ ops->oobretlen += len; ++ if (!readlen) ++ break; ++ ++ page_addr++; ++ } ++ ++ if (ret < 0) ++ return ret; ++ ++ if (mtd->ecc_stats.failed - stats.failed) ++ return -EBADMSG; ++ ++ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; ++} ++ ++/** ++ * spi_nand_do_write_oob - [MTD Interface] SPI-NAND write out-of-band ++ * @mtd: MTD device structure ++ * @to: offset to write to ++ * @ops: oob operation description structure ++ * ++ * SPI-NAND write out-of-band. ++ */ ++static int spi_nand_do_write_oob(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ int page_addr, len, ret; ++ struct spi_nand_chip *chip = mtd->priv; ++ int writelen = ops->ooblen; ++ ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ pr_debug("%s: to = 0x%08x, len = %i\n", ++ __func__, (unsigned int)to, (int)writelen); ++ ++ len = ops->mode == MTD_OOB_AUTO ? mtd->oobavail : mtd->oobsize; ++ ++ /* Do not allow write past end of page */ ++ if ((ops->ooboffs + writelen) > len) { ++ pr_debug("%s: attempt to write past end of page\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (unlikely(ops->ooboffs >= len)) { ++ pr_debug("%s: attempt to start write outside oob\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ /* Do not allow write past end of device */ ++ if (unlikely(to >= mtd->size || ++ ops->ooboffs + writelen > ++ ((mtd->size >> chip->page_shift) - ++ (to >> chip->page_shift)) * len)) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ /* Shift to get page */ ++ page_addr = to >> chip->page_shift; ++ /* Invalidate the page cache, if we write to the cached page */ ++ if (page_addr == chip->pagebuf) ++ chip->pagebuf = -1; ++ ++ spi_nand_fill_oob(chip, ops->oobbuf, writelen, ops); ++ ++ ret = spi_nand_do_write_page_oob(mtd, page_addr, ++ ops->mode == MTD_OOB_RAW); ++ if (ret) { ++ pr_debug("error %d writing page 0x%x\n", ++ ret, page_addr); ++ return ret; ++ } ++ ops->oobretlen = writelen; ++ ++ return 0; ++} ++ ++/** ++ * spi_nand_read_oob - [MTD Interface] SPI-NAND read data and/or out-of-band ++ * @mtd: MTD device structure ++ * @from: offset to read from ++ * @ops: oob operation description structure ++ * ++ * SPI-NAND read data and/or out-of-band data. ++ */ ++static int spi_nand_read_oob(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ int ret = -ENOTSUPP; ++ ++ struct spi_nand_chip *this = mtd->priv; ++ fh_dev_debug(&this->spi->dev, "Enter %s, from 0x%08llx \n", __func__, from); ++ ops->retlen = 0; ++ ++ /* Do not allow reads past end of device */ ++ if (ops->datbuf && (from + ops->len) > mtd->size) { ++ pr_debug("%s: attempt to read beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ spi_nand_get_device(mtd, FL_READING); ++ ++ switch (ops->mode) { ++ case MTD_OOB_PLACE: ++ case MTD_OOB_AUTO: ++ case MTD_OOB_RAW: ++ break; ++ ++ default: ++ goto out; ++ } ++ ++ if (!ops->datbuf) ++ ret = spi_nand_do_read_oob(mtd, from, ops); ++ else ++ ret = spi_nand_do_read_ops(mtd, from, ops); ++ ++out: ++ spi_nand_release_device(mtd); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_write_oob - [MTD Interface] SPI-NAND write data and/or out-of-band ++ * @mtd: MTD device structure ++ * @to: offset to write to ++ * @ops: oob operation description structure ++ */ ++static int spi_nand_write_oob(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ int ret = -ENOTSUPP; ++ struct spi_nand_chip *this = mtd->priv; ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ ++ ops->retlen = 0; ++ ++ /* Do not allow writes past end of device */ ++ if (ops->datbuf && (to + ops->len) > mtd->size) { ++ pr_debug("%s: attempt to write beyond end of device\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ spi_nand_get_device(mtd, FL_WRITING); ++ ++ switch (ops->mode) { ++ case MTD_OOB_PLACE: ++ case MTD_OOB_AUTO: ++ case MTD_OOB_RAW: ++ break; ++ ++ default: ++ goto out; ++ } ++ ++ if (!ops->datbuf) ++ ret = spi_nand_do_write_oob(mtd, to, ops); ++ else ++ ret = spi_nand_do_write_ops(mtd, to, ops); ++ ++out: ++ spi_nand_release_device(mtd); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_block_bad - [INTERN] Check if block at offset is bad ++ * @mtd: MTD device structure ++ * @offs: offset relative to mtd start ++ */ ++static int spi_nand_block_bad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ struct mtd_oob_ops ops = {0}; ++ u32 block_addr; ++ u8 bad[2] = {0, 0}; ++ u8 ret = 0; ++ ++ block_addr = ofs >> chip->block_shift; ++ ops.mode = MTD_OOB_PLACE; ++ ops.ooblen = 2; ++ ops.oobbuf = bad; ++ ++ ret = spi_nand_do_read_oob(mtd, block_addr << chip->block_shift, &ops); ++ if (bad[0] != 0xFF || bad[1] != 0xFF) ++ ret = 1; ++ ++ return ret; ++ ++} ++ ++/** ++ * spi_nand_block_checkbad - [GENERIC] Check if a block is marked bad ++ * @mtd: MTD device structure ++ * @ofs: offset from device start ++ * @allowbbt: 1, if its allowed to access the bbt area ++ * ++ * Check, if the block is bad. Either by reading the bad block table or ++ * calling of the scan function. ++ */ ++static int spi_nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, ++ int allowbbt) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ if (!chip->bbt) ++ return spi_nand_block_bad(mtd, ofs); ++ ++ /* Return info from the table */ ++ return spi_nand_isbad_bbt(mtd, ofs, allowbbt); ++} ++ ++/** ++ * spi_nand_block_isbad - [MTD Interface] Check if block at offset is bad ++ * @mtd: MTD device structure ++ * @offs: offset relative to mtd start ++ */ ++static int spi_nand_block_isbad(struct mtd_info *mtd, loff_t offs) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ return chip->block_bad(mtd, offs, 0); ++} ++ ++/** ++ * spi_nand_block_markbad_lowlevel - mark a block bad ++ * @mtd: MTD device structure ++ * @ofs: offset from device start ++ * ++ * This function performs the generic bad block marking steps (i.e., bad ++ * block table(s) and/or marker(s)). We only allow the hardware driver to ++ * specify how to write bad block markers to OOB (chip->block_markbad). ++ * ++ * We try operations in the following order: ++ * (1) erase the affected block, to allow OOB marker to be written cleanly ++ * (2) write bad block marker to OOB area of affected block (unless flag ++ * NAND_BBT_NO_OOB_BBM is present) ++ * (3) update the BBT ++ * Note that we retain the first error encountered in (2) or (3), finish the ++ * procedures, and dump the error in the end. ++*/ ++static int spi_nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ struct mtd_oob_ops ops = {0}; ++ struct erase_info einfo = {0}; ++ u32 block_addr; ++ u8 buf[2] = {0, 0}; ++ int res, ret = 0; ++ ++ if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { ++ /*erase bad block before mark bad block*/ ++ einfo.mtd = mtd; ++ einfo.addr = ofs; ++ einfo.len = 1UL << chip->block_shift; ++ spi_nand_erase(mtd, &einfo); ++ ++ block_addr = ofs >> chip->block_shift; ++ ops.mode = MTD_OOB_PLACE; ++ ops.ooblen = 2; ++ ops.oobbuf = buf; ++ ++ ret = spi_nand_do_write_oob(mtd, ++ block_addr << chip->block_shift, &ops); ++ } ++ ++ /* Mark block bad in BBT */ ++ if (chip->bbt) { ++ res = spi_nand_markbad_bbt(mtd, ofs); ++ if (!ret) ++ ret = res; ++ } ++ ++ if (!ret) ++ mtd->ecc_stats.badblocks++; ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_block_markbad - [MTD Interface] Mark block at the given offset ++ * as bad ++ * @mtd: MTD device structure ++ * @ofs: offset relative to mtd start ++ */ ++static int spi_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) ++{ ++ int ret; ++ ++ ret = spi_nand_block_isbad(mtd, ofs); ++ if (ret) { ++ /* If it was bad already, return success and do nothing */ ++ if (ret > 0) ++ return 0; ++ return ret; ++ } ++ ++ return spi_nand_block_markbad_lowlevel(mtd, ofs); ++} ++ ++/** ++ * __spi_nand_erase - [INTERN] erase block(s) ++ * @mtd: MTD device structure ++ * @einfo: erase instruction ++ * @allowbbt: allow to access bbt ++ * ++ * Erase one ore more blocks ++ */ ++int __spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo, ++ int allowbbt) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int page_addr, pages_per_block; ++ loff_t len; ++ u8 status; ++ int ret = 0; ++ ++ ++ /* check address align on block boundary */ ++ if (einfo->addr & (chip->block_size - 1)) { ++ pr_debug("%s: Unaligned address\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (einfo->len & (chip->block_size - 1)) { ++ pr_debug("%s: Length not block aligned\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Do not allow erase past end of device */ ++ if ((einfo->len + einfo->addr) > chip->size) { ++ pr_debug("%s: Erase past end of device\n", __func__); ++ return -EINVAL; ++ } ++ ++ einfo->fail_addr = MTD_FAIL_ADDR_UNKNOWN; ++ ++ /* Grab the lock and see if the device is available */ ++ spi_nand_get_device(mtd, FL_ERASING); ++ ++ pages_per_block = 1 << (chip->block_shift - chip->page_shift); ++ page_addr = einfo->addr >> chip->page_shift; ++ len = einfo->len; ++ ++ einfo->state = MTD_ERASING; ++ ++ while (len) { ++ /* Check if we have a bad block, we do not erase bad blocks! */ ++ if (chip->block_bad(mtd, ((loff_t) page_addr) << ++ chip->page_shift, allowbbt)) { ++ pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", ++ __func__, page_addr); ++ einfo->state = MTD_ERASE_FAILED; ++ goto erase_exit; ++ } ++ /* ++ * Invalidate the page cache, if we erase the block which ++ * contains the current cached page. ++ */ ++ if (page_addr <= chip->pagebuf && chip->pagebuf < ++ (page_addr + pages_per_block)) ++ chip->pagebuf = -1; ++ ++ ret = chip->write_enable(chip); ++ if (ret < 0) { ++ pr_debug("write enable command failed\n"); ++ einfo->state = MTD_ERASE_FAILED; ++ goto erase_exit; ++ } ++ ++ ret = chip->erase_block(chip, page_addr); ++ if (ret < 0) { ++ pr_debug("block erase command failed\n"); ++ einfo->state = MTD_ERASE_FAILED; ++ einfo->fail_addr = (loff_t)page_addr ++ << chip->page_shift; ++ goto erase_exit; ++ } ++ ret = chip->waitfunc(chip, &status); ++ if (ret < 0) { ++ pr_debug("block erase command wait failed\n"); ++ einfo->state = MTD_ERASE_FAILED; ++ goto erase_exit; ++ } ++ if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) { ++ pr_debug("erase block 0x%012llx failed\n", ++ ((loff_t) page_addr) << chip->page_shift); ++ einfo->state = MTD_ERASE_FAILED; ++ einfo->fail_addr = (loff_t)page_addr ++ << chip->page_shift; ++ goto erase_exit; ++ } ++ ++ /* Increment page address and decrement length */ ++ len -= (1ULL << chip->block_shift); ++ page_addr += pages_per_block; ++ } ++ ++ einfo->state = MTD_ERASE_DONE; ++ ++erase_exit: ++ ++ ret = einfo->state == MTD_ERASE_DONE ? 0 : -EIO; ++ ++ spi_nand_release_device(mtd); ++ ++ /* Do call back function */ ++ if (!ret) ++ mtd_erase_callback(einfo); ++ ++ /* Return more or less happy */ ++ return ret; ++} ++EXPORT_SYMBOL(__spi_nand_erase); ++ ++/** ++ * spi_nand_erase - [MTD Interface] erase block(s) ++ * @mtd: MTD device structure ++ * @einfo: erase instruction ++ * ++ * Erase one ore more blocks ++ */ ++static int spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo) ++{ ++ return __spi_nand_erase(mtd, einfo, 0); ++} ++ ++/** ++ * spi_nand_sync - [MTD Interface] sync ++ * @mtd: MTD device structure ++ * ++ * Sync is actually a wait for chip ready function ++ */ ++static void spi_nand_sync(struct mtd_info *mtd) ++{ ++ pr_debug("spi_nand_sync: called\n"); ++ ++ /* Grab the lock and see if the device is available */ ++ spi_nand_get_device(mtd, FL_SYNCING); ++ ++ /* Release it and go back */ ++ spi_nand_release_device(mtd); ++} ++ ++/** ++ * spi_nand_suspend - [MTD Interface] Suspend the SPI-NAND flash ++ * @mtd: MTD device structure ++ */ ++static int spi_nand_suspend(struct mtd_info *mtd) ++{ ++ return spi_nand_get_device(mtd, FL_PM_SUSPENDED); ++} ++ ++/** ++ * spi_nand_resume - [MTD Interface] Resume the SPI-NAND flash ++ * @mtd: MTD device structure ++ */ ++static void spi_nand_resume(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ ++ if (this->state == FL_PM_SUSPENDED) ++ spi_nand_release_device(mtd); ++ else ++ pr_err("%s is not called in suspended state\n:", __func__); ++} ++ ++ ++/* ++ * spi_nand_send_cmd - to process a command to send to the SPI-NAND ++ * @spi: spi device structure ++ * @cmd: command structure ++ * ++ * Set up the command buffer to send to the SPI controller. ++ * The command buffer has to initialized to 0. ++ */ ++int spi_nand_send_cmd(struct spi_device *spi, struct spi_nand_cmd *cmd) ++{ ++ struct spi_message message; ++ struct spi_transfer x[4]; ++ u8 buf[8], i; ++ u32 buflen = 0; ++ ++ spi_message_init(&message); ++ memset(x, 0, sizeof(x)); ++ x[0].len = 1; ++ x[0].tx_buf = &cmd->cmd; ++ x[0].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ spi_message_add_tail(&x[0], &message); ++ ++ buf[buflen++] = cmd->cmd; ++ ++ if (cmd->n_addr) { ++ x[1].len = cmd->n_addr; ++ x[1].tx_buf = cmd->addr; ++ spi_message_add_tail(&x[1], &message); ++ x[1].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ } ++ for (i = 0; i < cmd->n_addr && buflen < 7; i++) ++ buf[buflen++] = cmd->addr[i]; ++ ++ if (cmd->n_tx) { ++ x[2].len = cmd->n_tx; ++ /*x[2].tx_nbits = cmd->tx_nbits; always 0 for single future version*/ ++ x[2].tx_buf = cmd->tx_buf; ++ x[2].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ spi_message_add_tail(&x[2], &message); ++ } ++ for (i = 0; i < cmd->n_tx && buflen < 7; i++) ++ buf[buflen++] = cmd->tx_buf[i]; ++ ++ if (cmd->n_rx) { ++ x[3].len = cmd->n_rx; ++ /*x[3].rx_nbits = cmd->rx_nbits;*/ ++ x[3].rx_buf = cmd->rx_buf; ++ if (cmd->cmd == SPINAND_CMD_READ_CACHE_X4) ++ x[3].xfer_wire_mode = QUAD_WIRE_SUPPORT; ++ else if (cmd->cmd == SPINAND_CMD_READ_CACHE_X2) ++ x[3].xfer_wire_mode = DUAL_WIRE_SUPPORT; ++ else ++ x[3].xfer_wire_mode = ONE_WIRE_SUPPORT; ++ spi_message_add_tail(&x[3], &message); ++ } ++ for (i = 0; i < cmd->n_rx && buflen < 7; i++) ++ buf[buflen++] = cmd->rx_buf[i]; ++ ++ buflen = 1 + cmd->n_addr + cmd->n_tx + cmd->n_rx; ++ if (fh_start_debug || cmd->cmd == 0x1f) ++ fh_dev_debug(&spi->dev, " spi%d:%d: send cmd 0x: %02x %02x %02x %02x %02x %02x, size %d\n", ++ spi->master->bus_num, spi->chip_select, ++ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buflen); ++ ++ return spi_sync(spi, &message); ++} ++EXPORT_SYMBOL(spi_nand_send_cmd); ++/* ++ * spi_nand_read_status- send command 0x0f to the SPI-NAND status register value ++ * @spi: spi device structure ++ * @status: buffer to store value ++ * Description: ++ * After read, write, or erase, the Nand device is expected to set the ++ * busy status. ++ * This function is to allow reading the status of the command: read, ++ * write, and erase. ++ * Once the status turns to be ready, the other status bits also are ++ * valid status bits. ++ */ ++static int spi_nand_read_status(struct spi_device *spi, uint8_t *status) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ int ret; ++ ++ cmd.cmd = SPINAND_CMD_READ_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = REG_STATUS; ++ cmd.n_rx = 1; ++ cmd.rx_buf = status; ++ ++ ret = spi_nand_send_cmd(spi, &cmd); ++ if (ret < 0) ++ dev_err(&spi->dev, "err: %d read status register\n", ret); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_get_otp- send command 0x0f to read the SPI-NAND OTP register ++ * @spi: spi device structure ++ * @opt: buffer to store value ++ * Description: ++ * There is one bit( bit 0x10 ) to set or to clear the internal ECC. ++ * Enable chip internal ECC, set the bit to 1 ++ * Disable chip internal ECC, clear the bit to 0 ++ */ ++static int spi_nand_get_otp(struct spi_device *spi, u8 *otp) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ int ret; ++ ++ cmd.cmd = SPINAND_CMD_READ_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = REG_OTP; ++ cmd.n_rx = 1; ++ cmd.rx_buf = otp; ++ ++ ret = spi_nand_send_cmd(spi, &cmd); ++ if (ret < 0) ++ dev_err(&spi->dev, "error %d get otp\n", ret); ++ return ret; ++} ++ ++/** ++ * spi_nand_set_otp- send command 0x1f to write the SPI-NAND OTP register ++ * @spi: spi device structure ++ * @status: buffer stored value ++ * Description: ++ * There is one bit( bit 0x10 ) to set or to clear the internal ECC. ++ * Enable chip internal ECC, set the bit to 1 ++ * Disable chip internal ECC, clear the bit to 0 ++ */ ++static int spi_nand_set_otp(struct spi_device *spi, u8 *otp) ++{ ++ int ret; ++ struct spi_nand_cmd cmd = { 0 }; ++ ++ cmd.cmd = SPINAND_CMD_WRITE_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = REG_OTP; ++ cmd.n_tx = 1; ++ cmd.tx_buf = otp; ++ ++ ret = spi_nand_send_cmd(spi, &cmd); ++ if (ret < 0) ++ dev_err(&spi->dev, "error %d set otp\n", ret); ++ ++ return ret; ++} ++ ++/** ++ * spi_nand_enable_ecc- enable internal ECC ++ * @chip: SPI-NAND device structure ++ * Description: ++ * There is one bit( bit 0x10 ) to set or to clear the internal ECC. ++ * Enable chip internal ECC, set the bit to 1 ++ * Disable chip internal ECC, clear the bit to 0 ++ */ ++static int spi_nand_enable_ecc(struct spi_nand_chip *chip) ++{ ++ struct spi_device *spi = chip->spi; ++ int ret; ++ u8 otp = 0; ++ ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ ret = spi_nand_get_otp(spi, &otp); ++ if (ret < 0) ++ return ret; ++ ++ fh_dev_debug(&spi->dev, "get opt: 0x%02x\n", otp); ++ if ((otp & OTP_ECC_MASK) == OTP_ECC_ENABLE) ++ return 0; ++ ++ otp |= OTP_ECC_ENABLE; ++ ret = spi_nand_set_otp(spi, &otp); ++ if (ret < 0) ++ return ret; ++ fh_dev_debug(&spi->dev, "set opt: 0x%02x\n", otp); ++ return spi_nand_get_otp(spi, &otp); ++} ++ ++static int spi_nand_get_qe_value(struct spi_nand_chip *chip, u8 *otp) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ int ret; ++ ++ cmd.cmd = SPINAND_CMD_READ_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = chip->qe_addr; ++ cmd.n_rx = 1; ++ cmd.rx_buf = otp; ++ ++ ret = spi_nand_send_cmd(chip->spi, &cmd); ++ return ret; ++} ++ ++static int spi_nand_set_qe_value(struct spi_nand_chip *chip, u8 *otp) ++{ ++ int ret; ++ struct spi_nand_cmd cmd = { 0 }; ++ ++ cmd.cmd = SPINAND_CMD_WRITE_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = chip->qe_addr; ++ cmd.n_tx = 1; ++ cmd.tx_buf = otp; ++ ++ ret = spi_nand_send_cmd(chip->spi, &cmd); ++ return ret; ++} ++ ++ ++ ++static int spi_nand_set_qe(struct spi_nand_chip *chip) ++{ ++ int ret; ++ u8 otp = 0; ++ ++ ret = spi_nand_get_qe_value(chip, &otp); ++ if (ret < 0) ++ return ret; ++ ++ if (chip->qe_flag) ++ otp |= chip->qe_mask; ++ else ++ otp &= (~chip->qe_mask); ++ ret = spi_nand_set_qe_value(chip, &otp); ++ if (ret < 0) ++ return ret; ++ return spi_nand_get_qe_value(chip, &otp); ++} ++ ++ ++/** ++ * spi_nand_disable_ecc- disable internal ECC ++ * @chip: SPI-NAND device structure ++ * Description: ++ * There is one bit( bit 0x10 ) to set or to clear the internal ECC. ++ * Enable chip internal ECC, set the bit to 1 ++ * Disable chip internal ECC, clear the bit to 0 ++ */ ++static int spi_nand_disable_ecc(struct spi_nand_chip *chip) ++{ ++ struct spi_device *spi = chip->spi; ++ int ret; ++ u8 otp = 0; ++ ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ret = spi_nand_get_otp(spi, &otp); ++ if (ret < 0) ++ return ret; ++ ++ if ((otp & OTP_ECC_MASK) == OTP_ECC_ENABLE) { ++ otp &= ~OTP_ECC_ENABLE; ++ ret = spi_nand_set_otp(spi, &otp); ++ if (ret < 0) ++ return ret; ++ return spi_nand_get_otp(spi, &otp); ++ } else ++ return 0; ++} ++ ++/** ++ * spi_nand_write_enable- send command 0x06 to enable write or erase the ++ * Nand cells ++ * @chip: SPI-NAND device structure ++ * Description: ++ * Before write and erase the Nand cells, the write enable has to be set. ++ * After the write or erase, the write enable bit is automatically ++ * cleared (status register bit 2) ++ * Set the bit 2 of the status register has the same effect ++ */ ++static int spi_nand_write_enable(struct spi_nand_chip *chip) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_WR_ENABLE; ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++/* ++ * spi_nand_read_from_cache- send command 0x13 to read data from Nand to cache ++ * @chip: SPI-NAND device structure ++ * @page_addr: page to read ++ */ ++static int spi_nand_read_page_to_cache(struct spi_nand_chip *chip, ++ u32 page_addr) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_READ; ++ cmd.n_addr = 3; ++ cmd.addr[0] = (u8)(page_addr >> 16); ++ cmd.addr[1] = (u8)(page_addr >> 8); ++ cmd.addr[2] = (u8)page_addr; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++/* ++ * spi_nand_read_from_cache- send command 0x03 to read out the data from the ++ * cache register ++ * Description: ++ * The read can specify 1 to (page size + spare size) bytes of data read at ++ * the corresponding locations. ++ * No tRd delay. ++ */ ++int spi_nand_read_from_cache(struct spi_nand_chip *chip, u32 page_addr, ++ u32 column, size_t len, u8 *rbuf) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ /*cmd.cmd = SPINAND_CMD_READ_RDM;*/ ++ cmd.n_addr = 3; ++ if (spi->dev_open_multi_wire_flag & QUAD_WIRE_SUPPORT) { ++ cmd.cmd = SPINAND_CMD_READ_CACHE_X4; ++ if (chip->multi_wire_command_length == 5) ++ cmd.n_addr = 4; ++ } else if (spi->dev_open_multi_wire_flag & DUAL_WIRE_SUPPORT) { ++ cmd.cmd = SPINAND_CMD_READ_CACHE_X2; ++ if (chip->multi_wire_command_length == 5) ++ cmd.n_addr = 4; ++ } else ++ cmd.cmd = SPINAND_CMD_READ_RDM; ++ if (chip->dev_id[0] == 0xC8) {/*FIXME: early GD chips, test 1G*/ ++ cmd.addr[0] = 0; ++ cmd.addr[1] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[0] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[2] = (u8)column; ++ } ++ else{ ++ cmd.addr[0] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[0] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[1] = (u8)column; ++ cmd.addr[2] = 0; ++ } ++ cmd.n_rx = len; ++ cmd.rx_buf = rbuf; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++/* ++ * spi_nand_read_from_cache_x2- send command 0x3b to read out the data from the ++ * cache register ++ * Description: ++ * The read can specify 1 to (page size + spare size) bytes of data read at ++ * the corresponding locations. ++ * No tRd delay. ++ */ ++/*int spi_nand_read_from_cache_x2(struct spi_nand_chip *chip, u32 page_addr, ++ u32 column, size_t len, u8 *rbuf) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ ++ cmd.cmd = SPINAND_CMD_READ_CACHE_X2; ++ cmd.n_addr = 3; ++ cmd.addr[0] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[0] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[1] = (u8)column; ++ cmd.addr[2] = 0; ++ cmd.n_rx = len; ++ cmd.rx_nbits = SPI_NBITS_DUAL; ++ cmd.rx_buf = rbuf; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++}*/ ++ ++/* ++ * spi_nand_read_from_cache_x4- send command 0x6b to read out the data from the ++ * cache register ++ * Description: ++ * The read can specify 1 to (page size + spare size) bytes of data read at ++ * the corresponding locations. ++ * No tRd delay. ++ */ ++/*int spi_nand_read_from_cache_x4(struct spi_nand_chip *chip, u32 page_addr, ++ u32 column, size_t len, u8 *rbuf) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ ++ cmd.cmd = SPINAND_CMD_READ_CACHE_X4; ++ cmd.n_addr = 3; ++ cmd.addr[0] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[0] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[1] = (u8)column; ++ cmd.addr[2] = 0; ++ cmd.n_rx = len; ++ cmd.rx_nbits = SPI_NBITS_QUAD; ++ cmd.rx_buf = rbuf; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++}*/ ++ ++/* ++ * spi_nand_read_from_cache_snor_protocol- send command 0x03 to read out the ++ * data from the cache register, 0x03 command protocol is same as SPI NOR ++ * read command ++ * Description: ++ * The read can specify 1 to (page size + spare size) bytes of data read at ++ * the corresponding locations. ++ * No tRd delay. ++ */ ++int spi_nand_read_from_cache_snor_protocol(struct spi_nand_chip *chip, ++ u32 page_addr, u32 column, size_t len, u8 *rbuf) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_READ_RDM; ++ cmd.n_addr = 3; ++ cmd.addr[0] = 0; ++ cmd.addr[1] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[1] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[2] = (u8)column; ++ cmd.n_rx = len; ++ cmd.rx_buf = rbuf; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++EXPORT_SYMBOL(spi_nand_read_from_cache_snor_protocol); ++ ++/* ++ * spi_nand_program_data_to_cache--to write a page to cache ++ * @chip: SPI-NAND device structure ++ * @page_addr: page to write ++ * @column: the location to write to the cache ++ * @len: number of bytes to write ++ * wrbuf: buffer held @len bytes ++ * ++ * Description: ++ * The write command used here is 0x02--indicating that the cache is ++ * cleared first. ++ * Since it is writing the data to cache, there is no tPROG time. ++ */ ++static int spi_nand_program_data_to_cache(struct spi_nand_chip *chip, ++ u32 page_addr, u32 column, size_t len, u8 *wbuf) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_PROG_LOAD; ++ cmd.n_addr = 2; ++ cmd.addr[0] = (u8)(column >> 8); ++ if (chip->options & SPINAND_NEED_PLANE_SELECT) ++ cmd.addr[0] |= (u8)(((page_addr >> ++ (chip->block_shift - chip->page_shift)) & 0x1) << 4); ++ cmd.addr[1] = (u8)column; ++ cmd.n_tx = len; ++ cmd.tx_buf = wbuf; ++ fh_dev_debug(&spi->dev, "see n_tx %d, oob[4] 0x%08x\n", ++ len, *(uint32_t*)(wbuf+2048)); ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++/** ++ * spi_nand_program_execute--to write a page from cache to the Nand array ++ * @chip: SPI-NAND device structure ++ * @page_addr: the physical page location to write the page. ++ * ++ * Description: ++ * The write command used here is 0x10--indicating the cache is writing to ++ * the Nand array. ++ * Need to wait for tPROG time to finish the transaction. ++ */ ++static int spi_nand_program_execute(struct spi_nand_chip *chip, u32 page_addr) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ cmd.cmd = SPINAND_CMD_PROG; ++ cmd.n_addr = 3; ++ cmd.addr[0] = (u8)(page_addr >> 16); ++ cmd.addr[1] = (u8)(page_addr >> 8); ++ cmd.addr[2] = (u8)page_addr; ++ ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++ ++/** ++ * spi_nand_erase_block_erase--to erase a block ++ * @chip: SPI-NAND device structure ++ * @page_addr: the page to erase. ++ * ++ * Description: ++ * The command used here is 0xd8--indicating an erase command to erase ++ * one block ++ * Need to wait for tERS. ++ */ ++static int spi_nand_erase_block(struct spi_nand_chip *chip, ++ u32 page_addr) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_ERASE_BLK; ++ cmd.n_addr = 3; ++ cmd.addr[0] = (u8)(page_addr >> 16); ++ cmd.addr[1] = (u8)(page_addr >> 8); ++ cmd.addr[2] = (u8)page_addr; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++/** ++ * spi_nand_wait - [DEFAULT] wait until the command is done ++ * @chip: SPI-NAND device structure ++ * @s: buffer to store status register(can be NULL) ++ * ++ * Wait for command done. This applies to erase and program only. Erase can ++ * take up to 400ms and program up to 20ms. ++ */ ++static int spi_nand_wait(struct spi_nand_chip *chip, u8 *s) ++{ ++ unsigned long timeo = jiffies; ++ u8 status, state = chip->state; ++ int ret = -ETIMEDOUT; ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ if (state == FL_ERASING) ++ timeo += msecs_to_jiffies(400); ++ else ++ timeo += msecs_to_jiffies(1000); // 20 -> 40 for mx2g ++ ++ while (time_before(jiffies, timeo)) { ++ spi_nand_read_status(chip->spi, &status); ++ if ((status & STATUS_OIP_MASK) == STATUS_READY) { ++ ret = 0; ++ goto out; ++ } ++ cond_resched(); ++ } ++out: ++ if (s) ++ *s = status; ++ ++ return 0; ++} ++ ++ ++/* ++ * spi_nand_reset- send RESET command "0xff" to the SPI-NAND. ++ * @chip: SPI-NAND device structure ++ */ ++static int spi_nand_reset(struct spi_nand_chip *chip) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ struct spi_device *spi = chip->spi; ++ fh_dev_debug(&spi->dev, "Enter %s\n", __func__); ++ ++ cmd.cmd = SPINAND_CMD_RESET; ++ ++ if (spi_nand_send_cmd(spi, &cmd) < 0) ++ pr_err("spi_nand reset failed!\n"); ++ ++ /* elapse 1ms before issuing any other command */ ++ udelay(1000); ++ ++ return 0; ++} ++ ++ ++/** ++ * spi_nand_lock_block- send write register 0x1f command to the lock/unlock device ++ * @spi: spi device structure ++ * @lock: value to set to block lock register ++ * ++ * Description: ++ * After power up, all the Nand blocks are locked. This function allows ++ * one to unlock the blocks, and so it can be written or erased. ++ */ ++static int spi_nand_lock_block(struct spi_device *spi, u8 lock) ++{ ++ struct spi_nand_cmd cmd = {0}; ++ int ret; ++ ++ cmd.cmd = SPINAND_CMD_WRITE_REG; ++ cmd.n_addr = 1; ++ cmd.addr[0] = REG_BLOCK_LOCK; ++ cmd.n_tx = 1; ++ cmd.tx_buf = &lock; ++ ++ ret = spi_nand_send_cmd(spi, &cmd); ++ if (ret < 0) ++ dev_err(&spi->dev, "error %d lock block\n", ret); ++ ++ return ret; ++} ++ ++static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) ++{ ++ int i; ++ ++ while (len--) { ++ crc ^= *p++ << 8; ++ for (i = 0; i < 8; i++) ++ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); ++ } ++ ++ return crc; ++} ++ ++/* Sanitize ONFI strings so we can safely print them */ ++static void sanitize_string(uint8_t *s, size_t len) ++{ ++ ssize_t i; ++ ++ /* Null terminate */ ++ s[len - 1] = 0; ++ ++ /* Remove non printable chars */ ++ for (i = 0; i < len - 1; i++) { ++ if (s[i] < ' ' || s[i] > 127) ++ s[i] = '?'; ++ } ++ ++ /* Remove trailing spaces */ ++ strim(s); ++} ++ ++/* ++ * Check if the SPI-NAND chip is ONFI compliant, ++ * returns 1 if it is, 0 otherwise. ++ */ ++static bool spi_nand_detect_onfi(struct spi_nand_chip *chip) ++{ ++ struct spi_device *spi = chip->spi; ++ struct spi_nand_onfi_params *p; ++ char *buffer; ++ bool ret = true; ++ u8 otp; ++ int i; ++ ++ /*FIXME buffer size*/ ++ buffer = kmalloc(256 * 3, GFP_KERNEL); ++ otp = OTP_ENABLE; ++ spi_nand_set_otp(spi, &otp); ++ chip->load_page(chip, 0x01); ++ chip->waitfunc(chip, NULL); ++ spi_nand_read_from_cache(chip, 0x01, 0x00, 256 * 3, buffer); ++ otp = OTP_ECC_ENABLE; ++ spi_nand_set_otp(spi, &otp); ++ ++ p = (struct spi_nand_onfi_params *)buffer; ++ for (i = 0; i < 3; i++, p++) { ++ if (p->sig[0] != 'O' || p->sig[1] != 'N' || ++ p->sig[2] != 'F' || p->sig[3] != 'I') ++ continue; ++ if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == ++ le16_to_cpu(p->crc)) ++ break; ++ } ++ if (i == 3) { ++ pr_err("Could not find valid ONFI parameter page; aborting\n"); ++ ret = false; ++ goto out; ++ } ++ ++ memcpy(&chip->onfi_params, p, sizeof(*p)); ++ ++ p = &chip->onfi_params; ++ ++ sanitize_string(p->manufacturer, sizeof(p->manufacturer)); ++ sanitize_string(p->model, sizeof(p->model)); ++ ++ chip->name = p->model; ++ chip->size = le32_to_cpu(p->byte_per_page) * ++ le32_to_cpu(p->pages_per_block) * ++ le32_to_cpu(p->blocks_per_lun) * p->lun_count; ++ chip->block_size = le32_to_cpu(p->byte_per_page) * ++ le32_to_cpu(p->pages_per_block); ++ chip->page_size = le32_to_cpu(p->byte_per_page); ++ chip->page_spare_size = le16_to_cpu(p->spare_bytes_per_page); ++ chip->block_shift = ilog2(chip->block_size); ++ chip->page_shift = ilog2(chip->page_size); ++ chip->page_mask = chip->page_size - 1; ++ chip->bits_per_cell = p->bits_per_cell; ++ /*FIXME need to find a way to read options from ONFI table*/ ++ chip->options = SPINAND_NEED_PLANE_SELECT; ++ if (p->ecc_bits != 0xff) { ++ chip->ecc_strength_ds = p->ecc_bits; ++ chip->ecc_step_ds = 512; ++ } ++ ++out: ++ kfree(buffer); ++ return ret; ++} ++ ++static void spi_nand_set_defaults(struct spi_nand_chip *chip) ++{ ++ /*struct spi_device *spi = chip->spi;*/ ++ ++ /* if (spi->mode & SPI_RX_QUAD) ++ chip->read_cache = spi_nand_read_from_cache_x4; ++ else if (spi->mode & SPI_RX_DUAL) ++ chip->read_cache = spi_nand_read_from_cache_x2; ++ else*/ ++ chip->read_cache = spi_nand_read_from_cache; ++ ++ if (!chip->reset) ++ chip->reset = spi_nand_reset; ++ if (!chip->erase_block) ++ chip->erase_block = spi_nand_erase_block; ++ if (!chip->load_page) ++ chip->load_page = spi_nand_read_page_to_cache; ++ if (!chip->store_cache) ++ chip->store_cache = spi_nand_program_data_to_cache; ++ if (!chip->write_page) ++ chip->write_page = spi_nand_program_execute; ++ if (!chip->write_enable) ++ chip->write_enable = spi_nand_write_enable; ++ if (!chip->waitfunc) ++ chip->waitfunc = spi_nand_wait; ++ if (!chip->enable_ecc) ++ chip->enable_ecc = spi_nand_enable_ecc; ++ if (!chip->disable_ecc) ++ chip->disable_ecc = spi_nand_disable_ecc; ++ if (!chip->block_bad) ++ chip->block_bad = spi_nand_block_checkbad; ++ if (!chip->set_qe) ++ chip->set_qe = spi_nand_set_qe; ++} ++ ++static int spi_nand_check(struct spi_nand_chip *chip) ++{ ++ if (!chip->reset) ++ return -ENODEV; ++ if (!chip->read_id) ++ return -ENODEV; ++ if (!chip->load_page) ++ return -ENODEV; ++ if (!chip->read_cache) ++ return -ENODEV; ++ if (!chip->store_cache) ++ return -ENODEV; ++ if (!chip->write_page) ++ return -ENODEV; ++ if (!chip->erase_block) ++ return -ENODEV; ++ if (!chip->waitfunc) ++ return -ENODEV; ++ if (!chip->write_enable) ++ return -ENODEV; ++ if (!chip->get_ecc_status) ++ return -ENODEV; ++ if (!chip->enable_ecc) ++ return -ENODEV; ++ if (!chip->disable_ecc) ++ return -ENODEV; ++ if (!chip->ecclayout) ++ return -ENODEV; ++ return 0; ++} ++ ++/** ++ * spi_nand_scan_ident - [SPI-NAND Interface] Scan for the SPI-NAND device ++ * @mtd: MTD device structure ++ * ++ * This is the first phase of the normal spi_nand_scan() function. It reads the ++ * flash ID and sets up MTD fields accordingly. ++ * ++ */ ++int spi_nand_scan_ident(struct mtd_info *mtd) ++{ ++ int ret; ++ u8 id[SPINAND_MAX_ID_LEN] = {0}; ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ spi_nand_set_defaults(chip); ++ chip->reset(chip); ++ ++ chip->read_id(chip, id); ++ if (id[0] == 0 && id[1] == 0) { ++ pr_err("SPINAND: read id error! 0x%02x, 0x%02x!\n", ++ id[0], id[1]); ++ return -ENODEV; ++ } ++ ++ pr_err("SPINAND: read id ! 0x%02x, 0x%02x 0x%02x, 0x%02x!\n", ++ id[0], id[1], id[2], id[3]); ++ if (spi_nand_scan_id_table(chip, id)) ++ goto ident_done; ++ pr_info("SPI-NAND type mfr_id: %x, dev_id: %x is not in id table.\n", ++ id[0], id[1]); ++ ++ ++ if (chip->spi->dev_open_multi_wire_flag & QUAD_WIRE_SUPPORT) ++ chip->set_qe(chip); ++ ++ if (spi_nand_detect_onfi(chip)) ++ goto ident_done; ++ ++ return -ENODEV; ++ ++ident_done: ++ pr_info("SPI-NAND: %s is found.\n", chip->name); ++ ++ /*chip->mfr_id = id[0]; ++ chip->dev_id = id[1];*/ ++ ++ chip->buf = kzalloc(chip->page_size + chip->page_spare_size, ++ GFP_KERNEL); ++ if (!chip->buf) ++ return -ENOMEM; ++ ++ chip->oobbuf = chip->buf + chip->page_size; ++ ++ ret = spi_nand_lock_block(chip->spi, BL_ALL_UNLOCKED); ++ ret = chip->enable_ecc(chip); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(spi_nand_scan_ident); ++ ++/** ++ * spi_nand_scan_tail - [SPI-NAND Interface] Scan for the SPI-NAND device ++ * @mtd: MTD device structure ++ * ++ * This is the second phase of the normal spi_nand_scan() function. It fills out ++ * all the uninitialized function pointers with the defaults. ++ */ ++int spi_nand_scan_tail(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ int ret; ++ ++ ret = spi_nand_check(chip); ++ if (ret) ++ return ret; ++ /* Initialize state */ ++ chip->state = FL_READY; ++ /* Invalidate the pagebuffer reference */ ++ chip->pagebuf = -1; ++ chip->bbt_options |= NAND_BBT_USE_FLASH; ++ chip->badblockpos = NAND_LARGE_BADBLOCK_POS; ++ ++ init_waitqueue_head(&chip->wq); ++ spin_lock_init(&chip->chip_lock); ++ ++ mtd->name = chip->name; ++ mtd->size = chip->size; ++ mtd->erasesize = chip->block_size; ++ mtd->writesize = chip->page_size; ++ mtd->writebufsize = mtd->writesize; ++ mtd->oobsize = chip->page_spare_size; ++ mtd->owner = THIS_MODULE; ++ mtd->type = MTD_NANDFLASH; ++ mtd->flags = MTD_CAP_NANDFLASH; ++ /*xxx:porting down: if (!mtd->ecc_strength) ++ mtd->ecc_strength = chip->ecc_strength_ds ? ++ chip->ecc_strength_ds : 1;*/ ++ mtd->bitflip_threshold = 1; ++ mtd->ecclayout = chip->ecclayout; ++ mtd->oobsize = chip->page_spare_size; ++ mtd->oobavail = chip->ecclayout->oobavail; ++ /* remove _* */ ++ mtd->erase = spi_nand_erase; ++ mtd->point = NULL; ++ mtd->unpoint = NULL; ++ mtd->read = spi_nand_read; ++ mtd->write = spi_nand_write; ++ mtd->read_oob = spi_nand_read_oob; ++ mtd->write_oob = spi_nand_write_oob; ++ mtd->sync = spi_nand_sync; ++ mtd->lock = NULL; ++ mtd->unlock = NULL; ++ mtd->suspend = spi_nand_suspend; ++ mtd->resume = spi_nand_resume; ++ mtd->block_isbad = spi_nand_block_isbad; ++ mtd->block_markbad = spi_nand_block_markbad; ++ ++#ifndef CONFIG_SPI_NAND_BBT ++ /* Build bad block table */ ++ return spi_nand_default_bbt(mtd); ++#else ++ return 0; ++#endif ++} ++EXPORT_SYMBOL_GPL(spi_nand_scan_tail); ++ ++/** ++ * spi_nand_scan_ident_release - [SPI-NAND Interface] Free resources ++ * applied by spi_nand_scan_ident ++ * @mtd: MTD device structure ++ */ ++int spi_nand_scan_ident_release(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ kfree(chip->buf); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(spi_nand_scan_ident_release); ++ ++/** ++ * spi_nand_scan_tail_release - [SPI-NAND Interface] Free resources ++ * applied by spi_nand_scan_tail ++ * @mtd: MTD device structure ++ */ ++int spi_nand_scan_tail_release(struct mtd_info *mtd) ++{ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(spi_nand_scan_tail_release); ++ ++/** ++ * spi_nand_release - [SPI-NAND Interface] Free resources held by the SPI-NAND ++ * device ++ * @mtd: MTD device structure ++ */ ++int spi_nand_release(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *chip = mtd->priv; ++ ++ mtd_device_unregister(mtd); ++ kfree(chip->buf); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(spi_nand_release); ++ ++MODULE_DESCRIPTION("SPI NAND framework"); ++MODULE_AUTHOR("Peter Pan<peterpandong at micron.com>"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/drivers/mtd/spi-nand/spi-nand-bbt.c b/drivers/mtd/spi-nand/spi-nand-bbt.c +new file mode 100644 +index 00000000..5340606f +--- /dev/null ++++ b/drivers/mtd/spi-nand/spi-nand-bbt.c +@@ -0,0 +1,1357 @@ ++/* ++ * drivers/mtd/spi_nand_bbt.c ++ * ++ * Overview: ++ * Bad block table support for the SPI-NAND driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This file is derived from nand_base.c ++ * ++ * TODO: ++ * share BBT code with parallel nand ++ */ ++ ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/bbm.h> ++#include <linux/mtd/spi-nand.h> ++#include <linux/bitops.h> ++#include <linux/delay.h> ++#include <linux/vmalloc.h> ++#include <linux/string.h> ++#include <linux/spi/spi.h> ++#include <asm/string.h> ++ ++#define BBT_BLOCK_GOOD 0x00 ++#define BBT_BLOCK_WORN 0x01 ++#define BBT_BLOCK_RESERVED 0x02 ++#define BBT_BLOCK_FACTORY_BAD 0x03 ++ ++#define BBT_ENTRY_MASK 0x03 ++#define BBT_ENTRY_SHIFT 2 ++ ++#ifdef SPINAND_BBT_DEBUG ++#define fh_dev_debug dev_err ++#define fh_debug_dump(buf,len) do { \ ++ unsigned int i; \ ++ printk("\t %s:L%d", __func__,__LINE__); \ ++ for (i=0;i<len/4;i++) { \ ++ if (0 == i % 4 ) \ ++ printk("\n\t\t 0x%08x:\t",(unsigned int) buf+i*4 ); \ ++ printk("%08x ", *(unsigned int*) (buf + i*4));\ ++ } \ ++ } while(0) ++#else ++#define fh_dev_debug(...) ++#define fh_debug_dump(buf,len) ++#endif ++ ++ ++static int spi_nand_update_bbt(struct mtd_info *mtd, loff_t offs); ++ ++static inline uint8_t bbt_get_entry(struct spi_nand_chip *chip, int block) ++{ ++ uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT]; ++ ++ entry >>= (block & BBT_ENTRY_MASK) * 2; ++ return entry & BBT_ENTRY_MASK; ++} ++ ++static inline void bbt_mark_entry(struct spi_nand_chip *chip, int block, ++ uint8_t mark) ++{ ++ uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2); ++ ++ chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk; ++} ++ ++static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) ++{ ++ if (memcmp(buf, td->pattern, td->len)) ++ return -1; ++ return 0; ++} ++ ++/** ++ * check_pattern - [GENERIC] check if a pattern is in the buffer ++ * @buf: the buffer to search ++ * @len: the length of buffer to search ++ * @paglen: the pagelength ++ * @td: search pattern descriptor ++ * ++ * Check for a pattern at the given place. Used to search bad block tables and ++ * good / bad block identifiers. ++ */ ++static int check_pattern(uint8_t *buf, int len, int paglen, ++ struct nand_bbt_descr *td) ++{ ++ if (td->options & NAND_BBT_NO_OOB) ++ return check_pattern_no_oob(buf, td); ++ ++ /* Compare the pattern */ ++ fh_debug_dump(buf + paglen + td->offs, td->len); ++ if (memcmp(buf + paglen + td->offs, td->pattern, td->len)) ++ return -1; ++ ++ return 0; ++} ++ ++/** ++ * check_short_pattern - [GENERIC] check if a pattern is in the buffer ++ * @buf: the buffer to search ++ * @td: search pattern descriptor ++ * ++ * Check for a pattern at the given place. Used to search bad block tables and ++ * good / bad block identifiers. Same as check_pattern, but no optional empty ++ * check. ++ */ ++static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) ++{ ++ /* Compare the pattern */ ++ if (memcmp(buf + td->offs, td->pattern, td->len)) ++ return -1; ++ return 0; ++} ++ ++/** ++ * add_marker_len - compute the length of the marker in data area ++ * @td: BBT descriptor used for computation ++ * ++ * The length will be 0 if the marker is located in OOB area. ++ */ ++static u32 add_marker_len(struct nand_bbt_descr *td) ++{ ++ u32 len; ++ ++ if (!(td->options & NAND_BBT_NO_OOB)) ++ return 0; ++ ++ len = td->len; ++ if (td->options & NAND_BBT_VERSION) ++ len++; ++ return len; ++} ++ ++static inline int mtd_is_eccerr(int err) ++{ ++ return err == -EBADMSG; ++} ++ ++static inline int mtd_is_bitflip(int err) ++{ ++ return err == -EUCLEAN; ++} ++ ++static inline int mtd_is_bitflip_or_eccerr(int err) ++{ ++ return mtd_is_bitflip(err) || mtd_is_eccerr(err); ++} ++/** ++ * read_bbt - [GENERIC] Read the bad block table starting from page ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @page: the starting page ++ * @num: the number of bbt descriptors to read ++ * @td: the bbt describtion table ++ * @offs: block number offset in the table ++ * ++ * Read the bad block table starting from page. ++ */ ++static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, ++ struct nand_bbt_descr *td, int offs) ++{ ++ int res, ret = 0, i, j, act = 0; ++ struct spi_nand_chip *this = mtd->priv; ++ size_t retlen, len, totlen; ++ loff_t from; ++ int bits = td->options & NAND_BBT_NRBITS_MSK; ++ uint8_t msk = (uint8_t)((1 << bits) - 1); ++ u32 marker_len; ++ int reserved_block_code = td->reserved_block_code; ++ ++ totlen = (num * bits) >> 3; ++ marker_len = add_marker_len(td); ++ from = ((loff_t)page) << this->page_shift; ++ while (totlen) { ++ len = min(totlen, (size_t)(1 << this->block_shift)); ++ if (marker_len) { ++ /* ++ * In case the BBT marker is not in the OOB area it ++ * will be just in the first page. ++ */ ++ len -= marker_len; ++ from += marker_len; ++ marker_len = 0; ++ } ++ res = mtd->read(mtd, from, len, &retlen, ++ buf); /*/// mtd_read(mtd, from, len, &retlen, buf);*/ ++ if (res < 0) { ++ if (mtd_is_eccerr(res)) { ++ pr_info("spi_nand_bbt: ECC error in BBT at 0x%012llx\n", ++ from & ~mtd->writesize); ++ return res; ++ } else if (mtd_is_bitflip(res)) { ++ pr_info("spi_nand_bbt: corrected error in BBT at 0x%012llx\n", ++ from & ~mtd->writesize); ++ ret = res; ++ } else { ++ pr_info("spi_nand_bbt: error reading BBT\n"); ++ return res; ++ } ++ } ++ ++ /* Analyse data */ ++ for (i = 0; i < len; i++) { ++ uint8_t dat = buf[i]; ++ ++ for (j = 0; j < 8; j += bits, act++) { ++ uint8_t tmp = (dat >> j) & msk; ++ ++ if (tmp == msk) ++ continue; ++ if (reserved_block_code && ++ (tmp == reserved_block_code)) { ++ pr_info("spi_nand_read_bbt: reserved block at 0x%012llx\n", ++ (loff_t)(offs + act) << ++ this->block_shift); ++ bbt_mark_entry(this, offs + act, ++ BBT_BLOCK_RESERVED); ++ mtd->ecc_stats.bbtblocks++; ++ continue; ++ } ++ /* ++ * Leave it for now, if it's matured we can ++ * move this message to pr_debug. ++ */ ++ pr_info("spi_nand_read_bbt: bad block at 0x%012llx\n", ++ (loff_t)(offs + act) << ++ this->block_shift); ++ /* Factory marked bad or worn out? */ ++ if (tmp == 0) ++ bbt_mark_entry(this, offs + act, ++ BBT_BLOCK_FACTORY_BAD); ++ else ++ bbt_mark_entry(this, offs + act, ++ BBT_BLOCK_WORN); ++ mtd->ecc_stats.badblocks++; ++ } ++ } ++ totlen -= len; ++ from += len; ++ } ++ return ret; ++} ++ ++/** ++ * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @td: descriptor for the bad block table ++ * @chip: read the table for a specific chip, -1 read all chips; applies only if ++ * NAND_BBT_PERCHIP option is set ++ * ++ * Read the bad block table for all chips starting at a given page. We assume ++ * that the bbt bits are in consecutive order. ++ */ ++static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *td, int chip) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int res = 0; ++ ++ res = read_bbt(mtd, buf, td->pages[0], ++ mtd->size >> this->block_shift, td, 0); ++ if (res) ++ return res; ++ ++ return 0; ++} ++ ++/* BBT marker is in the first page, no OOB */ ++static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, ++ struct nand_bbt_descr *td) ++{ ++ size_t retlen; ++ size_t len; ++ ++ len = td->len; ++ if (td->options & NAND_BBT_VERSION) ++ len++; ++ ++ /*return mtd_read(mtd, offs, len, &retlen, buf);*/ ++ return mtd->read(mtd, offs, len, &retlen, buf); ++} ++ ++/** ++ * scan_read_oob - [GENERIC] Scan data+OOB region to buffer ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @offs: offset at which to scan ++ * @len: length of data region to read ++ * ++ * Scan read data from data+OOB. May traverse multiple pages, interleaving ++ * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest" ++ * ECC condition (error or bitflip). May quit on the first (non-ECC) error. ++ */ ++static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, ++ size_t len) ++{ ++ struct mtd_oob_ops ops; ++ int res, ret = 0; ++ struct spi_nand_chip *chip = mtd->priv; ++ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__); ++ ++ ops.mode = MTD_OOB_PLACE; ++ ops.ooboffs = 0; ++ ops.ooblen = mtd->oobsize; ++ ++ while (len > 0) { ++ ops.datbuf = buf; ++ ops.len = min_t(size_t, len, mtd->writesize); ++ ops.oobbuf = buf + ops.len; ++ ++ /*res = mtd_read_oob(mtd, offs, &ops);*/ ++ res = mtd->read_oob(mtd, offs, &ops); ++ if (res) { ++ if (!mtd_is_bitflip_or_eccerr(res)) ++ return res; ++ else if (mtd_is_eccerr(res) || !ret) ++ ret = res; ++ } ++ ++ buf += mtd->oobsize + mtd->writesize; ++ len -= mtd->writesize; ++ offs += mtd->writesize; ++ } ++ return ret; ++} ++ ++static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs, ++ size_t len, struct nand_bbt_descr *td) ++{ ++ if (td->options & NAND_BBT_NO_OOB) ++ return scan_read_data(mtd, buf, offs, td); ++ else ++ return scan_read_oob(mtd, buf, offs, len); ++} ++ ++/* Scan write data with oob to flash */ ++static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, ++ uint8_t *buf, uint8_t *oob) ++{ ++ struct mtd_oob_ops ops; ++ ++ ops.mode = MTD_OOB_PLACE; ++ ops.ooboffs = 0; ++ ops.ooblen = mtd->oobsize; ++ ops.datbuf = buf; ++ ops.oobbuf = oob; ++ ops.len = len; ++ ++ /*return mtd_write_oob(mtd, offs, &ops);*/ ++ return mtd->write_oob(mtd, offs, &ops); ++} ++ ++static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) ++{ ++ u32 ver_offs = td->veroffs; ++ ++ if (!(td->options & NAND_BBT_NO_OOB)) ++ ver_offs += mtd->writesize; ++ return ver_offs; ++} ++ ++/** ++ * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @td: descriptor for the bad block table ++ * @md: descriptor for the bad block table mirror ++ * ++ * Read the bad block table(s) for all chips starting at a given page. We ++ * assume that the bbt bits are in consecutive order. ++ */ ++static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *td, struct nand_bbt_descr *md) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ ++ /* Read the primary version, if available */ ++ if (td->options & NAND_BBT_VERSION) { ++ scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift, ++ mtd->writesize, td); ++ td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; ++ pr_info("Bad block table at page %d, version 0x%02X\n", ++ td->pages[0], td->version[0]); ++ } ++ ++ /* Read the mirror version, if available */ ++ if (md && (md->options & NAND_BBT_VERSION)) { ++ scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift, ++ mtd->writesize, md); ++ md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; ++ pr_info("Bad block table at page %d, version 0x%02X\n", ++ md->pages[0], md->version[0]); ++ } ++} ++ ++/* Scan a given block partially */ ++static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, ++ loff_t offs, uint8_t *buf, int numpages) ++{ ++ struct mtd_oob_ops ops; ++ int j, ret; ++ ++ ops.ooblen = mtd->oobsize; ++ ops.oobbuf = buf; ++ ops.ooboffs = 0; ++ ops.datbuf = NULL; ++ ops.mode = MTD_OOB_PLACE; ++ ++ for (j = 0; j < numpages; j++) { ++ /* ++ * Read the full oob until read_oob is fixed to handle single ++ * byte reads for 16 bit buswidth. ++ */ ++ ret = mtd->read_oob(mtd, offs, &ops);/*mtd_read_oob(mtd, offs, &ops);*/ ++ /* Ignore ECC errors when checking for BBM */ ++ if (ret < 0 && !mtd_is_bitflip_or_eccerr(ret)) ++ return ret; ++ ++ if (mtd_is_eccerr(ret)) ++ return 1; ++ ++ if (check_short_pattern(buf, bd)) ++ return 1; ++ ++ offs += mtd->writesize; ++ } ++ return 0; ++} ++ ++/** ++ * create_bbt - [GENERIC] Create a bad block table by scanning the device ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @bd: descriptor for the good/bad block search pattern ++ * @chip: create the table for a specific chip, -1 read all chips; applies only ++ * if NAND_BBT_PERCHIP option is set ++ * ++ * Create a bad block table by scanning the device for the given good/bad block ++ * identify pattern. ++ */ ++static int create_bbt(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *bd, int chip) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int i, numblocks, numpages; ++ int startblock; ++ loff_t from; ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ ++ pr_info("Scanning device for bad blocks\n"); ++ ++ if (bd->options & NAND_BBT_SCAN2NDPAGE) ++ numpages = 2; ++ else ++ numpages = 1; ++ ++ if (chip == -1) { ++ numblocks = mtd->size >> this->block_shift; ++ startblock = 0; ++ from = 0; ++ } else { ++ numblocks = this->size >> this->block_shift; ++ startblock = chip * numblocks; ++ numblocks += startblock; ++ from = (loff_t)startblock << this->block_shift; ++ } ++ ++ if (this->bbt_options & NAND_BBT_SCANLASTPAGE) ++ from += mtd->erasesize - (mtd->writesize * numpages); ++ ++ for (i = startblock; i < numblocks; i++) { ++ int ret; ++ ++ BUG_ON(bd->options & NAND_BBT_NO_OOB); ++ ret = scan_block_fast(mtd, bd, from, buf, numpages); ++ if (ret < 0) ++ return ret; ++ ++ if (ret) { ++ bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD); ++ pr_warn("Bad eraseblock %d at 0x%012llx\n", ++ i, (unsigned long long)from); ++ mtd->ecc_stats.badblocks++; ++ } ++ ++ from += (1 << this->block_shift); ++ } ++ return 0; ++} ++ ++/** ++ * search_bbt - [GENERIC] scan the device for a specific bad block table ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @td: descriptor for the bad block table ++ * ++ * Read the bad block table by searching for a given ident pattern. Search is ++ * preformed either from the beginning up or from the end of the device ++ * downwards. The search starts always at the start of a block. If the option ++ * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains ++ * the bad block information of this chip. This is necessary to provide support ++ * for certain DOC devices. ++ * ++ * The bbt ident pattern resides in the oob area of the first page in a block. ++ */ ++static int search_bbt(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *td) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int i, chips; ++ int startblock, block, dir; ++ int scanlen = mtd->writesize + mtd->oobsize; ++ int bbtblocks; ++ int blocktopage = this->block_shift - this->page_shift; ++ ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ /* Search direction top -> down? */ ++ if (td->options & NAND_BBT_LASTBLOCK) { ++ startblock = (mtd->size >> this->block_shift) - 1; ++ dir = -1; ++ } else { ++ startblock = 0; ++ dir = 1; ++ } ++ ++ chips = 1; ++ bbtblocks = mtd->size >> this->block_shift; ++ ++ for (i = 0; i < chips; i++) { ++ /* Reset version information */ ++ td->version[i] = 0; ++ td->pages[i] = -1; ++ /* Scan the maximum number of blocks */ ++ for (block = 0; block < td->maxblocks; block++) { ++ ++ int actblock = startblock + dir * block; ++ loff_t offs = (loff_t)actblock << this->block_shift; ++ ++ /* Read first page */ ++ scan_read(mtd, buf, offs, mtd->writesize, td); ++ fh_dev_debug(&this->spi->dev, "read block %d, first v 0x%08x\n ", ++ actblock, *(int *)buf); ++ fh_dev_debug(&this->spi->dev, "td pattern:%s, offset %d, len %d\n ", ++ td->pattern, td->offs,td->len); ++ if (!check_pattern(buf, scanlen, mtd->writesize, td)) { ++ td->pages[i] = actblock << blocktopage; ++ if (td->options & NAND_BBT_VERSION) { ++ offs = bbt_get_ver_offs(mtd, td); ++ td->version[i] = buf[offs]; ++ } ++ break; ++ } ++ } ++ startblock += this->size >> this->block_shift; ++ } ++ /* Check, if we found a bbt for each requested chip */ ++ for (i = 0; i < chips; i++) { ++ if (td->pages[i] == -1) ++ pr_warn("Bad block table not found for chip %d\n", i); ++ else ++ pr_info("Bad block table found at page %d, version 0x%02X\n", ++ td->pages[i], td->version[i]); ++ } ++ return 0; ++} ++ ++/** ++ * search_read_bbts - [GENERIC] scan the device for bad block table(s) ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @td: descriptor for the bad block table ++ * @md: descriptor for the bad block table mirror ++ * ++ * Search and read the bad block table(s). ++ */ ++static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *td, ++ struct nand_bbt_descr *md) ++{ ++ /* Search the primary table */ ++ search_bbt(mtd, buf, td); ++ ++ /* Search the mirror table */ ++ if (md) ++ search_bbt(mtd, buf, md); ++} ++ ++/** ++ * write_bbt - [GENERIC] (Re)write the bad block table ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @td: descriptor for the bad block table ++ * @md: descriptor for the bad block table mirror ++ * @chipsel: selector for a specific chip, -1 for all ++ * ++ * (Re)write the bad block table. ++ */ ++static int write_bbt(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *td, struct nand_bbt_descr *md, ++ int chipsel) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ struct erase_info einfo; ++ int i, res, chip = 0; ++ int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; ++ int nrchips, pageoffs, ooboffs; ++ uint8_t msk[4]; ++ uint8_t rcode = td->reserved_block_code; ++ size_t retlen, len = 0; ++ loff_t to; ++ struct mtd_oob_ops ops; ++ extern int fh_start_debug; ++ fh_start_debug = 1; ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ ++ ops.ooblen = mtd->oobsize; ++ ops.ooboffs = 0; ++ ops.datbuf = NULL; ++ ops.mode = MTD_OOB_PLACE; ++ ++ if (!rcode) ++ rcode = 0xff; ++ numblocks = (int)(mtd->size >> this->block_shift); ++ nrchips = 1; ++ ++ /* Loop through the chips */ ++ for (; chip < nrchips; chip++) { ++ /* ++ * There was already a version of the table, reuse the page ++ * This applies for absolute placement too, as we have the ++ * page nr. in td->pages. ++ */ ++ if (td->pages[chip] != -1) { ++ page = td->pages[chip]; ++ goto write; ++ } ++ ++ /* ++ * Automatic placement of the bad block table. Search direction ++ * top -> down? ++ */ ++ if (td->options & NAND_BBT_LASTBLOCK) { ++ startblock = numblocks * (chip + 1) - 1; ++ dir = -1; ++ } else { ++ startblock = chip * numblocks; ++ dir = 1; ++ } ++ ++ for (i = 0; i < td->maxblocks; i++) { ++ int block = startblock + dir * i; ++ /* Check, if the block is bad */ ++ switch (bbt_get_entry(this, block)) { ++ case BBT_BLOCK_WORN: ++ case BBT_BLOCK_FACTORY_BAD: ++ continue; ++ } ++ page = block << ++ (this->block_shift - this->page_shift); ++ /* Check, if the block is used by the mirror table */ ++ if (!md || md->pages[chip] != page) ++ goto write; ++ } ++ pr_err("No space left to write bad block table\n"); ++ return -ENOSPC; ++write: ++ ++ /* Set up shift count and masks for the flash table */ ++ bits = td->options & NAND_BBT_NRBITS_MSK; ++ msk[2] = ~rcode; ++ switch (bits) { ++ case 1: ++ sft = 3; ++ sftmsk = 0x07; ++ msk[0] = 0x00; ++ msk[1] = 0x01; ++ msk[3] = 0x01; ++ break; ++ case 2: ++ sft = 2; ++ sftmsk = 0x06; ++ msk[0] = 0x00; ++ msk[1] = 0x01; ++ msk[3] = 0x03; ++ break; ++ case 4: ++ sft = 1; ++ sftmsk = 0x04; ++ msk[0] = 0x00; ++ msk[1] = 0x0C; ++ msk[3] = 0x0f; ++ break; ++ case 8: ++ sft = 0; ++ sftmsk = 0x00; ++ msk[0] = 0x00; ++ msk[1] = 0x0F; ++ msk[3] = 0xff; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ to = ((loff_t)page) << this->page_shift; ++ ++ fh_dev_debug(&this->spi->dev, " td.options 0x08%x\n", td->options); ++ ++ /* Must we save the block contents? */ ++ if (td->options & NAND_BBT_SAVECONTENT) { ++ /* Make it block aligned */ ++ to &= ~((loff_t)((1 << this->block_shift) - 1)); ++ len = 1 << this->block_shift; ++ res = mtd->read(mtd, to, len, &retlen, ++ buf); // mtd_read(mtd, to, len, &retlen, buf); ++ if (res < 0) { ++ if (retlen != len) { ++ pr_info("spi_nand_bbt: error reading block "); ++ pr_info("for writing the bad block table\n"); ++ return res; ++ } ++ pr_warn("spi_nand_bbt: ECC error while reading "); ++ pr_warn("block for writing bad block table\n"); ++ } ++ /* Read oob data */ ++ ops.ooblen = (len >> this->page_shift) * mtd->oobsize; ++ ops.oobbuf = &buf[len]; ++ res = mtd->read_oob(mtd, to + mtd->writesize, ++ &ops); /*mtd_read_oob(mtd, to + mtd->writesize, &ops);*/ ++ if (res < 0 || ops.oobretlen != ops.ooblen) ++ goto outerr; ++ ++ /* Calc the byte offset in the buffer */ ++ pageoffs = page - (int)(to >> this->page_shift); ++ offs = pageoffs << this->page_shift; ++ /* Preset the bbt area with 0xff */ ++ memset(&buf[offs], 0xff, (size_t)(numblocks >> sft)); ++ ooboffs = len + (pageoffs * mtd->oobsize); ++ ++ } else if (td->options & NAND_BBT_NO_OOB) { ++ ooboffs = 0; ++ offs = td->len; ++ /* The version byte */ ++ if (td->options & NAND_BBT_VERSION) ++ offs++; ++ /* Calc length */ ++ len = (size_t)(numblocks >> sft); ++ len += offs; ++ /* Make it page aligned! */ ++ len = ALIGN(len, mtd->writesize); ++ /* Preset the buffer with 0xff */ ++ memset(buf, 0xff, len); ++ /* Pattern is located at the begin of first page */ ++ memcpy(buf, td->pattern, td->len); ++ } else { ++ /* Calc length */ ++ len = (size_t)(numblocks >> sft); ++ /* Make it page aligned! */ ++ len = ALIGN(len, mtd->writesize); ++ /* Preset the buffer with 0xff */ ++ memset(buf, 0xff, len + ++ (len >> this->page_shift) * mtd->oobsize); ++ offs = 0; ++ ooboffs = len; ++ /* Pattern is located in oob area of first page */ ++ memcpy(&buf[ooboffs + td->offs], td->pattern, td->len); ++ ++ /*fh_debug_dump(td->pattern, td->len);*/ ++ } ++ ++ if (td->options & NAND_BBT_VERSION) ++ buf[ooboffs + td->veroffs] = td->version[chip]; ++ ++ /* Walk through the memory table */ ++ for (i = 0; i < numblocks; i++) { ++ uint8_t dat; ++ int sftcnt = (i << (3 - sft)) & sftmsk; ++ ++ dat = bbt_get_entry(this, chip * numblocks + i); ++ /* Do not store the reserved bbt blocks! */ ++ buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt); ++ } ++ ++ memset(&einfo, 0, sizeof(einfo)); ++ einfo.mtd = mtd; ++ einfo.addr = to; ++ einfo.len = 1 << this->block_shift; ++ res = __spi_nand_erase(mtd, &einfo, 1); ++ if (res < 0) ++ goto outerr; ++ ++ /*fh_debug_dump(&buf[ooboffs],20);*/ ++ res = scan_write_bbt(mtd, to, len, buf, ++ td->options & NAND_BBT_NO_OOB ? NULL : ++ &buf[len]); ++ ++ if (res < 0) ++ goto outerr; ++ ++ pr_info("Bad block table written to 0x%012llx, version 0x%02X\n", ++ (unsigned long long)to, td->version[chip]); ++ ++ /* Mark it as used */ ++ td->pages[chip] = page; ++ } ++ return 0; ++ ++outerr: ++ pr_warn("spi_nand_bbt: error while writing bad block table %d\n", res); ++ return res; ++} ++ ++/** ++ * spi_nand_memory_bbt - [GENERIC] create a memory based bad block table ++ * @mtd: MTD device structure ++ * @bd: descriptor for the good/bad block search pattern ++ * ++ * The function creates a memory based bbt by scanning the device for ++ * manufacturer / software marked good / bad blocks. ++ */ ++static inline int spi_nand_memory_bbt(struct mtd_info *mtd, ++ struct nand_bbt_descr *bd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ ++ return create_bbt(mtd, this->buf, bd, -1); ++} ++ ++/** ++ * check_create - [GENERIC] create and write bbt(s) if necessary ++ * @mtd: MTD device structure ++ * @buf: temporary buffer ++ * @bd: descriptor for the good/bad block search pattern ++ * ++ * The function checks the results of the previous call to read_bbt and creates ++ * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found ++ * for the chip/device. Update is necessary if one of the tables is missing or ++ * the version nr. of one table is less than the other. ++ */ ++static int check_create(struct mtd_info *mtd, uint8_t *buf, ++ struct nand_bbt_descr *bd) ++{ ++ int i, chips, writeops, create, chipsel, res, res2; ++ struct spi_nand_chip *this = mtd->priv; ++ struct nand_bbt_descr *td = this->bbt_td; ++ struct nand_bbt_descr *md = this->bbt_md; ++ struct nand_bbt_descr *rd, *rd2; ++ ++ chips = 1; ++ ++ for (i = 0; i < chips; i++) { ++ writeops = 0; ++ create = 0; ++ rd = NULL; ++ rd2 = NULL; ++ res = res2 = 0; ++ /* Per chip or per device? */ ++ chipsel = -1; ++ /* Mirrored table available? */ ++ if (md) { ++ if (td->pages[i] == -1 && md->pages[i] == -1) { ++ create = 1; ++ writeops = 0x03; ++ } else if (td->pages[i] == -1) { ++ rd = md; ++ writeops = 0x01; ++ } else if (md->pages[i] == -1) { ++ rd = td; ++ writeops = 0x02; ++ } else if (td->version[i] == md->version[i]) { ++ rd = td; ++ if (!(td->options & NAND_BBT_VERSION)) ++ rd2 = md; ++ } else if (((int8_t)(td->version[i] - md->version[i])) ++ > 0) { ++ rd = td; ++ writeops = 0x02; ++ } else { ++ rd = md; ++ writeops = 0x01; ++ } ++ } else { ++ if (td->pages[i] == -1) { ++ create = 1; ++ writeops = 0x01; ++ } else ++ rd = td; ++ } ++ ++ if (create) { ++ /* Create the bad block table by scanning the device? */ ++ if (!(td->options & NAND_BBT_CREATE)) ++ continue; ++ ++ /* Create the table in memory by scanning the chip(s) */ ++ /*xxx: create it; if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))*/ ++ create_bbt(mtd, buf, bd, chipsel); ++ ++ td->version[i] = 1; ++ if (md) ++ md->version[i] = 1; ++ } ++ ++ /* Read back first? */ ++ if (rd) { ++ res = read_abs_bbt(mtd, buf, rd, chipsel); ++ if (mtd_is_eccerr(res)) { ++ /* Mark table as invalid */ ++ rd->pages[i] = -1; ++ rd->version[i] = 0; ++ i--; ++ continue; ++ } ++ } ++ /* If they weren't versioned, read both */ ++ if (rd2) { ++ res2 = read_abs_bbt(mtd, buf, rd2, chipsel); ++ if (mtd_is_eccerr(res2)) { ++ /* Mark table as invalid */ ++ rd2->pages[i] = -1; ++ rd2->version[i] = 0; ++ i--; ++ continue; ++ } ++ } ++ ++ /* Scrub the flash table(s)? */ ++ if (mtd_is_bitflip(res) || mtd_is_bitflip(res2)) ++ writeops = 0x03; ++ ++ /* Update version numbers before writing */ ++ if (md) { ++ td->version[i] = max(td->version[i], md->version[i]); ++ md->version[i] = td->version[i]; ++ } ++ ++ /* Write the bad block table to the device? */ ++ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) { ++ res = write_bbt(mtd, buf, td, md, chipsel); ++ if (res < 0) ++ return res; ++ } ++ ++ /* Write the mirror bad block table to the device? */ ++ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) { ++ res = write_bbt(mtd, buf, md, td, chipsel); ++ if (res < 0) ++ return res; ++ } ++ } ++ return 0; ++} ++ ++/** ++ * mark_bbt_regions - [GENERIC] mark the bad block table regions ++ * @mtd: MTD device structure ++ * @td: bad block table descriptor ++ * ++ * The bad block table regions are marked as "bad" to prevent accidental ++ * erasures / writes. The regions are identified by the mark 0x02. ++ */ ++static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int i, j, chips, block, nrblocks, update; ++ uint8_t oldval; ++ ++ chips = 1; ++ nrblocks = (int)(mtd->size >> this->block_shift); ++ ++ for (i = 0; i < chips; i++) { ++ if ((td->options & NAND_BBT_ABSPAGE) || ++ !(td->options & NAND_BBT_WRITE)) { ++ if (td->pages[i] == -1) ++ continue; ++ block = td->pages[i] >> ++ (this->block_shift - this->page_shift); ++ oldval = bbt_get_entry(this, block); ++ bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); ++ if ((oldval != BBT_BLOCK_RESERVED) && ++ td->reserved_block_code) ++ spi_nand_update_bbt(mtd, (loff_t)block << ++ this->block_shift); ++ continue; ++ } ++ update = 0; ++ if (td->options & NAND_BBT_LASTBLOCK) ++ block = ((i + 1) * nrblocks) - td->maxblocks; ++ else ++ block = i * nrblocks; ++ for (j = 0; j < td->maxblocks; j++) { ++ oldval = bbt_get_entry(this, block); ++ bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); ++ if (oldval != BBT_BLOCK_RESERVED) ++ update = 1; ++ block++; ++ } ++ /* ++ * If we want reserved blocks to be recorded to flash, and some ++ * new ones have been marked, then we need to update the stored ++ * bbts. This should only happen once. ++ */ ++ if (update && td->reserved_block_code) ++ spi_nand_update_bbt(mtd, (loff_t)(block - 1) << ++ this->block_shift); ++ } ++ fh_dev_debug(&this->spi->dev, "Leave %s\n", __func__); ++} ++ ++/** ++ * verify_bbt_descr - verify the bad block description ++ * @mtd: MTD device structure ++ * @bd: the table to verify ++ * ++ * This functions performs a few sanity checks on the bad block description ++ * table. ++ */ ++static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ u32 pattern_len; ++ u32 bits; ++ u32 table_size; ++ ++ if (!bd) ++ return; ++ ++ pattern_len = bd->len; ++ bits = bd->options & NAND_BBT_NRBITS_MSK; ++ ++ BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) && ++ !(this->bbt_options & NAND_BBT_USE_FLASH)); ++ BUG_ON(!bits); ++ ++ if (bd->options & NAND_BBT_VERSION) ++ pattern_len++; ++ ++ if (bd->options & NAND_BBT_NO_OOB) { ++ BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH)); ++ BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB)); ++ BUG_ON(bd->offs); ++ if (bd->options & NAND_BBT_VERSION) ++ BUG_ON(bd->veroffs != bd->len); ++ BUG_ON(bd->options & NAND_BBT_SAVECONTENT); ++ } ++ ++ table_size = mtd->size >> this->block_shift; ++ table_size >>= 3; ++ table_size *= bits; ++ if (bd->options & NAND_BBT_NO_OOB) ++ table_size += pattern_len; ++ BUG_ON(table_size > (1 << this->block_shift)); ++} ++ ++/** ++ * spi_nand_scan_bbt - [SPI-NAND Interface] scan, find, read and maybe create ++ * bad block table(s) ++ * @mtd: MTD device structure ++ * @bd: descriptor for the good/bad block search pattern ++ * ++ * The function checks, if a bad block table(s) is/are already available. If ++ * not it scans the device for manufacturer marked good / bad blocks and writes ++ * the bad block table(s) to the selected place. ++ * ++ * The bad block table memory is allocated here. It must be freed by calling ++ * the spi_nand_free_bbt function. ++ */ ++int spi_nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int len, res = 0; ++ uint8_t *buf; ++ struct nand_bbt_descr *td = this->bbt_td; ++ struct nand_bbt_descr *md = this->bbt_md; ++ ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ len = mtd->size >> (this->block_shift + 2); ++ /* ++ * Allocate memory (2bit per block) and clear the memory bad block ++ * table. ++ */ ++ this->bbt = kzalloc(len, GFP_KERNEL); ++ if (!this->bbt) ++ return -ENOMEM; ++ ++ /* ++ * If no primary table decriptor is given, scan the device to build a ++ * memory based bad block table. ++ */ ++ if (!td) { ++ res = spi_nand_memory_bbt(mtd, bd); ++ if (res) { ++ pr_err("spi_nand_bbt: can't scan flash and build the RAM-based BBT\n"); ++ kfree(this->bbt); ++ this->bbt = NULL; ++ } ++ return res; ++ } ++ verify_bbt_descr(mtd, td); ++ verify_bbt_descr(mtd, md); ++ ++ /* Allocate a temporary buffer for one eraseblock incl. oob */ ++ len = (1 << this->block_shift); ++ len += (len >> this->page_shift) * mtd->oobsize; ++ buf = vmalloc(len); ++ if (!buf) { ++ kfree(this->bbt); ++ this->bbt = NULL; ++ return -ENOMEM; ++ } ++ ++ /* Is the bbt at a given page? */ ++ if (td->options & NAND_BBT_ABSPAGE) ++ read_abs_bbts(mtd, buf, td, md); ++ else { ++ /* Search the bad block table using a pattern in oob */ ++ search_read_bbts(mtd, buf, td, md); ++ } ++ ++ res = check_create(mtd, buf, bd); ++ ++ /* Prevent the bbt regions from erasing / writing */ ++ mark_bbt_region(mtd, td); ++ if (md) ++ mark_bbt_region(mtd, md); ++ ++ vfree(buf); ++ return res; ++} ++EXPORT_SYMBOL(spi_nand_scan_bbt); ++ ++/** ++ * spi_nand_update_bbt - update bad block table(s) ++ * @mtd: MTD device structure ++ * @offs: the offset of the newly marked block ++ * ++ * The function updates the bad block table(s). ++ */ ++static int spi_nand_update_bbt(struct mtd_info *mtd, loff_t offs) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int len, res = 0; ++ int chip, chipsel; ++ uint8_t *buf; ++ struct nand_bbt_descr *td = this->bbt_td; ++ struct nand_bbt_descr *md = this->bbt_md; ++ ++ if (!this->bbt || !td) ++ return -EINVAL; ++ ++ /* Allocate a temporary buffer for one eraseblock incl. oob */ ++ len = (1 << this->block_shift); ++ len += (len >> this->page_shift) * mtd->oobsize; ++ buf = kmalloc(len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ chip = 0; ++ chipsel = -1; ++ ++ td->version[chip]++; ++ if (md) ++ md->version[chip]++; ++ ++ /* Write the bad block table to the device? */ ++ if (td->options & NAND_BBT_WRITE) { ++ res = write_bbt(mtd, buf, td, md, chipsel); ++ if (res < 0) ++ goto out; ++ } ++ /* Write the mirror bad block table to the device? */ ++ if (md && (md->options & NAND_BBT_WRITE)) ++ res = write_bbt(mtd, buf, md, td, chipsel); ++ ++out: ++ kfree(buf); ++ return res; ++} ++ ++/* ++ * Define some generic bad / good block scan pattern which are used ++ * while scanning a device for factory marked good / bad blocks. ++ */ ++static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; ++ ++/* Generic flash bbt descriptors */ ++static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' }; ++static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' }; ++ ++static struct nand_bbt_descr bbt_main_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION, ++ .offs = 4, //.offs = 8, ++ .len = 4, ++ .veroffs = 2, //.veroffs = 12, ++ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, ++ .pattern = bbt_pattern ++}; ++ ++static struct nand_bbt_descr bbt_mirror_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION, ++ .offs = 4, //.offs = 8, ++ .len = 4, ++ .veroffs = 2, //.veroffs = 12, ++ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, ++ .pattern = mirror_pattern ++}; ++ ++static struct nand_bbt_descr bbt_main_no_oob_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_NO_OOB, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, ++ .pattern = bbt_pattern ++}; ++ ++static struct nand_bbt_descr bbt_mirror_no_oob_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_NO_OOB, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS, ++ .pattern = mirror_pattern ++}; ++ ++#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB) ++/** ++ * spi_nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure ++ * @this: SPI-NAND chip to create descriptor for ++ * ++ * This function allocates and initializes a nand_bbt_descr for BBM detection ++ * based on the properties of @this. The new descriptor is stored in ++ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when ++ * passed to this function. ++ */ ++static int spi_nand_create_badblock_pattern(struct spi_nand_chip *this) ++{ ++ struct nand_bbt_descr *bd; ++ ++ if (this->badblock_pattern) { ++ pr_warn("Bad block pattern already allocated; not replacing\n"); ++ return -EINVAL; ++ } ++ bd = kzalloc(sizeof(*bd), GFP_KERNEL); ++ if (!bd) ++ return -ENOMEM; ++ bd->options = this->bbt_options & BADBLOCK_SCAN_MASK; ++ bd->offs = this->badblockpos; ++ bd->len = 1; ++ bd->pattern = scan_ff_pattern; ++ bd->options |= NAND_BBT_DYNAMICSTRUCT; ++ this->badblock_pattern = bd; ++ return 0; ++} ++ ++/** ++ * spi_nand_default_bbt - [SPI-NAND Interface] Select a default bad block table for the device ++ * @mtd: MTD device structure ++ * ++ * This function selects the default bad block table support for the device and ++ * calls the spi_nand_scan_bbt function. ++ */ ++int spi_nand_default_bbt(struct mtd_info *mtd) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int ret; ++ ++ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__); ++ ++ fh_dev_debug(&this->spi->dev, "\tbbt option %x\n", this->bbt_options); ++ /* Is a flash based bad block table requested? */ ++ if (this->bbt_options & NAND_BBT_USE_FLASH) { ++ /* Use the default pattern descriptors */ ++ if (!this->bbt_td) { ++ if (this->bbt_options & NAND_BBT_NO_OOB) { ++ this->bbt_td = &bbt_main_no_oob_descr; ++ this->bbt_md = &bbt_mirror_no_oob_descr; ++ } else { ++ this->bbt_td = &bbt_main_descr; ++ this->bbt_md = &bbt_mirror_descr; ++ } ++ } ++ } else { ++ this->bbt_td = NULL; ++ this->bbt_md = NULL; ++ } ++ ++ if (!this->badblock_pattern) { ++ ret = spi_nand_create_badblock_pattern(this); ++ if (ret) ++ return ret; ++ } ++ ++ fh_dev_debug(&this->spi->dev, "badblock pattern 0x%02x\n", ++ * this->badblock_pattern->pattern); ++ return spi_nand_scan_bbt(mtd, this->badblock_pattern); ++} ++EXPORT_SYMBOL(spi_nand_default_bbt); ++ ++/** ++ * spi_nand_isbad_bbt - [SPI-NAND Interface] Check if a block is bad ++ * @mtd: MTD device structure ++ * @offs: offset in the device ++ * @allowbbt: allow access to bad block table region ++ */ ++int spi_nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int block, res; ++ ++ block = (int)(offs >> this->block_shift); ++ res = bbt_get_entry(this, block); ++ ++ pr_debug("%s: bbt info for offs 0x%08x: (block %d) 0x%02x\n", ++ __func__, (unsigned int)offs, block, res); ++ ++ switch (res) { ++ case BBT_BLOCK_GOOD: ++ return 0; ++ case BBT_BLOCK_WORN: ++ return 1; ++ case BBT_BLOCK_RESERVED: ++ return allowbbt ? 0 : 1; ++ } ++ return 1; ++} ++EXPORT_SYMBOL(spi_nand_isbad_bbt); ++/** ++ * spi_nand_markbad_bbt - [SPI-NAND Interface] Mark a block bad in the BBT ++ * @mtd: MTD device structure ++ * @offs: offset of the bad block ++ */ ++int spi_nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) ++{ ++ struct spi_nand_chip *this = mtd->priv; ++ int block, ret = 0; ++ ++ block = (int)(offs >> this->block_shift); ++ ++ /* Mark bad block in memory */ ++ bbt_mark_entry(this, block, BBT_BLOCK_WORN); ++ ++ /* Update flash-based bad block table */ ++ if (this->bbt_options & NAND_BBT_USE_FLASH) ++ ret = spi_nand_update_bbt(mtd, offs); ++ ++ return ret; ++} ++EXPORT_SYMBOL(spi_nand_markbad_bbt); +diff --git a/drivers/mtd/spi-nand/spi-nand-device.c b/drivers/mtd/spi-nand/spi-nand-device.c +new file mode 100644 +index 00000000..5f7d5160 +--- /dev/null ++++ b/drivers/mtd/spi-nand/spi-nand-device.c +@@ -0,0 +1,286 @@ ++/* ++ * Copyright (c) 2009-2014 Micron Technology, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/mtd/nand.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++#include <linux/mtd/spi-nand.h> ++#include "spi-nand-ids.h" ++ ++#ifdef SPINAND_BBT_DEBUG ++#define fh_dev_debug dev_err ++#else ++#define fh_dev_debug(...) ++#endif ++ ++static int spi_nand_read_id(struct spi_nand_chip *chip, u8 *buf) ++{ ++ struct spi_device *spi = chip->spi; ++ struct spi_nand_cmd cmd = { 0 }; ++ ++ cmd.cmd = SPINAND_CMD_READ_ID; ++ cmd.n_rx = SPINAND_MAX_ID_LEN; ++ cmd.rx_buf = buf; ++ ++ return spi_nand_send_cmd(spi, &cmd); ++} ++ ++static void spi_nand_ecc_status(struct spi_nand_chip *chip, unsigned int status, ++ unsigned int *corrected, unsigned int *ecc_error) ++{ ++ unsigned int ecc_status = (status >> SPI_NAND_ECC_SHIFT) & ++ chip->ecc_mask; ++ ++ *ecc_error = (ecc_status == chip->ecc_uncorr); ++ if (*ecc_error == 0) ++ *corrected = ecc_status; ++} ++ ++static void spi_nand_mt29f_ecc_status(unsigned int status, ++ unsigned int *corrected, unsigned int *ecc_error) ++{ ++ unsigned int ecc_status = (status >> SPI_NAND_MT29F_ECC_SHIFT) & ++ SPI_NAND_MT29F_ECC_MASK; ++ ++ *ecc_error = (ecc_status == SPI_NAND_MT29F_ECC_UNCORR); ++ if (*ecc_error == 0) ++ *corrected = ecc_status; ++} ++ ++static void spi_nand_gd5f_ecc_status(unsigned int status, ++ unsigned int *corrected, unsigned int *ecc_error) ++{ ++ unsigned int ecc_status = (status >> SPI_NAND_GD5F_ECC_SHIFT) & ++ SPI_NAND_GD5F_ECC_MASK; ++ ++ *ecc_error = (ecc_status == SPI_NAND_GD5F_ECC_UNCORR); ++ /*TODO fix corrected bits*/ ++ if (*ecc_error == 0) ++ *corrected = ecc_status; ++} ++ ++/*static int spi_nand_manufacture_init(struct spi_nand_chip *chip) ++{ ++ switch (chip->mfr_id) { ++ case SPINAND_MFR_MICRON: ++ chip->get_ecc_status = spi_nand_mt29f_ecc_status; ++ ++ if (chip->page_spare_size == 64) ++ chip->ecclayout = µn_ecc_layout_64; ++ ++ chip->bbt_options |= NAND_BBT_NO_OOB; ++ break; ++ case SPINAND_MFR_GIGADEVICE: ++ chip->get_ecc_status = spi_nand_gd5f_ecc_status; ++ chip->read_cache = spi_nand_read_from_cache_snor_protocol; ++ chip->ecc_strength_ds = 8; ++ chip->ecc_step_ds = chip->page_size >> 2; ++ if (chip->page_spare_size == 128) ++ chip->ecclayout = &gd5f_ecc_layout_128; ++ else if (chip->page_spare_size == 256) ++ chip->ecclayout = &gd5f_ecc_layout_256; ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++}*/ ++ ++static int spi_nand_device_probe(struct spi_device *spi) ++{ ++ struct spi_nand_chip *chip; ++ enum spi_nand_device_variant variant; ++ struct mtd_info *mtd; ++ /* struct mtd_part_parser_data ppdata;*/ ++ struct mtd_partition *parts = NULL; ++ int nr_parts = 0; ++ int ret, i; ++ struct flash_platform_data *data; ++ struct spi_master *p_master; ++ ++ fh_dev_debug(&spi->dev, "%s with spi%d:%d \n", __func__, ++ spi->master->bus_num, spi->chip_select); ++ ++ p_master = spi->master; ++ if (p_master->ctl_multi_wire_info.ctl_wire_support ++ & (DUAL_WIRE_SUPPORT|QUAD_WIRE_SUPPORT)) { ++ /*if master support multi wire, set one wire here..*/ ++ p_master->ctl_multi_wire_info.change_to_1_wire(p_master); ++ } ++ ++ data = spi->dev.platform_data; ++ chip = kzalloc(sizeof(struct spi_nand_chip), GFP_KERNEL); ++ if (!chip) { ++ ret = -ENOMEM; ++ goto err1; ++ } ++ chip->spi = spi; ++ ++ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); ++ if (!mtd) { ++ ret = -ENOMEM; ++ goto err2; ++ } ++ mtd->priv = chip; ++ chip->mtd = mtd; ++ spi_set_drvdata(spi, chip); ++ /* ++ * read ID command format might be different for different manufactory ++ * such as, Micron SPI NAND need extra one dummy byte after perform ++ * read ID command but Giga device don't need. ++ * ++ * So, specify manufactory of device in device tree is obligatory ++ */ ++/* variant = spi_get_device_id(spi)->driver_data; ++ switch (variant) { ++ case SPI_NAND_MT29F: ++ chip->read_id = spi_nand_mt29f_read_id; ++ break; ++ case SPI_NAND_GD5F: ++ chip->read_id = spi_nand_gd5f_read_id; ++ break; ++ default: ++ dev_err(&spi->dev, "unknown device, id %d\n", variant); ++ ret = -ENODEV; ++ goto err3; ++ }*/ ++ ++ spi->dev_open_multi_wire_flag = p_master->ctl_multi_wire_info.ctl_wire_support; ++ chip->read_id = spi_nand_read_id; ++ ret = spi_nand_scan_ident(mtd); ++ if (ret) { ++ ret = -ENODEV; ++ goto err3; ++ } ++ ++/* spi_nand_manufacture_init(chip);*/ ++ chip->get_ecc_status = spi_nand_ecc_status; ++ ++ ret = spi_nand_scan_tail(mtd); ++ if (ret) { ++ fh_dev_debug(&spi->dev, "goto err4 %s\n", __func__); ++ goto err4; ++ } ++ ++ /* partitions should match sector boundaries; and it may be good to ++ * use readonly partitions for writeprotected sectors (BP2..BP0). ++ */ ++ mtd->name = "spi0.0"; ++ if (mtd_has_cmdlinepart()) { ++ static const char *part_probes[] = { "cmdlinepart", NULL, }; ++ ++ nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0); ++ } ++ ++ if (nr_parts <= 0 && data && data->parts) { ++ parts = data->parts; ++ nr_parts = data->nr_parts; ++ } ++ ++ if (nr_parts > 0) { ++ for (i = 0; i < nr_parts; i++) { ++ DEBUG(MTD_DEBUG_LEVEL2, ++ "partitions[%d] = " "{.name = %s, .offset = 0x%llx, " ++ ".size = 0x%llx (%lldKiB) }\n", ++ i, parts[i].name, (long long)parts[i].offset, ++ (long long)parts[i].size, ++ (long long)(parts[i].size >> 10)); ++ } ++ } ++ ++ fh_dev_debug(&spi->dev, " mtd_device_register %s\n", __func__); ++ ret = mtd_device_register(mtd, parts, nr_parts); ++ if (!ret) ++ return 0; ++ ++ fh_dev_debug(&spi->dev, " spi_nand_scan_tail_release %s\n", __func__); ++ spi_nand_scan_tail_release(mtd); ++ fh_dev_debug(&spi->dev, "Leave %s\n", __func__); ++err4: ++ spi_nand_scan_ident_release(mtd); ++err3: ++ kfree(mtd); ++err2: ++ kfree(chip); ++err1: ++ return ret; ++} ++ ++int spi_nand_device_remove(struct spi_device *spi) ++{ ++ struct spi_nand_chip *chip = spi_get_drvdata(spi); ++ struct mtd_info *mtd = chip->mtd; ++ ++ spi_nand_release(mtd); ++ kfree(mtd); ++ kfree(chip); ++ ++ return 0; ++} ++ ++const struct spi_device_id spi_nand_id_table[] = { ++ { "spi-nand", SPI_NAND_GENERIC}, ++ { "mt29f", SPI_NAND_MT29F }, ++ { "gd5f", SPI_NAND_GD5F }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(spi, spi_nand_id_table); ++ ++/** ++ * module_spi_driver() - Helper macro for registering a SPI driver ++ * @__spi_driver: spi_driver struct ++ * ++ * Helper macro for SPI drivers which do not do anything special in module ++ * init/exit. This eliminates a lot of boilerplate. Each module may only ++ * use this macro once, and calling it replaces module_init() and module_exit() ++ */ ++#define module_spi_driver(__spi_driver) \ ++ module_driver(__spi_driver, spi_register_driver, \ ++ spi_unregister_driver) ++ ++static struct spi_driver spi_nand_device_driver = { ++ .driver = { ++ .name = "spi-nand", ++ .bus = &spi_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .id_table = spi_nand_id_table, ++ .probe = spi_nand_device_probe, ++ .remove = spi_nand_device_remove, ++}; ++ ++static int __init spi_nand_init(void) ++{ ++ return spi_register_driver(&spi_nand_device_driver); ++} ++ ++static void __exit spi_nand_exit(void) ++{ ++ spi_unregister_driver(&spi_nand_device_driver); ++} ++ ++module_init(spi_nand_init); ++module_exit(spi_nand_exit); ++ ++MODULE_DESCRIPTION("SPI NAND device"); ++MODULE_AUTHOR("Peter Pan<peterpandong at micron.com>"); ++MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia at imgtec.com>"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/drivers/mtd/spi-nand/spi-nand-ids.c b/drivers/mtd/spi-nand/spi-nand-ids.c +new file mode 100644 +index 00000000..00347a97 +--- /dev/null ++++ b/drivers/mtd/spi-nand/spi-nand-ids.c +@@ -0,0 +1,453 @@ ++/* ++ * Copyright (c) 2016 Fullhan, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include <linux/mtd/spi-nand.h> ++ ++/*static struct spi_nand_flash spi_nand_table[] = { ++ SPI_NAND_INFO("MT29F2G01AAAED", 0x2C, 0X22, 2048, 64, 64, 2048, ++ SPINAND_NEED_PLANE_SELECT), ++ SPI_NAND_INFO("MT29F4G01AAADD", 0x2C, 0X32, 2048, 64, 64, 4096, ++ SPINAND_NEED_PLANE_SELECT), ++ SPI_NAND_INFO("GD5F 512MiB 1.8V", 0xC8, 0XA4, 4096, 256, 64, 2048, ++ 0), ++ SPI_NAND_INFO("GD5F 512MiB 3.3V", 0xC8, 0XB4, 4096, 256, 64, 2048, ++ 0), ++ SPI_NAND_INFO("GD5F 256MiB 3.3V", 0xC8, 0XB2, 2048, 128, 64, 2048, ++ 0), ++ SPI_NAND_INFO("GD5F 128MiB 3.3V", 0xC8, 0XB1, 2048, 128, 64, 1024, ++ 0), ++ SPI_NAND_INFO("W25N01GV", 0xEF, 0XAA21, 2048, 64, 64, 1024, ++ 0), ++ {.name = NULL}, ++};*/ ++ ++/** ++* Default OOB area specification layout ++*/ ++static struct nand_ecclayout ecc_layout_64 = { ++ .eccbytes = 32, ++ .eccpos = { ++ 8, 9, 10, 11, 12, 13, 14, 15, ++ 24, 25, 26, 27, 28, 29, 30, 21, ++ 40, 41, 42, 43, 44, 45, 46, 47, ++ 56, 57, 58, 59, 60, 61, 62, 63 ++ }, ++ .oobavail = 30, ++ .oobfree = { ++ { ++ .offset = 2, ++ .length = 6 ++ }, { ++ .offset = 16, ++ .length = 8 ++ }, { ++ .offset = 32, ++ .length = 8 ++ }, { ++ .offset = 48, ++ .length = 8 ++ }, ++ } ++}; ++ ++static struct nand_ecclayout gd5f_ecc_layout_256 = { ++ .eccbytes = 128, ++ .eccpos = { ++ 128, 129, 130, 131, 132, 133, 134, 135, ++ 136, 137, 138, 139, 140, 141, 142, 143, ++ 144, 145, 146, 147, 148, 149, 150, 151, ++ 152, 153, 154, 155, 156, 157, 158, 159, ++ 160, 161, 162, 163, 164, 165, 166, 167, ++ 168, 169, 170, 171, 172, 173, 174, 175, ++ 176, 177, 178, 179, 180, 181, 182, 183, ++ 184, 185, 186, 187, 188, 189, 190, 191, ++ 192, 193, 194, 195, 196, 197, 198, 199, ++ 200, 201, 202, 203, 204, 205, 206, 207, ++ 208, 209, 210, 211, 212, 213, 214, 215, ++ 216, 217, 218, 219, 220, 221, 222, 223, ++ 224, 225, 226, 227, 228, 229, 230, 231, ++ 232, 233, 234, 235, 236, 237, 238, 239, ++ 240, 241, 242, 243, 244, 245, 246, 247, ++ 248, 249, 250, 251, 252, 253, 254, 255 ++ }, ++ .oobavail = 127, ++ .oobfree = { {1, 127} } ++}; ++ ++static struct nand_ecclayout gd5f_ecc_layout_128 = { ++ .eccbytes = 64, ++ .eccpos = { ++ 64, 65, 66, 67, 68, 69, 70, 72, ++ 72, 73, 74, 75, 76, 77, 78, 79, ++ 80, 81, 82, 83, 84, 85, 86, 87, ++ 88, 89, 90, 91, 92, 93, 94, 95, ++ 96, 97, 98, 99, 100, 101, 102, 103, ++ 104, 105, 106, 107, 108, 109, 110, 111, ++ 112, 113, 114, 115, 116, 117, 118, 119, ++ 120, 121, 122, 123, 124, 125, 126, 127, ++ }, ++ .oobavail = 62, ++ .oobfree = { {2, 63} } ++}; ++ ++static struct nand_ecclayout pn26_ecc_layout_128 = { ++ .eccbytes = 52, ++ .eccpos = { ++ 6, 7, 8, 9, 10, 11, 12, 13, 14,15,16,17,18, ++ 21,22,23,24,25,26,27,28,29,30,31,32,33, ++ 36,37,38,39,40,41,42,43,44,45,46,47,48, ++ 51,52,53,54,55,56,57,58,59,60,61,62,63 ++ }, ++ .oobavail = 72, ++ .oobfree = { ++ { ++ .offset = 4, ++ .length = 2 ++ }, { ++ .offset = 19, ++ .length = 2 ++ }, { ++ .offset = 34, ++ .length = 2 ++ }, { ++ .offset = 49, ++ .length = 2 ++ }, ++ { ++ .offset = 64, ++ .length = 64 ++ }, ++ } ++}; ++ ++static struct nand_ecclayout default_ecc_layout = { ++ .eccbytes = 64, ++ .oobavail = 28, ++ .oobfree = { { 2, 30 } } ++}; ++ ++static struct nand_ecclayout mx35_ecc_layout_64 = { ++ .eccbytes = 0, ++ .oobavail = 62, ++ .oobfree = { {2, 62} } ++}; ++ ++static struct nand_ecclayout mt29f_ecc_layout_128 = { ++ .eccbytes = 64, ++ .oobavail = 60, ++ .oobfree = { {4, 60} } ++}; ++static struct nand_ecclayout tc58_ecc_layout_64 = { ++ .eccbytes = 0, ++ .oobavail = 60, ++ .oobfree = { {4, 60} } ++}; ++ ++static struct nand_ecclayout ds35_ecc_layout_64 = { ++ .eccbytes = 16, ++ .oobavail = 32, ++ .oobfree = { ++ { ++ .offset = 8, ++ .length = 8 ++ }, { ++ .offset = 24, ++ .length = 8 ++ }, { ++ .offset = 40, ++ .length = 8 ++ }, { ++ .offset = 56, ++ .length = 8 ++ }, ++ } ++}; ++ ++ ++static struct spi_nand_flash spi_nand_table[] = { ++ { ++ .name = "W25N01GV", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 3, ++ }, ++ .dev_id = {0xEF, 0xAA, 0x21}, ++ .page_size = 2048, ++ .page_spare_size = 64, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &ecc_layout_64, ++ .qe_addr = 0xa0, ++ .qe_flag = 0x0, ++ .qe_mask = 1<<1, ++ .multi_wire_command_length = 4, ++ }, ++ { ++ .name = "MX35LF1GE4AB", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xC2, 0x12}, ++ .page_size = 2048, ++ .page_spare_size = 64, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &mx35_ecc_layout_64, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 4, ++ }, ++ { ++ .name = "MX35LF2GE4AB", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xC2, 0x22}, ++ .page_size = 2048, ++ .page_spare_size = 64, ++ .pages_per_blk = 64, ++ .blks_per_chip = 2048, ++ .options = SPINAND_NEED_PLANE_SELECT, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &mx35_ecc_layout_64, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 4, ++ }, ++ { ++ .name = "GD5F1GQ4U", ++ .id_info = { ++ .id_addr = SPI_NAND_ID_NO_DUMMY, ++ .id_len = 3, ++ }, ++ .dev_id = {0xC8, 0xB1, 0x48}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 7, ++ .ecc_uncorr = 7, ++ .ecc_layout = &gd5f_ecc_layout_128, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 5, ++ }, ++ { ++ .name = "GD5F2GQ4U", ++ .id_info = { ++ .id_addr = SPI_NAND_ID_NO_DUMMY, ++ .id_len = 3, ++ }, ++ .dev_id = {0xC8, 0xB2, 0x48}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 7, ++ .ecc_uncorr = 7, ++ .ecc_layout = &gd5f_ecc_layout_128, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 5, ++ }, ++ { ++ .name = "GD5F2GQ4UB", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xD2, 0xC8}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 2048, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &gd5f_ecc_layout_128, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 4, ++ }, ++ { ++ .name = "GD5F1GQ4UB", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xD1, 0xC8}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &gd5f_ecc_layout_128, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 4, ++ }, ++ { ++ .name = "PN26G01A", ++ .id_info = { ++ .id_addr = 0x0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xA1, 0xE1}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &pn26_ecc_layout_128, ++ .qe_addr = 0xb0, ++ .qe_flag = 0x1, ++ .qe_mask = 1<<0, ++ .multi_wire_command_length = 4, ++ }, ++ /*MT29F1G01*/ ++ { ++ .name = "MT29F1G01", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0x2c, 0x14}, ++ .page_size = 2048, ++ .page_spare_size = 128, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &mt29f_ecc_layout_128, ++ .qe_addr = 0xa0, ++ .qe_mask = 1<<1, ++ .qe_flag = 0, ++ .multi_wire_command_length = 4, ++ }, ++ /*TC58CVG0S3H*/ ++ { ++ .name = "TC58CVG0S3H", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0x98, 0xc2}, ++ .page_size = 2048, ++ .page_spare_size = 64, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &tc58_ecc_layout_64, ++ .qe_addr = 0xa0, ++ .qe_mask = 1<<1, ++ .qe_flag = 0, ++ .multi_wire_command_length = 4, ++ }, ++ /*DS35X1GA*/ ++ { ++ .name = "DS35X1GA", ++ .id_info = { ++ .id_addr = 0, ++ .id_len = 2, ++ }, ++ .dev_id = {0xe5, 0x71}, ++ .page_size = 2048, ++ .page_spare_size = 64, ++ .pages_per_blk = 64, ++ .blks_per_chip = 1024, ++ .options = 0, ++ .ecc_mask = 3, ++ .ecc_uncorr = 2, ++ .ecc_layout = &ds35_ecc_layout_64, ++ .qe_addr = 0xb0, ++ .qe_mask = 1<<0, ++ .qe_flag = 1, ++ .multi_wire_command_length = 4, ++ }, ++ ++ ++}; ++ ++/** ++ * spi_nand_scan_id_table - [INTERN] scan chip info in id table ++ * @chip: SPI-NAND device structure ++ * @id: point to manufacture id and device id ++ */ ++bool spi_nand_scan_id_table(struct spi_nand_chip *chip, u8 *id) ++{ ++ int i, j = 0; ++ struct spi_nand_flash *type = spi_nand_table; ++ int m=0; ++ ++ for (m=0; m<ARRAY_SIZE(spi_nand_table); m++,type++) { ++// if (id[0] == type->mfr_id && id[1] == type->dev_id) { ++ for (j=0, i = (SPI_NAND_ID_NO_DUMMY == type->id_info.id_addr) ? 0 : 1; ++ j < type->id_info.id_len;j++,i++ ) { ++ if (id[i] != type->dev_id[j]) ++ break; ++ } ++ if (j == type->id_info.id_len) { ++ chip->name = type->name; ++ chip->size = type->page_size * type->pages_per_blk ++ * type->blks_per_chip; ++ chip->block_size = type->page_size ++ * type->pages_per_blk; ++ chip->page_size = type->page_size; ++ chip->page_spare_size = type->page_spare_size; ++ chip->block_shift = ilog2(chip->block_size); ++ chip->page_shift = ilog2(chip->page_size); ++ chip->page_mask = chip->page_size - 1; ++ chip->options = type->options; ++ if (!type->ecc_layout) ++ chip->ecclayout = &default_ecc_layout; ++ else ++ chip->ecclayout = type->ecc_layout; ++ chip->dev_id_len = type->id_info.id_len; ++ chip->ecc_uncorr = type->ecc_uncorr; ++ chip->ecc_mask = type->ecc_mask; ++ memcpy(chip->dev_id, type->dev_id, chip->dev_id_len); ++ chip->qe_addr = type->qe_addr; ++ chip->qe_flag = type->qe_flag; ++ chip->qe_mask = type->qe_mask; ++ chip->multi_wire_command_length = ++ type->multi_wire_command_length; ++ return true; ++ } ++ } ++ return false; ++} +diff --git a/drivers/mtd/spi-nand/spi-nand-ids.h b/drivers/mtd/spi-nand/spi-nand-ids.h +new file mode 100644 +index 00000000..c488eee5 +--- /dev/null ++++ b/drivers/mtd/spi-nand/spi-nand-ids.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2016 Fullhan, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++ ++#ifndef DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_ ++#define DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_ ++ ++enum spi_nand_device_variant { ++ SPI_NAND_GENERIC, ++ SPI_NAND_MT29F, ++ SPI_NAND_GD5F, ++}; ++ ++ ++bool spi_nand_scan_id_table(struct spi_nand_chip *chip, u8 *id); ++ ++#endif /* DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_ */ +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 93359fab..828c6445 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -984,6 +984,8 @@ config DM9000 + + To compile this driver as a module, choose M here. The module + will be called dm9000. ++ ++source "drivers/net/fh_gmac/Kconfig" + + config DM9000_DEBUGLEVEL + int "DM9000 maximum debug level" +@@ -2542,6 +2544,7 @@ config S6GMAC + + source "drivers/net/stmmac/Kconfig" + ++ + config PCH_GBE + tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE" + depends on PCI +@@ -3450,4 +3453,6 @@ config VMXNET3 + To compile this driver as a module, choose M here: the + module will be called vmxnet3. + ++ ++ + endif # NETDEVICES +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index d5ce0115..7bc4daa1 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -254,6 +254,7 @@ obj-$(CONFIG_SMSC911X) += smsc911x.o + obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o + obj-$(CONFIG_BFIN_MAC) += bfin_mac.o + obj-$(CONFIG_DM9000) += dm9000.o ++obj-$(CONFIG_FH_GMAC) += fh_gmac/ + obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o + pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o + obj-$(CONFIG_MLX4_CORE) += mlx4/ +diff --git a/drivers/net/fh_gmac/Kconfig b/drivers/net/fh_gmac/Kconfig +new file mode 100644 +index 00000000..55134815 +--- /dev/null ++++ b/drivers/net/fh_gmac/Kconfig +@@ -0,0 +1,21 @@ ++config FH_GMAC ++ tristate "FH 10/100 Ethernet driver" ++ select MII ++ select PHYLIB ++ select CRC32 ++ depends on NETDEVICES && HAS_IOMEM ++ help ++ This is the driver for the Ethernet IPs are built around a ++ Synopsys IP Core. ++ ++if FH_GMAC ++ ++config FH_GMAC_DA ++ bool "FH GMAC DMA arbitration scheme" ++ default n ++ help ++ Selecting this option, rx has priority over Tx (only for Giga ++ Ethernet device). ++ By default, the DMA arbitration scheme is based on Round-robin ++ (rx:tx priority is 1:1). ++endif +diff --git a/drivers/net/fh_gmac/Makefile b/drivers/net/fh_gmac/Makefile +new file mode 100644 +index 00000000..e22c42f1 +--- /dev/null ++++ b/drivers/net/fh_gmac/Makefile +@@ -0,0 +1,5 @@ ++ ++ ++obj-$(CONFIG_FH_GMAC) += fh_gmac.o ++ ++fh_gmac-objs := fh_gmac_dma.o fh_gmac_main.o fh_gmac_ethtool.o fh_gmac_phyt.o +diff --git a/drivers/net/fh_gmac/fh_gmac.h b/drivers/net/fh_gmac/fh_gmac.h +new file mode 100755 +index 00000000..513fd6a1 +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac.h +@@ -0,0 +1,245 @@ ++/* ++ * fh_gmac.h ++ * ++ * Created on: May 22, 2014 ++ * Author: duobao ++ */ ++ ++#ifndef FH_GMAC_H_ ++#define FH_GMAC_H_ ++ ++#include <linux/phy.h> ++#include <linux/etherdevice.h> ++ ++#include "fh_gmac_phyt.h" ++#include "fh_gmac_dma.h" ++ ++//GMAC-MAC ++#define REG_GMAC_CONFIG (0x0000) ++#define REG_GMAC_FRAME_FILTER (0x0004) ++#define REG_GMAC_HASH_HIGH (0x0008) ++#define REG_GMAC_HASH_LOW (0x000C) ++#define REG_GMAC_GMII_ADDRESS (0x0010) ++#define REG_GMAC_GMII_DATA (0x0014) ++#define REG_GMAC_FLOW_CTRL (0x0018) ++#define REG_GMAC_DEBUG (0x0024) ++#define REG_GMAC_MAC_HIGH (0x0040) ++#define REG_GMAC_MAC_LOW (0x0044) ++//GMAC-DMA ++#define REG_GMAC_BUS_MODE (0x1000) ++#define REG_GMAC_TX_POLL_DEMAND (0x1004) ++#define REG_GMAC_RX_POLL_DEMAND (0x1008) ++#define REG_GMAC_RX_DESC_ADDR (0x100C) ++#define REG_GMAC_TX_DESC_ADDR (0x1010) ++#define REG_GMAC_STATUS (0x1014) ++#define REG_GMAC_OP_MODE (0x1018) ++#define REG_GMAC_INTR_EN (0x101C) ++#define REG_GMAC_ERROR_COUNT (0x1020) ++#define REG_GMAC_AXI_BUS_MODE (0x1028) ++#define REG_GMAC_AXI_STATUS (0x102C) ++#define REG_GMAC_CURR_TX_DESC (0x1048) ++#define REG_GMAC_CURR_RX_DESC (0x104C) ++ ++enum tx_dma_irq_status { ++ tx_hard_error = 1, ++ tx_hard_error_bump_tc = 2, ++ handle_tx_rx = 3, ++}; ++ ++enum rx_frame_status { ++ good_frame = 0, ++ discard_frame = 1, ++ csum_none = 2, ++ llc_snap = 4, ++}; ++ ++#define GMAC_MIN_ETHPKTSIZE (60) /* Minimum ethernet pkt size */ ++#define GMAC_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) ++ ++#define BUFFER_SIZE_2K 2048 ++#define BUFFER_SIZE_4K 4096 ++#define BUFFER_SIZE_8K 8192 ++#define BUFFER_SIZE_16K 16384 ++ ++#ifdef FH_GMAC_DMA_DEBUG ++#define GMAC_DMA_DBG(fmt, args...) printk(fmt, ## args) ++#else ++#define GMAC_DMA_DBG(fmt, args...) do { } while (0) ++#endif ++ ++#ifdef FH_GMAC_XMIT_DEBUG ++#define TX_DBG(fmt, args...) printk(fmt, ## args) ++#else ++#define TX_DBG(fmt, args...) do { } while (0) ++#endif ++ ++#ifdef FH_GMAC_RX_DEBUG ++#define RX_DBG(fmt, args...) printk(fmt, ## args) ++#else ++#define RX_DBG(fmt, args...) do { } while (0) ++#endif ++ ++#define FH_GMAC_DEBUG ( NETIF_MSG_DRV | \ ++ NETIF_MSG_PROBE | \ ++ NETIF_MSG_LINK | \ ++ NETIF_MSG_TIMER | \ ++ NETIF_MSG_IFDOWN | \ ++ NETIF_MSG_IFUP | \ ++ NETIF_MSG_RX_ERR | \ ++ NETIF_MSG_TX_ERR | \ ++ NETIF_MSG_TX_QUEUED | \ ++ NETIF_MSG_INTR | \ ++ NETIF_MSG_TX_DONE | \ ++ NETIF_MSG_RX_STATUS | \ ++ NETIF_MSG_PKTDATA | \ ++ NETIF_MSG_HW | \ ++ NETIF_MSG_WOL ) ++ ++enum { ++ gmac_gmii_clock_60_100, ++ gmac_gmii_clock_100_150, ++ gmac_gmii_clock_20_35, ++ gmac_gmii_clock_35_60, ++ gmac_gmii_clock_150_250, ++ gmac_gmii_clock_250_300 ++}; ++ ++enum { ++ gmac_interrupt_all = 0x0001ffff, ++ gmac_interrupt_none = 0x0 ++}; ++ ++typedef struct Gmac_Stats { ++ /* Transmit errors */ ++ unsigned long tx_underflow ____cacheline_aligned; ++ unsigned long tx_carrier; ++ unsigned long tx_losscarrier; ++ unsigned long tx_heartbeat; ++ unsigned long tx_deferred; ++ unsigned long tx_vlan; ++ unsigned long tx_jabber; ++ unsigned long tx_frame_flushed; ++ unsigned long tx_payload_error; ++ unsigned long tx_ip_header_error; ++ /* Receive errors */ ++ unsigned long rx_desc; ++ unsigned long rx_partial; ++ unsigned long rx_runt; ++ unsigned long rx_toolong; ++ unsigned long rx_collision; ++ unsigned long rx_crc; ++ unsigned long rx_length; ++ unsigned long rx_mii; ++ unsigned long rx_multicast; ++ unsigned long rx_gmac_overflow; ++ unsigned long rx_watchdog; ++ unsigned long da_rx_filter_fail; ++ unsigned long sa_rx_filter_fail; ++ unsigned long rx_missed_cntr; ++ unsigned long rx_overflow_cntr; ++ /* Tx/Rx IRQ errors */ ++ unsigned long tx_undeflow_irq; ++ unsigned long tx_process_stopped_irq; ++ unsigned long tx_jabber_irq; ++ unsigned long rx_overflow_irq; ++ unsigned long rx_buf_unav_irq; ++ unsigned long rx_process_stopped_irq; ++ unsigned long rx_watchdog_irq; ++ unsigned long tx_early_irq; ++ unsigned long fatal_bus_error_irq; ++ /* Extra info */ ++ unsigned long threshold; ++ unsigned long tx_pkt_n; ++ unsigned long rx_pkt_n; ++ unsigned long poll_n; ++ unsigned long sched_timer_n; ++ unsigned long normal_irq_n; ++}Gmac_Stats; ++ ++typedef struct Gmac_Object { ++ Gmac_Tx_DMA_Descriptors* tx_dma_descriptors ____cacheline_aligned; ++ Gmac_Rx_DMA_Descriptors* rx_dma_descriptors; ++ int full_duplex; //read only ++ int speed_100m; //read only ++ ++ struct sk_buff_head rx_recycle; ++ struct sk_buff** rx_skbuff; ++ struct sk_buff** tx_skbuff; ++ dma_addr_t* rx_skbuff_dma; ++ __u32 cur_rx; ++ __u32 dirty_rx; ++ __u32 cur_tx; ++ __u32 dirty_tx; ++ dma_addr_t tx_bus_addr; ++ dma_addr_t rx_bus_addr; ++ __u32 dma_tx_size; ++ __u32 dma_rx_size; ++ __u32 dma_buf_sz; ++ ++ spinlock_t lock; ++ ++ void __iomem *remap_addr; ++ __u8 local_mac_address[6]; ++ __u32 msg_enable; ++ struct device* dev; ++ struct net_device* ndev; ++ struct platform_device* pdev; ++ struct napi_struct napi; ++ struct mii_bus *mii; ++ struct phy_device *phydev; ++ Gmac_Stats stats; ++ ++ int oldlink; ++ int speed; ++ int oldduplex; ++ __u32 flow_ctrl; ++ __u32 pause; ++ ++ int wolopts; ++ int wolenabled; ++ ++ int phy_interface; ++ struct fh_gmac_platform_data* priv_data; ++ ++ struct clk* clk; ++ ++}Gmac_Object; ++ ++#define TX_TIMEO 5000 /* default 5 seconds */ ++#define DMA_RX_SIZE 256 ++#define DMA_TX_SIZE 256 ++#define FLOW_OFF 0 ++#define FLOW_RX 4 ++#define FLOW_TX 2 ++#define FLOW_AUTO (FLOW_TX | FLOW_RX) ++#define PAUSE_TIME 0x200 ++ ++int fh_mdio_register(struct net_device *ndev); ++int fh_mdio_unregister(struct net_device *ndev); ++ ++void GMAC_DMA_StartTx(Gmac_Object* pGmac); ++void GMAC_DMA_StopTx(Gmac_Object* pGmac); ++void GMAC_DMA_StartRx(Gmac_Object* pGmac); ++void GMAC_DMA_StopRx(Gmac_Object* pGmac); ++ ++void fh_gmac_set_ethtool_ops(struct net_device *netdev); ++ ++void GMAC_DMA_InitDescRings(struct net_device *ndev); ++int GMAC_DMA_Init(struct net_device *ndev, __u32 dma_tx, __u32 dma_rx); ++void GMAC_DMA_InitRxDesc(Gmac_Rx_DMA_Descriptors* desc, unsigned int size); ++void GMAC_DMA_InitTxDesc(Gmac_Tx_DMA_Descriptors* desc, unsigned int size); ++void GMAC_DMA_OpMode(Gmac_Object* pGmac); ++void GMAC_DMA_FreeDesc(Gmac_Object* pGmac); ++void GMAC_DMA_FreeRxSkbufs(Gmac_Object* pGmac); ++void GMAC_DMA_FreeTxSkbufs(Gmac_Object* pGmac); ++void GMAC_DMA_DisplayRxDesc(Gmac_Rx_DMA_Descriptors* desc, int size); ++void GMAC_DMA_DisplayTxDesc(Gmac_Tx_DMA_Descriptors* desc, int size); ++int GMAC_DMA_Interrupt(Gmac_Object* pGmac); ++int GMAC_DMA_TxStatus(Gmac_Object* pGmac, Gmac_Tx_DMA_Descriptors* desc); ++int GMAC_DMA_RxStatus(Gmac_Object* pGmac, Gmac_Rx_DMA_Descriptors* desc); ++void GMAC_DMA_ReleaseTxDesc(Gmac_Tx_DMA_Descriptors* desc); ++void GMAC_DMA_DiagnosticFrame(void *data, Gmac_Object* pGmac); ++void GMAC_FlowCtrl(Gmac_Object * pGmac, unsigned int duplex, unsigned int fc, ++ unsigned int pause_time); ++ ++#endif /* FH_GMAC_H_ */ +diff --git a/drivers/net/fh_gmac/fh_gmac_dma.c b/drivers/net/fh_gmac/fh_gmac_dma.c +new file mode 100644 +index 00000000..9f11e146 +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_dma.c +@@ -0,0 +1,519 @@ ++#include <linux/io.h> ++#include <linux/dma-mapping.h> ++#include <asm/dma-mapping.h> ++#include <mach/fh_gmac.h> ++#include "fh_gmac.h" ++#include "fh_gmac_dma.h" ++ ++void GMAC_DMA_ReleaseTxDesc(Gmac_Tx_DMA_Descriptors * desc) ++{ ++ int ter = desc->desc1.bit.end_of_ring; ++ desc->desc0.dw = 0; ++ desc->desc1.dw = 0; ++ /* set termination field */ ++ desc->desc1.bit.end_of_ring = ter; ++} ++ ++void GMAC_DMA_DisplayRxDesc(Gmac_Rx_DMA_Descriptors * desc, int size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x DES2=0x%x DES3=0x%x", ++ i, (__u32) (&desc[i]), desc[i].desc0.dw, ++ desc[i].desc1.dw, desc[i].desc2.dw, desc[i].desc3.dw); ++ pr_info("\n"); ++ } ++} ++ ++void GMAC_DMA_DisplayTxDesc(Gmac_Tx_DMA_Descriptors * desc, int size) ++{ ++ int i; ++ pr_info("Tx desc:\n"); ++ for (i = 0; i < size; i++) { ++ pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x", ++ i, (__u32) & desc[i], desc[i].desc0.dw, ++ desc[i].desc1.dw, desc[i].desc2.dw, desc[i].desc3.dw); ++ pr_info("\n"); ++ } ++} ++ ++void GMAC_DMA_InitRxDesc(Gmac_Rx_DMA_Descriptors * desc, __u32 size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ desc->desc0.bit.own = 1; ++ desc->desc1.bit.buffer1_size = BUFFER_SIZE_2K - 1; ++ if (i == size - 1) { ++ desc->desc1.bit.end_of_ring = 1; ++ } ++ desc++; ++ } ++} ++ ++void GMAC_DMA_InitTxDesc(Gmac_Tx_DMA_Descriptors * desc, __u32 size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ desc->desc0.bit.own = 0; ++ if (i == size - 1) { ++ desc->desc1.bit.end_of_ring = 1; ++ } ++ desc++; ++ } ++} ++ ++void GMAC_DMA_OpMode(Gmac_Object * pGmac) ++{ ++ ++ //op mode, reg 6 ++ //transmit_store_forward ++ //receive_store_forward ++ writel(0 << 25 | 1 << 21 | 0 << 2 | 0 << 14, ++ pGmac->remap_addr + REG_GMAC_OP_MODE); ++} ++ ++void GMAC_DMA_InitDescRings(struct net_device *ndev) ++{ ++ int i; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct sk_buff *skb; ++ __u32 txsize = pGmac->dma_tx_size; ++ __u32 rxsize = pGmac->dma_rx_size; ++ __u32 bfsize = pGmac->dma_buf_sz; ++ ++ pGmac->rx_skbuff_dma = kmalloc(rxsize * sizeof(dma_addr_t), GFP_KERNEL); ++ pGmac->rx_skbuff = ++ kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL); ++ pGmac->rx_dma_descriptors = ++ (Gmac_Rx_DMA_Descriptors *) dma_alloc_coherent(pGmac->dev, ++ rxsize * ++ sizeof ++ (Gmac_Rx_DMA_Descriptors), ++ &pGmac->rx_bus_addr, ++ GFP_KERNEL); ++ pGmac->tx_skbuff = ++ kmalloc(sizeof(struct sk_buff *) * txsize, GFP_KERNEL); ++ pGmac->tx_dma_descriptors = ++ (Gmac_Tx_DMA_Descriptors *) dma_alloc_coherent(pGmac->dev, ++ txsize * ++ sizeof ++ (Gmac_Tx_DMA_Descriptors), ++ &pGmac->tx_bus_addr, ++ GFP_KERNEL); ++ ++ if ((pGmac->rx_dma_descriptors == NULL) ++ || (pGmac->tx_dma_descriptors == NULL)) { ++ pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__); ++ return; ++ } ++ ++ pr_debug("fh gmac (%s) DMA desc rings: virt addr (Rx %p, " ++ "Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n", ++ ndev->name, pGmac->rx_dma_descriptors, ++ pGmac->tx_dma_descriptors, (__u32) pGmac->rx_bus_addr, ++ (__u32) pGmac->tx_bus_addr); ++ ++ for (i = 0; i < rxsize; i++) { ++ Gmac_Rx_DMA_Descriptors *desc = pGmac->rx_dma_descriptors + i; ++ ++ skb = netdev_alloc_skb_ip_align(ndev, bfsize); ++ if (unlikely(skb == NULL)) { ++ pr_err("%s: Rx init fails; skb is NULL\n", __func__); ++ break; ++ } ++ pGmac->rx_skbuff[i] = skb; ++ pGmac->rx_skbuff_dma[i] = ++ dma_map_single(pGmac->dev, skb->data, bfsize, ++ DMA_FROM_DEVICE); ++ ++ desc->desc2.dw = pGmac->rx_skbuff_dma[i]; ++ } ++ pGmac->cur_rx = 0; ++ pGmac->dirty_rx = (__u32) (i - rxsize); ++ ++ pGmac->dma_buf_sz = bfsize; ++ ++ /* TX INITIALIZATION */ ++ for (i = 0; i < txsize; i++) { ++ pGmac->tx_skbuff[i] = NULL; ++ pGmac->tx_dma_descriptors[i].desc2.dw = 0; ++ } ++ pGmac->dirty_tx = 0; ++ pGmac->cur_tx = 0; ++ ++ /* Clear the Rx/Tx descriptors */ ++ GMAC_DMA_InitRxDesc(pGmac->rx_dma_descriptors, rxsize); ++ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, txsize); ++#ifdef FH_GMAC_DMA_DEBUG ++ if (netif_msg_hw(pGmac)) { ++ pr_info("RX descriptor ring:\n"); ++ GMAC_DMA_DisplayRxDesc(pGmac->rx_dma_descriptors, rxsize); ++ pr_info("TX descriptor ring:\n"); ++ GMAC_DMA_DisplayTxDesc(pGmac->tx_dma_descriptors, txsize); ++ } ++#endif ++} ++ ++void GMAC_DMA_FreeRxSkbufs(Gmac_Object * pGmac) ++{ ++ int i; ++ ++ for (i = 0; i < pGmac->dma_rx_size; i++) { ++ if (pGmac->rx_skbuff[i]) { ++ dma_unmap_single(pGmac->dev, pGmac->rx_skbuff_dma[i], ++ pGmac->dma_buf_sz, DMA_FROM_DEVICE); ++ dev_kfree_skb_any(pGmac->rx_skbuff[i]); ++ } ++ pGmac->rx_skbuff[i] = NULL; ++ } ++} ++ ++void GMAC_DMA_FreeTxSkbufs(Gmac_Object * pGmac) ++{ ++ int i; ++ ++ for (i = 0; i < pGmac->dma_tx_size; i++) { ++ if (pGmac->tx_skbuff[i] != NULL) { ++ Gmac_Tx_DMA_Descriptors *desc = ++ pGmac->tx_dma_descriptors + i; ++ if (desc->desc2.dw) { ++ __u32 size; ++ size = desc->desc1.bit.buffer1_size; ++ dma_unmap_single(pGmac->dev, desc->desc2.dw, ++ size, DMA_TO_DEVICE); ++ } ++ dev_kfree_skb_any(pGmac->tx_skbuff[i]); ++ pGmac->tx_skbuff[i] = NULL; ++ } ++ } ++} ++ ++void GMAC_DMA_FreeDesc(Gmac_Object * pGmac) ++{ ++ /* Release the DMA TX/RX socket buffers */ ++ GMAC_DMA_FreeRxSkbufs(pGmac); ++ GMAC_DMA_FreeTxSkbufs(pGmac); ++ ++ /* Free the region of consistent memory previously allocated for ++ * the DMA */ ++ dma_free_coherent(pGmac->dev, ++ pGmac->dma_tx_size * sizeof(Gmac_Tx_DMA_Descriptors), ++ pGmac->tx_dma_descriptors, pGmac->tx_bus_addr); ++ dma_free_coherent(pGmac->dev, ++ pGmac->dma_rx_size * sizeof(Gmac_Tx_DMA_Descriptors), ++ pGmac->rx_dma_descriptors, pGmac->rx_bus_addr); ++ kfree(pGmac->rx_skbuff_dma); ++ kfree(pGmac->rx_skbuff); ++ kfree(pGmac->tx_skbuff); ++} ++ ++int GMAC_DMA_Init(struct net_device *ndev, __u32 dma_tx, __u32 dma_rx) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++#ifdef GMAC_RESET ++ int limit; ++ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_BUS_MODE); ++ reg |= 0x1; ++ writel(reg, pGmac->remap_addr + REG_GMAC_BUS_MODE); ++ ++ limit = 10; ++ while (limit--) { ++ if (!(readl(pGmac->remap_addr + REG_GMAC_BUS_MODE) & 0x1)) { ++ break; ++ } ++ mdelay(10); ++ } ++ if (limit < 0) ++ return -EBUSY; ++#endif ++ //initialize dma bus mode reg0 ++ //8xpbl ++ //no address_aligned_beats ++ //no fixed_burst ++ writel(0 << 25 | 0 << 24 | 1 << 16 | 32 << 8, ++ pGmac->remap_addr + REG_GMAC_BUS_MODE); ++ writel(0x1a061, pGmac->remap_addr + REG_GMAC_INTR_EN); ++ /* The base address of the RX/TX descriptor lists must be written into ++ * DMA CSR3 and CSR4, respectively. */ ++ writel(dma_rx, pGmac->remap_addr + REG_GMAC_RX_DESC_ADDR); ++ writel(dma_tx, pGmac->remap_addr + REG_GMAC_TX_DESC_ADDR); ++ ++ return 0; ++} ++ ++void GMAC_DMA_StartTx(Gmac_Object * pGmac) ++{ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE); ++ reg |= 1 << 13; ++ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE); ++} ++ ++void GMAC_DMA_StopTx(Gmac_Object * pGmac) ++{ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE); ++ reg &= ~(1 << 13); ++ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE); ++} ++ ++void GMAC_DMA_StartRx(Gmac_Object * pGmac) ++{ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE); ++ reg |= 1 << 1; ++ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE); ++} ++ ++void GMAC_DMA_StopRx(Gmac_Object * pGmac) ++{ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE); ++ reg &= ~(1 << 1); ++ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE); ++} ++ ++#ifdef FH_GMAC_DMA_DEBUG ++static void GMAC_DMA_ShowTxState(__u32 status) ++{ ++ __u32 state; ++ state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT; ++ ++ switch (state) { ++ case 0: ++ pr_info("- TX (Stopped): Reset or Stop command\n"); ++ break; ++ case 1: ++ pr_info("- TX (Running):Fetching the Tx desc\n"); ++ break; ++ case 2: ++ pr_info("- TX (Running): Waiting for end of tx\n"); ++ break; ++ case 3: ++ pr_info("- TX (Running): Reading the data " ++ "and queuing the data into the Tx buf\n"); ++ break; ++ case 6: ++ pr_info("- TX (Suspended): Tx Buff Underflow " ++ "or an unavailable Transmit descriptor\n"); ++ break; ++ case 7: ++ pr_info("- TX (Running): Closing Tx descriptor\n"); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void GMAC_DMA_ShowRxState(__u32 status) ++{ ++ __u32 state; ++ state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT; ++ ++ switch (state) { ++ case 0: ++ pr_info("- RX (Stopped): Reset or Stop command\n"); ++ break; ++ case 1: ++ pr_info("- RX (Running): Fetching the Rx desc\n"); ++ break; ++ case 2: ++ pr_info("- RX (Running):Checking for end of pkt\n"); ++ break; ++ case 3: ++ pr_info("- RX (Running): Waiting for Rx pkt\n"); ++ break; ++ case 4: ++ pr_info("- RX (Suspended): Unavailable Rx buf\n"); ++ break; ++ case 5: ++ pr_info("- RX (Running): Closing Rx descriptor\n"); ++ break; ++ case 6: ++ pr_info("- RX(Running): Flushing the current frame" ++ " from the Rx buf\n"); ++ break; ++ case 7: ++ pr_info("- RX (Running): Queuing the Rx frame" ++ " from the Rx buf into memory\n"); ++ break; ++ default: ++ break; ++ } ++} ++#endif ++ ++int GMAC_DMA_Interrupt(Gmac_Object * pGmac) ++{ ++ int ret = 0; ++ Gmac_Stats *gmac_stats = &pGmac->stats; ++ /* read the status register (CSR5) */ ++ __u32 intr_status; ++ intr_status = readl(pGmac->remap_addr + REG_GMAC_STATUS); ++ ++ GMAC_DMA_DBG("%s: [GMAC_STATUS: 0x%08x]\n", __func__, intr_status); ++#ifdef FH_GMAC_DMA_DEBUG ++ /* It displays the DMA process states (CSR5 register) */ ++ GMAC_DMA_ShowTxState(intr_status); ++ GMAC_DMA_ShowRxState(intr_status); ++#endif ++ /* ABNORMAL interrupts */ ++ if (unlikely(intr_status & DMA_STATUS_AIS)) { ++ GMAC_DMA_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: "); ++ if (unlikely(intr_status & DMA_STATUS_UNF)) { ++ GMAC_DMA_DBG(KERN_INFO "transmit underflow\n"); ++ ret = tx_hard_error_bump_tc; ++ gmac_stats->tx_undeflow_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_TJT)) { ++ GMAC_DMA_DBG(KERN_INFO "transmit jabber\n"); ++ gmac_stats->tx_jabber_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_OVF)) { ++ GMAC_DMA_DBG(KERN_INFO "recv overflow\n"); ++ gmac_stats->rx_overflow_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_RU)) { ++ GMAC_DMA_DBG(KERN_INFO "receive buffer unavailable\n"); ++ gmac_stats->rx_buf_unav_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_RPS)) { ++ GMAC_DMA_DBG(KERN_INFO "receive process stopped\n"); ++ gmac_stats->rx_process_stopped_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_RWT)) { ++ GMAC_DMA_DBG(KERN_INFO "receive watchdog\n"); ++ gmac_stats->rx_watchdog_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_ETI)) { ++ GMAC_DMA_DBG(KERN_INFO "transmit early interrupt\n"); ++ gmac_stats->tx_early_irq++; ++ } ++ if (unlikely(intr_status & DMA_STATUS_TPS)) { ++ GMAC_DMA_DBG(KERN_INFO "transmit process stopped\n"); ++ gmac_stats->tx_process_stopped_irq++; ++ ret = tx_hard_error; ++ } ++ if (unlikely(intr_status & DMA_STATUS_FBI)) { ++ GMAC_DMA_DBG(KERN_INFO "fatal bus error\n"); ++ gmac_stats->fatal_bus_error_irq++; ++ ret = tx_hard_error; ++ } ++ } ++ /* TX/RX NORMAL interrupts */ ++ if (intr_status & DMA_STATUS_NIS) { ++ gmac_stats->normal_irq_n++; ++ if (likely((intr_status & DMA_STATUS_RI) || ++ (intr_status & (DMA_STATUS_TI)))) ++ ret = handle_tx_rx; ++ } ++ /* Optional hardware blocks, interrupts should be disabled */ ++ if (unlikely(intr_status & ++ (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) ++ pr_info("%s: unexpected status %08x\n", __func__, intr_status); ++ ++ /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ ++ writel(intr_status & 0x1ffff, pGmac->remap_addr + REG_GMAC_STATUS); ++ GMAC_DMA_DBG(KERN_INFO "\n\n"); ++ ++ return ret; ++} ++ ++int GMAC_DMA_TxStatus(Gmac_Object * pGmac, Gmac_Tx_DMA_Descriptors * desc) ++{ ++ int ret = 0; ++ struct net_device_stats *stats = &pGmac->ndev->stats; ++ Gmac_Stats *gmac_stats = &pGmac->stats; ++ ++ if (unlikely(desc->desc0.bit.error_summary)) { ++ if (unlikely(desc->desc0.bit.underflow_error)) { ++ gmac_stats->tx_underflow++; ++ stats->tx_fifo_errors++; ++ } ++ if (unlikely(desc->desc0.bit.no_carrier)) { ++ gmac_stats->tx_carrier++; ++ stats->tx_carrier_errors++; ++ } ++ if (unlikely(desc->desc0.bit.loss_of_carrier)) { ++ gmac_stats->tx_losscarrier++; ++ stats->tx_carrier_errors++; ++ } ++ if (unlikely((desc->desc0.bit.excessive_deferral) || ++ (desc->desc0.bit.excessive_collision) || ++ (desc->desc0.bit.late_collision))) ++ stats->collisions += desc->desc0.bit.collision_count; ++ ret = -1; ++ } ++ if (unlikely(desc->desc0.bit.deferred)) ++ gmac_stats->tx_deferred++; ++ ++ return ret; ++} ++ ++int GMAC_DMA_RxStatus(Gmac_Object * pGmac, Gmac_Rx_DMA_Descriptors * desc) ++{ ++ int ret = csum_none; ++ struct net_device_stats *stats = &pGmac->ndev->stats; ++ Gmac_Stats *gmac_stats = &pGmac->stats; ++ ++ if (unlikely(desc->desc0.bit.last_descriptor == 0)) { ++ pr_warning("ndesc Error: Oversized Ethernet " ++ "frame spanned multiple buffers\n"); ++ stats->rx_length_errors++; ++ return discard_frame; ++ } ++ ++ if (unlikely(desc->desc0.bit.error_summary)) { ++ if (unlikely(desc->desc0.bit.descriptor_error)) ++ gmac_stats->rx_desc++; ++ if (unlikely(desc->desc0.bit.ipc_chksum_error_giant_frame)) ++ gmac_stats->rx_toolong++; ++ if (unlikely(desc->desc0.bit.late_collision)) { ++ gmac_stats->rx_collision++; ++ stats->collisions++; ++ } ++ if (unlikely(desc->desc0.bit.crc_error)) { ++ gmac_stats->rx_crc++; ++ stats->rx_crc_errors++; ++ } ++ ret = discard_frame; ++ } ++ if (unlikely(desc->desc0.bit.dribble_error)) ++ ret = discard_frame; ++ ++ if (unlikely(desc->desc0.bit.length_error)) { ++ gmac_stats->rx_length++; ++ ret = discard_frame; ++ } ++ ++ return ret; ++} ++ ++void GMAC_DMA_DiagnosticFrame(void *data, Gmac_Object * pGmac) ++{ ++ struct net_device_stats *stats = (struct net_device_stats *)data; ++ Gmac_Stats *gmac_stats = &pGmac->stats; ++ __u32 csr8 = readl(pGmac->remap_addr + REG_GMAC_ERROR_COUNT); ++ ++ if (unlikely(csr8)) { ++ //Overflow bit for FIFO Overflow Counter ++ if (csr8 & 0x10000000) { ++ stats->rx_over_errors += 0x800; ++ gmac_stats->rx_overflow_cntr += 0x800; ++ } else { ++ unsigned int ove_cntr; ++ //indicates the number of frames missed by the application ++ ove_cntr = ((csr8 & 0x0ffe0000) >> 17); ++ stats->rx_over_errors += ove_cntr; ++ gmac_stats->rx_overflow_cntr += ove_cntr; ++ } ++ ++ //Overflow bit for Missed Frame Counter ++ if (csr8 & 0x10000) { ++ stats->rx_missed_errors += 0xffff; ++ gmac_stats->rx_missed_cntr += 0xffff; ++ } else { ++ //indicates the number of frames missed by the controller ++ unsigned int miss_f = (csr8 & 0xffff); ++ stats->rx_missed_errors += miss_f; ++ gmac_stats->rx_missed_cntr += miss_f; ++ } ++ } ++} +diff --git a/drivers/net/fh_gmac/fh_gmac_dma.h b/drivers/net/fh_gmac/fh_gmac_dma.h +new file mode 100755 +index 00000000..43c02761 +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_dma.h +@@ -0,0 +1,183 @@ ++/* ++ * fh_gmac_dma.h ++ * ++ * Created on: May 22, 2014 ++ * Author: duobao ++ */ ++ ++#ifndef FH_GMAC_DMA_H_ ++#define FH_GMAC_DMA_H_ ++ ++ ++ ++/* DMA Status register defines */ ++#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */ ++#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */ ++#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */ ++#define DMA_STATUS_GMI 0x08000000 ++#define DMA_STATUS_GLI 0x04000000 ++#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ ++#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ ++#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ ++#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */ ++#define DMA_STATUS_TS_SHIFT 20 ++#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */ ++#define DMA_STATUS_RS_SHIFT 17 ++#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */ ++#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */ ++#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */ ++#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */ ++#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */ ++#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */ ++#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */ ++#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */ ++#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */ ++#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */ ++#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */ ++#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */ ++#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */ ++#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */ ++#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ ++#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ ++ ++typedef union ++{ ++ struct ++ { ++ __u32 deferred :1; //0~31 ++ __u32 underflow_error :1; ++ __u32 excessive_deferral :1; ++ __u32 collision_count :4; ++ __u32 vlan_frame :1; ++ __u32 excessive_collision :1; ++ __u32 late_collision :1; ++ __u32 no_carrier :1; ++ __u32 loss_of_carrier :1; ++ __u32 payload_checksum_error :1; ++ __u32 frame_flushed :1; ++ __u32 jabber_timeout :1; ++ __u32 error_summary :1; ++ __u32 ip_header_error :1; ++ __u32 tx_timestamp_status :1; ++ __u32 reserved_30_18 :13; ++ __u32 own :1; ++ }bit; ++ __u32 dw; ++}Gmac_Tx_Descriptor0; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer1_size :11; //0~31 ++ __u32 buffer2_size :11; ++ __u32 timestamp_enable :1; ++ __u32 disable_padding :1; ++ __u32 second_address_chained :1; ++ __u32 end_of_ring :1; ++ __u32 disable_crc :1; ++ __u32 checksum_insertion_ctrl :2; ++ __u32 first_segment :1; ++ __u32 last_segment :1; ++ __u32 intr_on_completion :1; ++ }bit; ++ __u32 dw; ++}Gmac_Tx_Descriptor1; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer_address_pointer :32; //0~31 ++ }bit; ++ __u32 dw; ++}Gmac_Tx_Descriptor2; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer_address_pointer :32; //0~31 ++ }bit; ++ __u32 dw; ++}Gmac_Tx_Descriptor3; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 mac_addr_payload_chksum_error :1; //0 ++ __u32 crc_error :1; //1 ++ __u32 dribble_error :1; //2 ++ __u32 receive_error :1; //3 ++ __u32 watchdog_timeout :1; //4 ++ __u32 frame_type :1; //5 ++ __u32 late_collision :1; //6 ++ __u32 ipc_chksum_error_giant_frame :1; //7 ++ __u32 last_descriptor :1; //8 ++ __u32 first_descriptor :1; //9 ++ __u32 vlan_tag :1; //10 ++ __u32 overflow_error :1; //11 ++ __u32 length_error :1; //12 ++ __u32 sa_filter_fail :1; //13 ++ __u32 descriptor_error :1; //14 ++ __u32 error_summary :1; //15 ++ __u32 frame_length :14;//16~29 ++ __u32 da_filter_fail :1; //30 ++ __u32 own :1; //31 ++ }bit; ++ __u32 dw; ++}Gmac_Rx_Descriptor0; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer1_size :11; //0~10 ++ __u32 buffer2_size :11; //11~21 ++ __u32 reserved_23_22 :2; //22~23 ++ __u32 second_address_chained :1; //24 ++ __u32 end_of_ring :1; //25 ++ __u32 reserved_30_26 :5; //26~30 ++ __u32 disable_intr_on_completion :1; //31 ++ }bit; ++ __u32 dw; ++}Gmac_Rx_Descriptor1; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer_address_pointer :32; //0~31 ++ }bit; ++ __u32 dw; ++}Gmac_Rx_Descriptor2; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 buffer_address_pointer :32; //0~31 ++ }bit; ++ __u32 dw; ++}Gmac_Rx_Descriptor3; ++ ++typedef struct ++{ ++ Gmac_Tx_Descriptor0 desc0; /* control and status information of descriptor */ ++ Gmac_Tx_Descriptor1 desc1; /* buffer sizes */ ++ Gmac_Tx_Descriptor2 desc2; /* physical address of the buffer 1 */ ++ Gmac_Tx_Descriptor3 desc3; /* physical address of the buffer 2 */ ++}Gmac_Tx_DMA_Descriptors; ++ ++typedef struct ++{ ++ Gmac_Rx_Descriptor0 desc0; /* control and status information of descriptor */ ++ Gmac_Rx_Descriptor1 desc1; /* buffer sizes */ ++ Gmac_Rx_Descriptor2 desc2; /* physical address of the buffer 1 */ ++ Gmac_Rx_Descriptor3 desc3; /* physical address of the buffer 2 */ ++}Gmac_Rx_DMA_Descriptors; ++ ++ ++ ++#endif /* FH_GMAC_DMA_H_ */ +diff --git a/drivers/net/fh_gmac/fh_gmac_ethtool.c b/drivers/net/fh_gmac/fh_gmac_ethtool.c +new file mode 100755 +index 00000000..624b3a02 +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_ethtool.c +@@ -0,0 +1,316 @@ ++#include <linux/etherdevice.h> ++#include <linux/ethtool.h> ++#include <linux/mii.h> ++#include <linux/phy.h> ++#include <mach/fh_gmac.h> ++#include "fh_gmac.h" ++ ++#define REG_SPACE_SIZE 0x1054 ++#define GMAC_ETHTOOL_NAME "fh_gmac" ++ ++struct gmac_stats ++{ ++ char stat_string[ETH_GSTRING_LEN]; ++ int sizeof_stat; ++ int stat_offset; ++}; ++ ++#define FH_GMAC_STAT(m) \ ++ { #m, FIELD_SIZEOF(Gmac_Stats, m), \ ++ offsetof(Gmac_Object, stats.m)} ++ ++static const struct gmac_stats gmac_gstrings_stats[] = ++{ ++ FH_GMAC_STAT(tx_underflow), ++ FH_GMAC_STAT(tx_carrier), ++ FH_GMAC_STAT(tx_losscarrier), ++ FH_GMAC_STAT(tx_heartbeat), ++ FH_GMAC_STAT(tx_deferred), ++ FH_GMAC_STAT(tx_vlan), ++ FH_GMAC_STAT(tx_jabber), ++ FH_GMAC_STAT(tx_frame_flushed), ++ FH_GMAC_STAT(tx_payload_error), ++ FH_GMAC_STAT(tx_ip_header_error), ++ FH_GMAC_STAT(rx_desc), ++ FH_GMAC_STAT(rx_partial), ++ FH_GMAC_STAT(rx_runt), ++ FH_GMAC_STAT(rx_toolong), ++ FH_GMAC_STAT(rx_collision), ++ FH_GMAC_STAT(rx_crc), ++ FH_GMAC_STAT(rx_length), ++ FH_GMAC_STAT(rx_mii), ++ FH_GMAC_STAT(rx_multicast), ++ FH_GMAC_STAT(rx_gmac_overflow), ++ FH_GMAC_STAT(rx_watchdog), ++ FH_GMAC_STAT(da_rx_filter_fail), ++ FH_GMAC_STAT(sa_rx_filter_fail), ++ FH_GMAC_STAT(rx_missed_cntr), ++ FH_GMAC_STAT(rx_overflow_cntr), ++ FH_GMAC_STAT(tx_undeflow_irq), ++ FH_GMAC_STAT(tx_process_stopped_irq), ++ FH_GMAC_STAT(tx_jabber_irq), ++ FH_GMAC_STAT(rx_overflow_irq), ++ FH_GMAC_STAT(rx_buf_unav_irq), ++ FH_GMAC_STAT(rx_process_stopped_irq), ++ FH_GMAC_STAT(rx_watchdog_irq), ++ FH_GMAC_STAT(tx_early_irq), ++ FH_GMAC_STAT(fatal_bus_error_irq), ++ FH_GMAC_STAT(threshold), ++ FH_GMAC_STAT(tx_pkt_n), ++ FH_GMAC_STAT(rx_pkt_n), ++ FH_GMAC_STAT(poll_n), ++ FH_GMAC_STAT(sched_timer_n), ++ FH_GMAC_STAT(normal_irq_n), ++}; ++#define FH_GMAC_STATS_LEN ARRAY_SIZE(gmac_gstrings_stats) ++ ++static void gmac_ethtool_getdrvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, GMAC_ETHTOOL_NAME); ++ ++ strcpy(info->version, "0.0.1"); ++ info->fw_version[0] = '\0'; ++ info->n_stats = FH_GMAC_STATS_LEN; ++} ++ ++static int gmac_ethtool_getsettings(struct net_device *ndev, struct ethtool_cmd *cmd) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ struct phy_device *phy = pGmac->phydev; ++ int rc; ++ if (phy == NULL) ++ { ++ pr_err("%s: %s: PHY is not registered\n", ++ __func__, ndev->name); ++ return -ENODEV; ++ } ++ if (!netif_running(ndev)) ++ { ++ pr_err("%s: interface is disabled: we cannot track " ++ "link speed / duplex setting\n", ndev->name); ++ return -EBUSY; ++ } ++ cmd->transceiver = XCVR_INTERNAL; ++ spin_lock_irq(&pGmac->lock); ++ rc = phy_ethtool_gset(phy, cmd); ++ spin_unlock_irq(&pGmac->lock); ++ return rc; ++} ++ ++static int gmac_ethtool_setsettings(struct net_device *ndev, struct ethtool_cmd *cmd) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ struct phy_device *phy = pGmac->phydev; ++ int rc; ++ ++ spin_lock(&pGmac->lock); ++ rc = phy_ethtool_sset(phy, cmd); ++ spin_unlock(&pGmac->lock); ++ ++ return rc; ++} ++ ++static __u32 gmac_ethtool_getmsglevel(struct net_device *ndev) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ return pGmac->msg_enable; ++} ++ ++static void gmac_ethtool_setmsglevel(struct net_device *ndev, __u32 level) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ pGmac->msg_enable = level; ++ ++} ++ ++static int gmac_check_if_running(struct net_device *ndev) ++{ ++ if (!netif_running(ndev)) ++ return -EBUSY; ++ return 0; ++} ++ ++static int gmac_ethtool_get_regs_len(struct net_device *ndev) ++{ ++ return REG_SPACE_SIZE; ++} ++ ++static void gmac_ethtool_gregs(struct net_device *ndev, struct ethtool_regs *regs, void *space) ++{ ++ int i; ++ __u32 *reg_space = (__u32 *) space; ++ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ ++ memset(reg_space, 0x0, REG_SPACE_SIZE); ++ ++ /* MAC registers */ ++ for (i = 0; i < 55; i++) ++ reg_space[i] = readl(pGmac->remap_addr + (i * 4)); ++ /* DMA registers */ ++ for (i = 0; i < 22; i++) ++ reg_space[i + 55] = readl(pGmac->remap_addr + (REG_GMAC_BUS_MODE + (i * 4))); ++} ++ ++static void gmac_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ ++ spin_lock(&pGmac->lock); ++ ++ pause->rx_pause = 0; ++ pause->tx_pause = 0; ++ pause->autoneg = pGmac->phydev->autoneg; ++ ++ if (pGmac->flow_ctrl & FLOW_RX) ++ pause->rx_pause = 1; ++ if (pGmac->flow_ctrl & FLOW_TX) ++ pause->tx_pause = 1; ++ ++ spin_unlock(&pGmac->lock); ++} ++ ++static int gmac_set_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ struct phy_device *phy = pGmac->phydev; ++ int new_pause = FLOW_OFF; ++ int ret = 0; ++ ++ spin_lock(&pGmac->lock); ++ ++ if (pause->rx_pause) ++ new_pause |= FLOW_RX; ++ if (pause->tx_pause) ++ new_pause |= FLOW_TX; ++ ++ pGmac->flow_ctrl = new_pause; ++ phy->autoneg = pause->autoneg; ++ ++ if (phy->autoneg) ++ { ++ if (netif_running(ndev)) ++ ret = phy_start_aneg(phy); ++ } ++ else ++ { ++ GMAC_FlowCtrl(pGmac, phy->duplex, pGmac->flow_ctrl, pGmac->pause); ++ } ++ spin_unlock(&pGmac->lock); ++ return ret; ++} ++ ++static void gmac_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *dummy, __u64 *data) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ int i; ++ ++ /* Update HW stats if supported */ ++ GMAC_DMA_DiagnosticFrame(&ndev->stats, pGmac); ++ ++ for (i = 0; i < FH_GMAC_STATS_LEN; i++) ++ { ++ char *p = (char *)pGmac + gmac_gstrings_stats[i].stat_offset; ++ data[i] = (gmac_gstrings_stats[i].sizeof_stat == ++ sizeof(__u64)) ? (*(__u64 *)p) : (*(__u32 *)p); ++ } ++} ++ ++static int gmac_get_sset_count(struct net_device *netdev, int sset) ++{ ++ switch (sset) ++ { ++ case ETH_SS_STATS: ++ return FH_GMAC_STATS_LEN; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void gmac_get_strings(struct net_device *ndev, __u32 stringset, __u8 *data) ++{ ++ int i; ++ __u8 *p = data; ++ ++ switch (stringset) ++ { ++ case ETH_SS_STATS: ++ for (i = 0; i < FH_GMAC_STATS_LEN; i++) ++ { ++ memcpy(p, gmac_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); ++ p += ETH_GSTRING_LEN; ++ } ++ break; ++ default: ++ WARN_ON(1); ++ break; ++ } ++} ++ ++/* Currently only support WOL through Magic packet. */ ++static void gmac_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ ++ spin_lock_irq(&pGmac->lock); ++ if (device_can_wakeup(pGmac->dev)) ++ { ++ wol->supported = WAKE_MAGIC | WAKE_UCAST; ++ wol->wolopts = pGmac->wolopts; ++ } ++ spin_unlock_irq(&pGmac->lock); ++} ++ ++static int gmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ++{ ++ Gmac_Object* pGmac = netdev_priv(ndev); ++ __u32 support = WAKE_MAGIC | WAKE_UCAST; ++ ++ if (!device_can_wakeup(pGmac->dev)) ++ return -EINVAL; ++ ++ if (wol->wolopts & ~support) ++ return -EINVAL; ++ ++ if (wol->wolopts) ++ { ++ pr_info("fh_gmac: wakeup enable\n"); ++ device_set_wakeup_enable(pGmac->dev, 1); ++ enable_irq_wake(ndev->irq); ++ } ++ else ++ { ++ device_set_wakeup_enable(pGmac->dev, 0); ++ disable_irq_wake(ndev->irq); ++ } ++ ++ spin_lock_irq(&pGmac->lock); ++ pGmac->wolopts = wol->wolopts; ++ spin_unlock_irq(&pGmac->lock); ++ ++ return 0; ++} ++ ++static struct ethtool_ops fh_gmac_ethtool_ops = { ++ .begin = gmac_check_if_running, ++ .get_drvinfo = gmac_ethtool_getdrvinfo, ++ .get_settings = gmac_ethtool_getsettings, ++ .set_settings = gmac_ethtool_setsettings, ++ .get_msglevel = gmac_ethtool_getmsglevel, ++ .set_msglevel = gmac_ethtool_setmsglevel, ++ .get_regs = gmac_ethtool_gregs, ++ .get_regs_len = gmac_ethtool_get_regs_len, ++ .get_link = ethtool_op_get_link, ++ .get_pauseparam = gmac_get_pauseparam, ++ .set_pauseparam = gmac_set_pauseparam, ++ .get_ethtool_stats = gmac_get_ethtool_stats, ++ .get_strings = gmac_get_strings, ++ .get_wol = gmac_get_wol, ++ .set_wol = gmac_set_wol, ++ .get_sset_count = gmac_get_sset_count, ++}; ++ ++void fh_gmac_set_ethtool_ops(struct net_device *netdev) ++{ ++ SET_ETHTOOL_OPS(netdev, &fh_gmac_ethtool_ops); ++} +diff --git a/drivers/net/fh_gmac/fh_gmac_main.c b/drivers/net/fh_gmac/fh_gmac_main.c +new file mode 100755 +index 00000000..b08fe67b +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_main.c +@@ -0,0 +1,1300 @@ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/errno.h> ++#include <linux/in.h> ++#include <linux/ioport.h> ++#include <linux/slab.h> ++#include <linux/mm.h> ++#include <linux/interrupt.h> ++#include <linux/init.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/skbuff.h> ++#include <linux/ethtool.h> ++#include <linux/highmem.h> ++#include <linux/proc_fs.h> ++#include <linux/ctype.h> ++#include <linux/version.h> ++#include <linux/spinlock.h> ++#include <linux/dma-mapping.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/semaphore.h> ++#include <linux/phy.h> ++#include <linux/bitops.h> ++#include <linux/io.h> ++#include <linux/uaccess.h> ++#include <linux/irqreturn.h> ++ ++#include <asm/irq.h> ++#include <asm/page.h> ++#include <asm/setup.h> ++#include <linux/crc32.h> ++#include <mach/fh_gmac.h> ++#include "fh_gmac.h" ++ ++/* Module parameters */ ++static int watchdog = TX_TIMEO; ++static int debug = 16; /* -1: default, 0: no output, 16: all */ ++static int dma_txsize = DMA_TX_SIZE; ++static int dma_rxsize = DMA_RX_SIZE; ++static int flow_ctrl = FLOW_AUTO; ++static int pause = PAUSE_TIME; ++ ++static unsigned int phymode = PHY_INTERFACE_MODE_MII; ++ ++#if defined(FH_GMAC_XMIT_DEBUG) || defined(FH_GMAC_RX_DEBUG) ++static void print_pkt(unsigned char *buf, int len) ++{ ++ int j; ++ printk(KERN_DEBUG "len = %d byte, buf addr: 0x%p", len, buf); ++ for (j = 0; j < len; j++) { ++ if ((j % 16) == 0) ++ printk(KERN_DEBUG"\n %03x:", j); ++ printk(KERN_DEBUG" %02x", buf[j]); ++ } ++ printk(KERN_DEBUG"\n"); ++} ++#endif ++ ++static __u32 GMAC_BitReverse(register __u32 x) ++{ ++ register __u32 y = 0x55555555; ++ x = (((x >> 1) & y) | ((x & y) << 1)); ++ y = 0x33333333; ++ x = (((x >> 2) & y) | ((x & y) << 2)); ++ y = 0x0f0f0f0f; ++ x = (((x >> 4) & y) | ((x & y) << 4)); ++ y = 0x00ff00ff; ++ x = (((x >> 8) & y) | ((x & y) << 8)); ++ return (x >> 16) | (x << 16); ++} ++ ++ ++static void GMAC_SetMacAddress(Gmac_Object *pGmac) ++{ ++ ++ __u32 macHigh = pGmac->local_mac_address[5]<<8 | ++ pGmac->local_mac_address[4]; ++ __u32 macLow = pGmac->local_mac_address[3]<<24 | ++ pGmac->local_mac_address[2]<<16 | ++ pGmac->local_mac_address[1]<<8 | ++ pGmac->local_mac_address[0]; ++ ++ writel(macHigh, pGmac->remap_addr + REG_GMAC_MAC_HIGH); ++ writel(macLow, pGmac->remap_addr + REG_GMAC_MAC_LOW); ++} ++ ++int gmac_dev_set_mac_addr(struct net_device *dev, void *p) ++{ ++ Gmac_Object *pGmac = netdev_priv(dev); ++ struct sockaddr *addr = p; ++ memcpy(pGmac->local_mac_address, addr->sa_data, ETH_ALEN); ++ GMAC_SetMacAddress(pGmac); ++ return eth_mac_addr(dev, p); ++} ++ ++static inline void GMAC_EnableMac(Gmac_Object *pGmac) ++{ ++ /* transmitter enable */ ++ /* receive enable */ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG); ++ reg |= 0xc; ++ writel(reg, pGmac->remap_addr + REG_GMAC_CONFIG); ++ ++} ++ ++ ++ ++static inline void GMAC_DisableMac(Gmac_Object *pGmac) ++{ ++ /* transmitter disable */ ++ /* receive disable */ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG); ++ reg &= ~0xc; ++ writel(reg | 0xc, pGmac->remap_addr + REG_GMAC_CONFIG); ++} ++ ++static inline void GMAC_CoreInit(Gmac_Object *pGmac) ++{ ++ /* FIXME: heartbeat disable */ ++ /* auto pad or crc stripping */ ++ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG); ++ reg |= 0x80; ++ writel(reg | 0xc, pGmac->remap_addr + REG_GMAC_CONFIG); ++} ++ ++void GMAC_FlowCtrl(Gmac_Object *pGmac, unsigned int duplex, ++ unsigned int fc, unsigned int pause_time) ++{ ++ __u32 flow = fc; ++ ++ if (duplex) ++ flow |= (pause_time << 16); ++ writel(flow, pGmac->remap_addr + REG_GMAC_FLOW_CTRL); ++} ++ ++static void gmac_tx_err(Gmac_Object *pGmac) ++{ ++ ++ netif_stop_queue(pGmac->ndev); ++ GMAC_DMA_StopTx(pGmac); ++ GMAC_DMA_FreeTxSkbufs(pGmac); ++ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, pGmac->dma_tx_size); ++ pGmac->dirty_tx = 0; ++ pGmac->cur_tx = 0; ++ GMAC_DMA_StartTx(pGmac); ++ pGmac->ndev->stats.tx_errors++; ++ netif_wake_queue(pGmac->ndev); ++} ++ ++ ++static irqreturn_t fh_gmac_interrupt(int irq, void *dev_id) ++{ ++ ++ struct net_device *ndev = (struct net_device *)dev_id; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ int status; ++ ++ if (unlikely(!ndev)) { ++ pr_err("%s: invalid ndev pointer\n", __func__); ++ return IRQ_NONE; ++ } ++ ++ ++ status = GMAC_DMA_Interrupt(pGmac); ++ if (likely(status == handle_tx_rx)) { ++ if (likely(napi_schedule_prep(&pGmac->napi))) { ++ writel(0x0, pGmac->remap_addr + REG_GMAC_INTR_EN); ++ __napi_schedule(&pGmac->napi); ++ } ++ } else if (unlikely(status & tx_hard_error_bump_tc)) { ++ /* FIXME: tx underflow */ ++ } else if (unlikely(status == tx_hard_error)) { ++ gmac_tx_err(pGmac); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void fh_gmac_verify_args(void) ++{ ++ if (unlikely(watchdog < 0)) ++ watchdog = TX_TIMEO; ++ if (unlikely(dma_rxsize < 0)) ++ dma_rxsize = DMA_RX_SIZE; ++ if (unlikely(dma_txsize < 0)) ++ dma_txsize = DMA_TX_SIZE; ++ if (unlikely(flow_ctrl > 1)) ++ flow_ctrl = FLOW_AUTO; ++ else if (likely(flow_ctrl < 0)) ++ flow_ctrl = FLOW_OFF; ++ if (unlikely((pause < 0) || (pause > 0xffff))) ++ pause = PAUSE_TIME; ++ ++} ++ ++static void fh_gmac_adjust_link(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct phy_device *phydev = pGmac->phydev; ++ unsigned long flags; ++ int new_state = 0; ++ ++ if (phydev == NULL) ++ return; ++ ++ spin_lock_irqsave(&pGmac->lock, flags); ++ if (phydev->link) { ++ __u32 ctrl = readl(pGmac->remap_addr + REG_GMAC_CONFIG); ++ ++ /* Now we make sure that we can be in full duplex mode. ++ * If not, we operate in half-duplex mode. */ ++ if (phydev->duplex != pGmac->oldduplex) { ++ new_state = 1; ++ if (!(phydev->duplex)) ++ ctrl &= ~0x800; ++ else ++ ctrl |= 0x800; ++ pGmac->oldduplex = phydev->duplex; ++ } ++ /* Flow Control operation */ ++ if (phydev->pause) { ++ __u32 fc = pGmac->flow_ctrl, pause_time = pGmac->pause; ++ GMAC_FlowCtrl(pGmac, phydev->duplex, fc, pause_time); ++ } ++ ++ if (phydev->speed != pGmac->speed) { ++ new_state = 1; ++ switch (phydev->speed) { ++ case 100: ++ ctrl |= 0x4000; ++ if (pGmac->priv_data->set_rmii_speed) ++ pGmac->priv_data-> ++ set_rmii_speed(gmac_speed_100m); ++ break; ++ case 10: ++ ctrl &= ~0x4000; ++ if (pGmac->priv_data->set_rmii_speed) ++ pGmac->priv_data-> ++ set_rmii_speed(gmac_speed_10m); ++ break; ++ default: ++ if (netif_msg_link(pGmac)) ++ pr_warning("%s: Speed (%d) is not 10" ++ " or 100!\n", ndev->name, ++ phydev->speed); ++ break; ++ } ++ ++ pGmac->speed = phydev->speed; ++ } ++ writel(ctrl, pGmac->remap_addr + REG_GMAC_CONFIG); ++ if (!pGmac->oldlink) { ++ new_state = 1; ++ pGmac->oldlink = 1; ++ } ++ } else if (pGmac->oldlink) { ++ new_state = 1; ++ pGmac->oldlink = 0; ++ pGmac->speed = 0; ++ pGmac->oldduplex = -1; ++ } ++ ++ if (new_state && netif_msg_link(pGmac)) ++ phy_print_status(phydev); ++ ++ spin_unlock_irqrestore(&pGmac->lock, flags); ++} ++ ++ ++static inline void fh_gmac_rx_refill(Gmac_Object *pGmac) ++{ ++ __u32 rxsize = pGmac->dma_rx_size; ++ int bfsize = pGmac->dma_buf_sz; ++ Gmac_Rx_DMA_Descriptors *desc = pGmac->rx_dma_descriptors; ++ ++ for (; pGmac->cur_rx - pGmac->dirty_rx > 0; ++ pGmac->dirty_rx++) { ++ __u32 entry = pGmac->dirty_rx % rxsize; ++ if (likely(pGmac->rx_skbuff[entry] == NULL)) { ++ struct sk_buff *skb; ++ ++ skb = __skb_dequeue(&pGmac->rx_recycle); ++ if (skb == NULL) ++ skb = netdev_alloc_skb_ip_align(pGmac->ndev, ++ bfsize); ++ ++ if (unlikely(skb == NULL)) ++ break; ++ ++ pGmac->rx_skbuff[entry] = skb; ++ pGmac->rx_skbuff_dma[entry] = ++ dma_map_single(pGmac->dev, skb->data, bfsize, ++ DMA_FROM_DEVICE); ++ ++ (desc + entry)->desc2.dw = pGmac->rx_skbuff_dma[entry]; ++ RX_DBG(KERN_INFO "\trefill entry #%d\n", entry); ++ } ++ wmb(); ++ (desc+entry)->desc0.bit.own = 1; ++ wmb(); ++ } ++} ++ ++static int fh_gmac_rx(Gmac_Object *pGmac, int limit) ++{ ++ __u32 rxsize = pGmac->dma_rx_size; ++ __u32 entry = pGmac->cur_rx % rxsize; ++ __u32 next_entry; ++ __u32 count = 0; ++ Gmac_Rx_DMA_Descriptors *desc = ++ pGmac->rx_dma_descriptors + entry; ++ Gmac_Rx_DMA_Descriptors *desc_next; ++ ++#ifdef FH_GMAC_RX_DEBUG ++ if (netif_msg_hw(pGmac)) { ++ printk(KERN_DEBUG ">>> fh_gmac_rx: descriptor ring:\n"); ++ GMAC_DMA_DisplayRxDesc(pGmac->rx_dma_descriptors, rxsize); ++ } ++#endif ++ count = 0; ++ while (!desc->desc0.bit.own) { ++ int status; ++ ++ if (count >= limit) ++ break; ++ ++ count++; ++ ++ next_entry = (++pGmac->cur_rx) % rxsize; ++ desc_next = pGmac->rx_dma_descriptors + next_entry; ++ prefetch(desc_next); ++ ++ /* read the status of the incoming frame */ ++ status = (GMAC_DMA_RxStatus(pGmac, desc)); ++ if (unlikely(status == discard_frame)) { ++ pGmac->ndev->stats.rx_errors++; ++ } else { ++ struct sk_buff *skb; ++ int frame_len; ++ frame_len = desc->desc0.bit.frame_length; ++ /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 ++ * Type frames (LLC/LLC-SNAP) */ ++ if (unlikely(status != llc_snap)) ++ frame_len -= ETH_FCS_LEN; ++#ifdef FH_GMAC_RX_DEBUG ++ if (frame_len > ETH_FRAME_LEN) ++ pr_debug("\tRX frame size %d, COE status: %d\n", ++ frame_len, status); ++ ++ if (netif_msg_hw(pGmac)) ++ pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", ++ desc, entry, desc->desc2.dw); ++#endif ++ skb = pGmac->rx_skbuff[entry]; ++ if (unlikely(!skb)) { ++ pr_err("%s: Inconsistent Rx descriptor chain\n", ++ pGmac->ndev->name); ++ pGmac->ndev->stats.rx_dropped++; ++ break; ++ } ++ prefetch(skb->data - NET_IP_ALIGN); ++ pGmac->rx_skbuff[entry] = NULL; ++ ++ skb_put(skb, frame_len); ++ dma_unmap_single(pGmac->dev, ++ pGmac->rx_skbuff_dma[entry], ++ pGmac->dma_buf_sz, DMA_FROM_DEVICE); ++#ifdef FH_GMAC_RX_DEBUG ++ if (netif_msg_pktdata(pGmac)) { ++ pr_info(" frame received (%dbytes)", frame_len); ++ print_pkt(skb->data, frame_len); ++ } ++#endif ++ skb->protocol = eth_type_trans(skb, pGmac->ndev); ++ ++ if (unlikely(status == csum_none)) { ++ /* always for the old mac 10/100 */ ++ skb_checksum_none_assert(skb); ++ netif_receive_skb(skb); ++ } else { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ napi_gro_receive(&pGmac->napi, skb); ++ } ++ ++ pGmac->ndev->stats.rx_packets++; ++ pGmac->ndev->stats.rx_bytes += frame_len; ++ } ++ entry = next_entry; ++ desc = desc_next; /* use prefetched values */ ++ } ++ ++ fh_gmac_rx_refill(pGmac); ++ ++ pGmac->stats.rx_pkt_n += count; ++ ++ return count; ++} ++ ++/* minimum number of free TX descriptors required to wake up TX process */ ++#define FH_GMAC_TX_THRESH(x) (x->dma_tx_size/4) ++ ++static inline __u32 gmac_tx_avail(Gmac_Object *pGmac) ++{ ++ return pGmac->dirty_tx + pGmac->dma_tx_size - pGmac->cur_tx - 1; ++} ++ ++ ++ ++static void fh_gmac_tx(Gmac_Object *pGmac) ++{ ++ __u32 txsize = pGmac->dma_tx_size; ++ while (pGmac->dirty_tx != pGmac->cur_tx) { ++ int last; ++ __u32 entry = pGmac->dirty_tx % txsize; ++ struct sk_buff *skb = pGmac->tx_skbuff[entry]; ++ Gmac_Tx_DMA_Descriptors *desc = ++ pGmac->tx_dma_descriptors + entry; ++ ++ /* Check if the descriptor is owned by the DMA. */ ++ if (desc->desc0.bit.own) ++ break; ++ ++ /* Verify tx error by looking at the last segment */ ++ last = desc->desc1.bit.last_segment; ++ if (likely(last)) { ++ int tx_error = GMAC_DMA_TxStatus(pGmac, desc); ++ if (likely(tx_error == 0)) { ++ pGmac->ndev->stats.tx_packets++; ++ pGmac->stats.tx_pkt_n++; ++ } else { ++ pGmac->ndev->stats.tx_errors++; ++ } ++ } ++ TX_DBG("%s: curr %d, dirty %d\n", __func__, ++ pGmac->cur_tx, pGmac->dirty_tx); ++ ++ if (likely(desc->desc2.dw)) { ++ dma_unmap_single(pGmac->dev, desc->desc2.dw, ++ desc->desc1.bit.buffer1_size, ++ DMA_TO_DEVICE); ++ } ++ if (unlikely(desc->desc3.dw)) ++ desc->desc3.dw = 0; ++ ++ if (likely(skb != NULL)) { ++ /* ++ * If there's room in the queue (limit it to size) ++ * we add this skb back into the pool, ++ * if it's the right size. ++ */ ++ if ((skb_queue_len(&pGmac->rx_recycle) ++ < pGmac->dma_rx_size) ++ && ++ skb_recycle_check(skb, pGmac->dma_buf_sz)) { ++ __skb_queue_head(&pGmac->rx_recycle, skb); ++ } else { ++ dev_kfree_skb(skb); ++ } ++ ++ pGmac->tx_skbuff[entry] = NULL; ++ } ++ GMAC_DMA_ReleaseTxDesc(desc); ++ ++ entry = (++pGmac->dirty_tx) % txsize; ++ } ++ if (unlikely(netif_queue_stopped(pGmac->ndev) && ++ gmac_tx_avail(pGmac) > ++ FH_GMAC_TX_THRESH(pGmac))) { ++ netif_tx_lock(pGmac->ndev); ++ if (netif_queue_stopped(pGmac->ndev) && ++ gmac_tx_avail(pGmac) > ++ FH_GMAC_TX_THRESH(pGmac)) { ++ TX_DBG("%s: restart transmit\n", __func__); ++ netif_wake_queue(pGmac->ndev); ++ } ++ netif_tx_unlock(pGmac->ndev); ++ } ++} ++ ++ ++static int fh_gmac_poll(struct napi_struct *napi, int budget) ++{ ++ Gmac_Object *pGmac = container_of(napi, Gmac_Object, napi); ++ int work_done = 0; ++ ++ pGmac->stats.poll_n++; ++ fh_gmac_tx(pGmac); ++ work_done = fh_gmac_rx(pGmac, budget); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ writel(0x1a061, pGmac->remap_addr + REG_GMAC_INTR_EN); ++ } ++ return work_done; ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* Polling receive - used by NETCONSOLE and other diagnostic tools ++ * to allow network I/O with interrupts disabled. */ ++static void gmac_poll_controller(struct net_device *ndev) ++{ ++ disable_irq(ndev->irq); ++ fh_gmac_interrupt(ndev->irq, ndev); ++ enable_irq(ndev->irq); ++} ++#endif ++ ++ ++static __u32 gmac_handle_jumbo_frames(struct sk_buff *skb, ++ struct net_device *dev, int checksum_insertion) ++{ ++ /* FIXME: 8K jumbo frame */ ++ Gmac_Object *pGmac = netdev_priv(dev); ++ __u32 nopaged_len = skb_headlen(skb); ++ __u32 txsize = pGmac->dma_tx_size; ++ __u32 entry = pGmac->cur_tx % txsize; ++ Gmac_Tx_DMA_Descriptors *desc = pGmac->tx_dma_descriptors + entry; ++ ++ if (nopaged_len > BUFFER_SIZE_2K) { ++ ++ int buf2_size = nopaged_len - BUFFER_SIZE_2K + 1; ++ ++ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data, ++ BUFFER_SIZE_2K, DMA_TO_DEVICE); ++ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K; ++ desc->desc1.bit.first_segment = 1; ++ desc->desc1.bit.buffer1_size = BUFFER_SIZE_2K - 1; ++ desc->desc1.bit.checksum_insertion_ctrl = 3; ++ entry = (++pGmac->cur_tx) % txsize; ++ desc = pGmac->tx_dma_descriptors + entry; ++ desc->desc2.dw = dma_map_single(pGmac->dev, ++ skb->data + BUFFER_SIZE_2K, ++ buf2_size, DMA_TO_DEVICE); ++ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K; ++ desc->desc1.bit.first_segment = 0; ++ desc->desc1.bit.buffer1_size = buf2_size; ++ desc->desc1.bit.checksum_insertion_ctrl = checksum_insertion; ++ desc->desc0.bit.own = 1; ++ pGmac->tx_skbuff[entry] = NULL; ++ } else { ++ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data, ++ nopaged_len, DMA_TO_DEVICE); ++ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K; ++ desc->desc1.bit.first_segment = 1; ++ desc->desc1.bit.buffer1_size = nopaged_len; ++ desc->desc1.bit.checksum_insertion_ctrl = checksum_insertion; ++ } ++ return entry; ++} ++ ++/* Configuration changes (passed on by ifconfig) */ ++static int gmac_dev_set_config(struct net_device *ndev, struct ifmap *map) ++{ ++ if (ndev->flags & IFF_UP) /* can't act on a running interface */ ++ return -EBUSY; ++ ++ /* Don't allow changing the I/O address */ ++ if (map->base_addr != ndev->base_addr) { ++ pr_warning("%s: can't change I/O address\n", ndev->name); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Don't allow changing the IRQ */ ++ if (map->irq != ndev->irq) { ++ pr_warning("%s: can't change IRQ number %d\n", ++ ndev->name, ndev->irq); ++ return -EOPNOTSUPP; ++ } ++ ++ /* ignore other fields */ ++ return 0; ++} ++ ++ ++static int gmac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ __u32 txsize = pGmac->dma_tx_size; ++ __u32 entry; ++ int i, csum_insertion = 0; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ Gmac_Tx_DMA_Descriptors *desc, *first; ++ ++ if (unlikely(gmac_tx_avail(pGmac) < nfrags + 1)) { ++ if (!netif_queue_stopped(ndev)) { ++ netif_stop_queue(ndev); ++ /* This is a hard error, log it. */ ++ pr_err("%s: BUG! Tx Ring full when queue awake\n", ++ __func__); ++ } ++ return NETDEV_TX_BUSY; ++ } ++ ++ entry = pGmac->cur_tx % txsize; ++ /* fixme: debug */ ++ ++#ifdef FH_GMAC_XMIT_DEBUG ++ if ((skb->len > ETH_FRAME_LEN) || nfrags) ++ pr_info("fh gmac xmit:\n" ++ "\tskb addr %p - len: %d - nopaged_len: %d\n" ++ "\tn_frags: %d - ip_summed: %d - %s gso\n", ++ skb, skb->len, skb_headlen(skb), ++ nfrags, skb->ip_summed, ++ !skb_is_gso(skb) ? "isn't" : "is"); ++#endif ++ ++ csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL) ? 3 : 0; ++ ++ desc = pGmac->tx_dma_descriptors + entry; ++ first = desc; ++ ++#ifdef FH_GMAC_XMIT_DEBUG ++ if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN)) ++ pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n" ++ "\t\tn_frags: %d, ip_summed: %d\n", ++ skb->len, skb_headlen(skb), nfrags, skb->ip_summed); ++#endif ++ pGmac->tx_skbuff[entry] = skb; ++ if (unlikely(skb->len >= BUFFER_SIZE_2K)) { ++ printk(KERN_ERR "jumbo_frames detected\n"); ++ entry = gmac_handle_jumbo_frames(skb, ndev, csum_insertion); ++ desc = pGmac->tx_dma_descriptors + entry; ++ } else { ++ __u32 nopaged_len = skb_headlen(skb); ++ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data, ++ nopaged_len, DMA_TO_DEVICE); ++ desc->desc1.bit.first_segment = 1; ++ desc->desc1.bit.buffer1_size = nopaged_len; ++ desc->desc1.bit.checksum_insertion_ctrl = csum_insertion; ++ } ++ ++ for (i = 0; i < nfrags; i++) { ++ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int len = frag->size; ++ ++ entry = (++pGmac->cur_tx) % txsize; ++ desc = pGmac->tx_dma_descriptors + entry; ++ ++ TX_DBG("\t[entry %d] segment len: %d\n", entry, len); ++ desc->desc2.dw = dma_map_page(pGmac->dev, frag->page, ++ frag->page_offset, ++ len, DMA_TO_DEVICE); ++ pGmac->tx_skbuff[entry] = NULL; ++ desc->desc1.bit.first_segment = 0; ++ desc->desc1.bit.buffer1_size = len; ++ wmb(); ++ desc->desc1.bit.checksum_insertion_ctrl = csum_insertion; ++ desc->desc0.bit.own = 1; ++ wmb(); ++ } ++ ++ /* Interrupt on completition only for the latest segment */ ++ desc->desc1.bit.last_segment = 1; ++ desc->desc1.bit.intr_on_completion = 1; ++ wmb(); ++#ifdef CONFIG_STMMAC_TIMER ++ /* Clean IC while using timer */ ++ if (likely(priv->tm->enable)) ++ priv->hw->desc->clear_tx_ic(desc); ++#endif ++ /* To avoid raise condition */ ++ first->desc0.bit.own = 1; ++ wmb(); ++ pGmac->cur_tx++; ++ ++#ifdef FH_GMAC_XMIT_DEBUG ++ if (netif_msg_pktdata(pGmac)) { ++ pr_info("fh gmac xmit: current=%d, dirty=%d, entry=%d, " ++ "first=%p, nfrags=%d\n", ++ (pGmac->cur_tx % txsize), (pGmac->dirty_tx % txsize), ++ entry, first, nfrags); ++ GMAC_DMA_DisplayTxDesc(pGmac->tx_dma_descriptors, 3); ++ pr_info(">>> frame to be transmitted: "); ++ print_pkt(skb->data, skb->len); ++ } ++#endif ++ if (unlikely(gmac_tx_avail(pGmac) <= (MAX_SKB_FRAGS + 1))) { ++ TX_DBG("%s: stop transmitted packets\n", __func__); ++ netif_stop_queue(ndev); ++ } ++ ++ ndev->stats.tx_bytes += skb->len; ++ writel(0x1, pGmac->remap_addr + REG_GMAC_TX_POLL_DEMAND); ++ ++ return NETDEV_TX_OK; ++} ++ ++static void gmac_dev_tx_timeout(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ gmac_tx_err(pGmac); ++} ++ ++static int gmac_dev_change_mtu(struct net_device *ndev, int new_mtu) ++{ ++ int max_mtu; ++/* ++ if (netif_running(ndev)) ++ { ++ pr_err("%s: must be stopped to change its MTU\n", ndev->name); ++ return -EBUSY; ++ } ++*/ ++ max_mtu = ETH_DATA_LEN; ++ ++ if ((new_mtu < 46) || (new_mtu > max_mtu)) { ++ pr_err("%s: invalid MTU, max MTU is: %d\n", ++ ndev->name, max_mtu); ++ return -EINVAL; ++ } ++ ++ ndev->mtu = new_mtu; ++ netdev_update_features(ndev); ++ ++ return 0; ++} ++ ++ ++static void gmac_set_filter(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ __u32 value = readl(pGmac->remap_addr + REG_GMAC_FRAME_FILTER); ++ ++ if (ndev->flags & IFF_PROMISC) { ++ /* enable Promiscuous Mode */ ++ value = 0x1; ++ } else if ((netdev_mc_count(ndev) > 64) ++ || (ndev->flags & IFF_ALLMULTI)) { ++ /* enable Pass All Multicast */ ++ value = 0x10; ++ ++ writel(0xffffffff, pGmac->remap_addr + REG_GMAC_HASH_HIGH); ++ writel(0xffffffff, pGmac->remap_addr + REG_GMAC_HASH_LOW); ++ } else if (netdev_mc_empty(ndev)) { ++ /* no multicast */ ++ value = 0; ++ } else { ++ __u32 mc_filter[2]; ++ struct netdev_hw_addr *ha; ++ ++ /* Perfect filter mode for physical address and Hash ++ filter for multicast */ ++ value = 0x404; ++ ++ memset(mc_filter, 0, sizeof(mc_filter)); ++ netdev_for_each_mc_addr(ha, ndev) ++ { ++ /* The upper 6 bits of the calculated CRC are used to ++ * index the contens of the hash table */ ++ int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; ++ ++ /* The most significant bit determines the register to ++ * use (H/L) while the other 5 bits determine the bit ++ * within the register. */ ++ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); ++ } ++ writel(GMAC_BitReverse(mc_filter[0]), ++ pGmac->remap_addr + REG_GMAC_HASH_HIGH); ++ writel(GMAC_BitReverse(mc_filter[1]), ++ pGmac->remap_addr + REG_GMAC_HASH_LOW); ++ } ++ writel(value, pGmac->remap_addr + REG_GMAC_FRAME_FILTER); ++} ++ ++static void gmac_dev_mcast_set(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ ++ spin_lock(&pGmac->lock); ++ gmac_set_filter(ndev); ++ spin_unlock(&pGmac->lock); ++} ++ ++static int gmac_dev_ioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ int ret; ++ ++ if (!netif_running(ndev)) ++ return -EINVAL; ++ ++ if (!pGmac->phydev) ++ return -EINVAL; ++ ++ ret = phy_mii_ioctl(pGmac->phydev, ifrq, cmd); ++ ++ return ret; ++ ++} ++ ++ ++ ++static int fh_gmac_init_phy(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct phy_device *phydev; ++ char phy_id[MII_BUS_ID_SIZE + 3]; ++ char bus_id[MII_BUS_ID_SIZE]; ++ ++ if (pGmac->phydev == NULL) ++ return -ENODEV; ++ ++ snprintf(bus_id, MII_BUS_ID_SIZE, "%x", 0); ++ snprintf(phy_id, MII_BUS_ID_SIZE + 3, ++ PHY_ID_FMT, bus_id, pGmac->priv_data->phyid); ++ pr_debug("fh_gmac_init_phy: trying to attach to %s\n", phy_id); ++ ++ phydev = phy_connect(ndev, phy_id, &fh_gmac_adjust_link, 0, ++ pGmac->phy_interface); ++ ++ if (IS_ERR(phydev)) { ++ pr_err("%s: Could not attach to PHY\n", ndev->name); ++ return PTR_ERR(phydev); ++ } ++ ++ phydev->advertising &= ~(SUPPORTED_1000baseT_Half ++ | SUPPORTED_1000baseT_Full); ++ ++ ++ /* ++ * Broken HW is sometimes missing the pull-up resistor on the ++ * MDIO line, which results in reads to non-existent devices returning ++ * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent ++ * device as well. ++ * Note: phydev->phy_id is the result of reading the UID PHY registers. ++ */ ++ if (phydev->phy_id == 0) { ++ phy_disconnect(phydev); ++ return -ENODEV; ++ } ++ pr_debug("fh_gmac_init_phy: %s: attached to PHY (UID 0x%x)" ++ " Link = %d\n", ndev->name, phydev->phy_id, phydev->link); ++ ++ return 0; ++} ++ ++ ++static int gmac_dev_open(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ int ret; ++ ++ fh_gmac_verify_args(); ++ ++ /* MDIO bus Registration */ ++ ret = fh_mdio_register(ndev); ++ if (ret < 0) ++ goto open_error; ++ ++ ret = fh_gmac_init_phy(ndev); ++ if (unlikely(ret)) { ++ pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret); ++ goto open_error; ++ } ++ /* Create and initialize the TX/RX descriptors chains. */ ++ /* FIXME: STMMAC_ALIGN(buf_sz); */ ++ pGmac->dma_tx_size = dma_txsize; ++ pGmac->dma_rx_size = dma_rxsize; ++ pGmac->dma_buf_sz = BUFFER_SIZE_2K; ++ ++ GMAC_DMA_InitDescRings(ndev); ++ /* DMA initialization and SW reset */ ++ ret = GMAC_DMA_Init(ndev, pGmac->tx_bus_addr, pGmac->rx_bus_addr); ++ if (ret < 0) { ++ pr_err("%s: DMA initialization failed\n", __func__); ++ goto open_error; ++ } ++ ++ /* Copy the MAC addr into the HW */ ++ GMAC_SetMacAddress(pGmac); ++ ++ /* Initialize the MAC Core */ ++ GMAC_CoreInit(pGmac); ++ ++ netdev_update_features(ndev); ++ ++ /* Request the IRQ lines */ ++ ret = request_irq(ndev->irq, fh_gmac_interrupt, ++ IRQF_SHARED, ndev->name, ndev); ++ if (unlikely(ret < 0)) { ++ pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", ++ __func__, ndev->irq, ret); ++ goto open_error; ++ } ++ ++ /* Enable the MAC Rx/Tx */ ++ GMAC_EnableMac(pGmac); ++ ++ /* Set the HW DMA mode and the COE */ ++ /* FIXME:TTC or SF */ ++ GMAC_DMA_OpMode(pGmac); ++ ++ /* Extra statistics */ ++ memset(&pGmac->stats, 0, sizeof(struct Gmac_Stats)); ++ /* FIXME: threshold? */ ++ pGmac->stats.threshold = 64; ++ ++ /* Start the ball rolling... */ ++ pr_debug("%s: DMA RX/TX processes started...\n", ndev->name); ++ GMAC_DMA_StartTx(pGmac); ++ GMAC_DMA_StartRx(pGmac); ++ /* FIXME: dump register */ ++ ++ if (pGmac->phydev) ++ phy_start(pGmac->phydev); ++ ++ napi_enable(&pGmac->napi); ++ skb_queue_head_init(&pGmac->rx_recycle); ++ netif_start_queue(ndev); ++ ++ return 0; ++ ++open_error: ++ if (pGmac->phydev) ++ phy_disconnect(pGmac->phydev); ++ ++ return ret; ++ ++} ++ ++static int gmac_dev_stop(struct net_device *ndev) ++{ ++ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ ++ /* Stop and disconnect the PHY */ ++ if (pGmac->phydev) { ++ phy_stop(pGmac->phydev); ++ phy_disconnect(pGmac->phydev); ++ pGmac->phydev = NULL; ++ ++ pGmac->oldduplex = 0; ++ pGmac->speed = 0; ++ } ++ ++ netif_stop_queue(ndev); ++ ++ napi_disable(&pGmac->napi); ++ skb_queue_purge(&pGmac->rx_recycle); ++ ++ /* Free the IRQ lines */ ++ free_irq(ndev->irq, ndev); ++ ++ /* Stop TX/RX DMA and clear the descriptors */ ++ GMAC_DMA_StopTx(pGmac); ++ GMAC_DMA_StopRx(pGmac); ++ ++ /* Release and free the Rx/Tx resources */ ++ GMAC_DMA_FreeDesc(pGmac); ++ ++ /* Disable the MAC Rx/Tx */ ++ GMAC_DisableMac(pGmac); ++ ++ netif_carrier_off(ndev); ++ ++ fh_mdio_unregister(ndev); ++ ++ return 0; ++} ++ ++ ++static const struct net_device_ops fh_gmac_netdev_ops = { ++ .ndo_open = gmac_dev_open, ++ .ndo_stop = gmac_dev_stop, ++ .ndo_start_xmit = gmac_dev_xmit, ++ .ndo_set_multicast_list = gmac_dev_mcast_set, ++ .ndo_set_mac_address = gmac_dev_set_mac_addr, ++ .ndo_do_ioctl = gmac_dev_ioctl, ++ .ndo_tx_timeout = gmac_dev_tx_timeout, ++ .ndo_change_mtu = gmac_dev_change_mtu, ++ .ndo_fix_features = NULL, ++ .ndo_set_config = gmac_dev_set_config, ++#ifdef STMMAC_VLAN_TAG_USED ++ .ndo_vlan_rx_register = stmmac_vlan_rx_register, ++#endif ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = gmac_poll_controller, ++#endif ++}; ++ ++ ++static int __devinit fh_gmac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ Gmac_Object *pGmac; ++ struct net_device *ndev; ++ struct resource *mem_res, *irq_res; ++ struct fh_gmac_platform_data *plat_data; ++ ++ pr_info("GMAC driver:\n\tplatform registration... "); ++ ++ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem_res) { ++ pr_err("%s: ERROR: getting resource failed" ++ "cannot get IORESOURCE_MEM\n", ++ __func__); ++ return -ENODEV; ++ } ++ ++ if (!request_mem_region(mem_res->start, ++ resource_size(mem_res), pdev->name)) { ++ pr_err("%s: ERROR: memory allocation failed" ++ "cannot get the I/O addr 0x%x\n", ++ __func__, (__u32)mem_res->start); ++ return -EBUSY; ++ } ++ ++ ndev = alloc_etherdev(sizeof(Gmac_Object)); ++ ++ if (!ndev) { ++ pr_err("%s: ERROR: allocating the device\n", __func__); ++ ret = -ENOMEM; ++ goto out_release_region; ++ } ++ ++ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!irq_res) { ++ pr_err("%s: ERROR: getting resource failed" ++ "cannot get IORESOURCE_IRQ\n", __func__); ++ ret = -ENXIO; ++ goto out_free_ndev; ++ } ++ ndev->irq = irq_res->start; ++ ++ pGmac = netdev_priv(ndev); ++ ++ pGmac->remap_addr = ioremap(mem_res->start, resource_size(mem_res)); ++ ++ if (!pGmac->remap_addr) { ++ pr_err("%s: ERROR: memory mapping failed\n", __func__); ++ ret = -ENOMEM; ++ goto out_free_ndev; ++ } ++ ++ pGmac->clk = clk_get(&pdev->dev, "eth_clk"); ++ if (IS_ERR(pGmac->clk)) { ++ ret = PTR_ERR(pGmac->clk); ++ goto out_unmap; ++ } ++ clk_enable(pGmac->clk); ++ /* add net_device to platform_device */ ++ SET_NETDEV_DEV(ndev, &pdev->dev); ++ ++ pGmac->dev = &(pdev->dev); ++ pGmac->pdev = pdev; ++ pGmac->ndev = ndev; ++ plat_data = pdev->dev.platform_data; ++ pGmac->priv_data = plat_data; ++ ++ platform_set_drvdata(pdev, ndev); ++ ndev->base_addr = (unsigned long)pGmac->remap_addr; ++ ++ ether_setup(ndev); ++ ndev->netdev_ops = &fh_gmac_netdev_ops; ++ fh_gmac_set_ethtool_ops(ndev); ++ ++ ndev->hw_features = NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_RXCSUM; ++ ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ++ ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ++ pGmac->msg_enable = netif_msg_init(debug, FH_GMAC_DEBUG); ++ ++ ++ if (flow_ctrl) { ++ /* RX/TX pause on */ ++ pGmac->flow_ctrl = FLOW_AUTO; ++ } ++ ++ pGmac->pause = pause; ++ ++ ++ netif_napi_add(ndev, &(pGmac->napi), fh_gmac_poll, 64); ++ ++ ++ if (!is_valid_ether_addr(pGmac->local_mac_address)) { ++ /* Use random MAC if none passed */ ++ random_ether_addr(pGmac->local_mac_address); ++ pr_warning("\tusing random MAC address: %pM\n", ++ pGmac->local_mac_address); ++ } ++ ndev->dev_addr = pGmac->local_mac_address; ++ ++ spin_lock_init(&pGmac->lock); ++ ++ ret = register_netdev(ndev); ++ if (ret) { ++ pr_err("%s: ERROR %i registering the netdevice\n", ++ __func__, ret); ++ ret = -ENODEV; ++ goto out_plat_exit; ++ } ++ ++ pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" ++ "\t\tIO base addr: 0x%p)\n", ndev->name, pdev->name, ++ pdev->id, ndev->irq, pGmac->remap_addr); ++ ++ plat_data->interface = pGmac->phy_interface = phymode; ++ ++ /* Custom initialisation */ ++ if (pGmac->priv_data->early_init) ++ pGmac->priv_data->early_init(plat_data); ++ ++ if (pGmac->priv_data->plat_init) ++ pGmac->priv_data->plat_init(plat_data); ++ ++ return 0; ++ ++out_plat_exit: ++ clk_disable(pGmac->clk); ++out_unmap: ++ iounmap(pGmac->remap_addr); ++out_free_ndev: ++ free_netdev(ndev); ++ platform_set_drvdata(pdev, NULL); ++out_release_region: ++ release_mem_region(mem_res->start, resource_size(mem_res)); ++ ++ return ret; ++} ++ ++static int __init parse_tag_phymode(const struct tag *tag) ++{ ++ phymode = tag->u.phymode.phymode; ++ return 0; ++} ++ ++__tagtable(ATAG_PHYMODE, parse_tag_phymode); ++ ++static int __devexit fh_gmac_remove(struct platform_device *pdev) ++{ ++ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct resource *res; ++ ++ pr_info("%s:\n\tremoving driver", __func__); ++ ++ GMAC_DMA_StopTx(pGmac); ++ GMAC_DMA_StopRx(pGmac); ++ ++ GMAC_DisableMac(pGmac); ++ ++ netif_carrier_off(ndev); ++ ++ platform_set_drvdata(pdev, NULL); ++ unregister_netdev(ndev); ++ ++ clk_disable(pGmac->clk); ++ ++ iounmap((void *)pGmac->remap_addr); ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(res->start, resource_size(res)); ++ free_netdev(ndev); ++ ++ return 0; ++} ++ ++ ++#ifdef CONFIG_PM ++static int fh_gmac_suspend(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ ++ if (!ndev || !netif_running(ndev)) ++ return 0; ++ ++ spin_lock(&pGmac->lock); ++ ++ netif_device_detach(ndev); ++ netif_stop_queue(ndev); ++ if (pGmac->phydev) ++ phy_stop(pGmac->phydev); ++ ++ napi_disable(&pGmac->napi); ++ ++ /* Stop TX/RX DMA */ ++ GMAC_DMA_StopTx(pGmac); ++ GMAC_DMA_StopRx(pGmac); ++ /* Clear the Rx/Tx descriptors */ ++ GMAC_DMA_InitRxDesc(pGmac->rx_dma_descriptors, pGmac->dma_rx_size); ++ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, pGmac->dma_tx_size); ++ ++ /* Enable Power down mode by programming the PMT regs */ ++ if (device_may_wakeup(pGmac->dev)) { ++ /* no power management required */ ++ /* priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); */ ++ } else { ++ GMAC_DisableMac(pGmac); ++ } ++ ++ spin_unlock(&pGmac->lock); ++ return 0; ++} ++ ++static int fh_gmac_resume(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ u32 reg; ++ ++ reg = pGmac->mii->read(pGmac->mii, 0, 0); ++ reg |= 1 << 15; ++ pGmac->mii->write(pGmac->mii, 0, 0, reg); ++ ++ pGmac->mii->reset(pGmac->mii); ++ ++ if (!netif_running(ndev)) ++ return 0; ++ ++ spin_lock(&pGmac->lock); ++ ++ /* Power Down bit, into the PM register, is cleared ++ * automatically as soon as a magic packet or a Wake-up frame ++ * is received. Anyway, it's better to manually clear ++ * this bit because it can generate problems while resuming ++ * from another devices (e.g. serial console). */ ++ if (device_may_wakeup(pGmac->dev)) { ++ /* no power management required */ ++ /* priv->hw->mac->pmt(priv->ioaddr, 0); */ ++ } ++ ++ netif_device_attach(ndev); ++ ++ /* Enable the MAC and DMA */ ++ GMAC_EnableMac(pGmac); ++ GMAC_DMA_StartTx(pGmac); ++ GMAC_DMA_StartRx(pGmac); ++ ++ napi_enable(&pGmac->napi); ++ ++ if (pGmac->phydev) ++ phy_start(pGmac->phydev); ++ ++ netif_start_queue(ndev); ++ ++ spin_unlock(&pGmac->lock); ++ return 0; ++} ++ ++static int fh_gmac_freeze(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ ++ if (!ndev || !netif_running(ndev)) ++ return 0; ++ ++ return gmac_dev_stop(ndev); ++} ++ ++static int fh_gmac_restore(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ ++ if (!ndev || !netif_running(ndev)) ++ return 0; ++ ++ return gmac_dev_open(ndev); ++} ++ ++static const struct dev_pm_ops fh_gmac_pm_ops = { ++ .suspend = fh_gmac_suspend, ++ .resume = fh_gmac_resume, ++ .freeze = fh_gmac_freeze, ++ .thaw = fh_gmac_restore, ++ .restore = fh_gmac_restore, ++}; ++#else ++static const struct dev_pm_ops fh_gmac_pm_ops; ++#endif /* CONFIG_PM */ ++ ++ ++static struct platform_driver fh_gmac_driver = { ++ .driver = { ++ .name = "fh_gmac", ++ .owner = THIS_MODULE, ++ .pm = &fh_gmac_pm_ops, ++ }, ++ .probe = fh_gmac_probe, ++ .remove = __devexit_p(fh_gmac_remove), ++}; ++ ++static int __init fh_gmac_init(void) ++{ ++ return platform_driver_register(&fh_gmac_driver); ++} ++late_initcall(fh_gmac_init); ++ ++ ++static void __exit fh_gmac_exit(void) ++{ ++ platform_driver_unregister(&fh_gmac_driver); ++} ++module_exit(fh_gmac_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("QIN"); ++MODULE_DESCRIPTION("Fullhan Ethernet driver"); +diff --git a/drivers/net/fh_gmac/fh_gmac_phyt.c b/drivers/net/fh_gmac/fh_gmac_phyt.c +new file mode 100644 +index 00000000..f9aee3d1 +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_phyt.c +@@ -0,0 +1,227 @@ ++#include <linux/mii.h> ++#include <linux/phy.h> ++#include <linux/slab.h> ++#include <linux/delay.h> ++#include <linux/gpio.h> ++#include <mach/fh_gmac.h> ++#include "fh_gmac_phyt.h" ++#include "fh_gmac.h" ++ ++static int fh_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) ++{ ++ struct net_device *ndev = bus->priv; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ int timeout = 1000; ++ ++ if (phyaddr < 0) ++ return -ENODEV; ++ ++ writel(phyaddr << 11 | gmac_gmii_clock_100_150 << 2 | phyreg << 6 | 0x1, ++ pGmac->remap_addr + REG_GMAC_GMII_ADDRESS); ++ ++ while (readl(pGmac->remap_addr + REG_GMAC_GMII_ADDRESS) & 0x1) { ++ udelay(100); ++ timeout--; ++ if (timeout < 0) { ++ printk(KERN_ERR "ERROR: %s, timeout\n", __func__); ++ break; ++ } ++ } ++ ++ return readl(pGmac->remap_addr + REG_GMAC_GMII_DATA); ++} ++ ++static int fh_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, ++ u16 phydata) ++{ ++ struct net_device *ndev = bus->priv; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ int timeout = 1000; ++ ++ if (phyaddr < 0) ++ return -ENODEV; ++ ++ writel(phydata, pGmac->remap_addr + REG_GMAC_GMII_DATA); ++ writel(0x1 << 1 | phyaddr << 11 | gmac_gmii_clock_100_150 << 2 | phyreg ++ << 6 | 0x1, pGmac->remap_addr + REG_GMAC_GMII_ADDRESS); ++ ++ while (readl(pGmac->remap_addr + REG_GMAC_GMII_ADDRESS) & 0x1) { ++ udelay(100); ++ timeout--; ++ if (timeout < 0) { ++ printk(KERN_ERR "ERROR: %s, timeout\n", __func__); ++ break; ++ } ++ } ++ return 0; ++} ++ ++int fh_mdio_reset(struct mii_bus *bus) ++{ ++ struct net_device *ndev = bus->priv; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct fh_gmac_platform_data *plat_data; ++ ++ plat_data = pGmac->priv_data; ++ ++ if (plat_data && plat_data->phy_reset) ++ plat_data->phy_reset(); ++ ++ return 0; ++} ++ ++int fh_mdio_set_mii(struct mii_bus *bus) ++{ ++ struct net_device *ndev = bus->priv; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ __u32 rmii_mode; ++ int phyid = pGmac->priv_data->phyid; ++ ++ if (pGmac->phydev == NULL) ++ return -ENODEV; ++ ++ if (pGmac->phy_interface == PHY_INTERFACE_MODE_RMII) { ++ switch (pGmac->phydev->phy_id) { ++ case FH_GMAC_PHY_RTL8201: ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_page_select, 7); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_rmii_mode, 0x1ffa); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_page_select, 0); ++ break; ++ case FH_GMAC_PHY_IP101G: ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ip101g_page_select, 16); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_rmii_mode, 0x1006); ++#if defined(CONFIG_ARCH_FH8856) || defined(CONFIG_ARCH_ZY2) \ ++ || defined(CONFIG_ARCH_FH8626V100) ++ /* adjust ip101g rxd0 & rxd1 drv curr */ ++ fh_mdio_write(bus, phyid, 26, 0xc5ed); ++#endif ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ip101g_page_select, 0x10); ++ break; ++ case FH_GMAC_PHY_TI83848: ++ rmii_mode = fh_mdio_read(bus, phyid, ++ gmac_phyt_ti83848_rmii_mode); ++ rmii_mode |= 0x20; ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ti83848_rmii_mode, rmii_mode); ++ break; ++ default: ++ return -ENODEV; ++ } ++ } else if (pGmac->phy_interface == PHY_INTERFACE_MODE_MII) { ++ switch (pGmac->phydev->phy_id) { ++ case FH_GMAC_PHY_RTL8201: ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_page_select, 7); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_rmii_mode, 0x6ff3); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_page_select, 0); ++ break; ++ case FH_GMAC_PHY_IP101G: ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ip101g_page_select, 16); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_rtl8201_rmii_mode, 0x2); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ip101g_page_select, 0x10); ++ break; ++ case FH_GMAC_PHY_TI83848: ++ rmii_mode = fh_mdio_read(bus, phyid, ++ gmac_phyt_ti83848_rmii_mode); ++ rmii_mode &= ~(0x20); ++ fh_mdio_write(bus, phyid, ++ gmac_phyt_ti83848_rmii_mode, rmii_mode); ++ break; ++ default: ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++int fh_mdio_register(struct net_device *ndev) ++{ ++ int err = 0, found, addr; ++ struct mii_bus *new_bus; ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ struct phy_device *phydev = NULL; ++ ++ new_bus = mdiobus_alloc(); ++ if (new_bus == NULL) ++ return -ENOMEM; ++ new_bus->name = ++ pGmac->phy_interface == ++ PHY_INTERFACE_MODE_MII ? "gmac_mii" : "gmac_rmii"; ++ new_bus->read = &fh_mdio_read; ++ new_bus->write = &fh_mdio_write; ++ new_bus->reset = &fh_mdio_reset; ++ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", 0); ++ new_bus->priv = ndev; ++ new_bus->parent = pGmac->dev; ++ err = mdiobus_register(new_bus); ++ if (err != 0) { ++ pr_err("%s: Cannot register as MDIO bus, error: %d\n", ++ new_bus->name, err); ++ goto bus_register_fail; ++ } ++ ++ pGmac->mii = new_bus; ++ ++ found = 0; ++ for (addr = 0; addr < 32; addr++) { ++ phydev = new_bus->phy_map[addr]; ++ if (phydev) { ++ if (pGmac->priv_data->phyid == -1) ++ pGmac->priv_data->phyid = addr; ++ ++ found = 1; ++ pGmac->phydev = phydev; ++ break; ++ } ++ } ++ ++ if (pGmac->mii == NULL || phydev == NULL) { ++ pr_warning("%s: MII BUS or phydev is NULL\n", ndev->name); ++ err = -ENXIO; ++ goto bus_register_fail; ++ } ++ ++ err = fh_mdio_set_mii(pGmac->mii); ++ ++ if (!found || err) { ++ pr_warning("%s: No PHY found\n", ndev->name); ++ err = -ENXIO; ++ goto bus_register_fail; ++ } ++ ++ pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n", ++ ndev->name, pGmac->phydev->phy_id, addr, ++ pGmac->phydev->irq, dev_name(&pGmac->phydev->dev), ++ (addr == ++ pGmac->priv_data->phyid) ? " active" : ""); ++ ++ return 0; ++ ++bus_register_fail: ++ pGmac->phydev = NULL; ++ mdiobus_unregister(new_bus); ++ kfree(new_bus); ++ return err; ++} ++ ++int fh_mdio_unregister(struct net_device *ndev) ++{ ++ Gmac_Object *pGmac = netdev_priv(ndev); ++ ++ mdiobus_unregister(pGmac->mii); ++ pGmac->mii->priv = NULL; ++ kfree(pGmac->mii); ++ return 0; ++} +diff --git a/drivers/net/fh_gmac/fh_gmac_phyt.h b/drivers/net/fh_gmac/fh_gmac_phyt.h +new file mode 100755 +index 00000000..de53c08d +--- /dev/null ++++ b/drivers/net/fh_gmac/fh_gmac_phyt.h +@@ -0,0 +1,83 @@ ++/* ++ * fh_gmac_phyt.h ++ * ++ * Created on: May 22, 2014 ++ * Author: duobao ++ */ ++ ++#ifndef FH_GMAC_PHYT_H_ ++#define FH_GMAC_PHYT_H_ ++ ++#define FH_GMAC_PHY_IP101G 0x02430C54 ++#define FH_GMAC_PHY_RTL8201 0x001CC816 ++#define FH_GMAC_PHY_TI83848 0xFFFFFFFF ++ ++enum ++{ ++ gmac_phyt_speed_10M_half_duplex = 1, ++ gmac_phyt_speed_100M_half_duplex = 2, ++ gmac_phyt_speed_10M_full_duplex = 5, ++ gmac_phyt_speed_100M_full_duplex = 6 ++}; ++ ++ ++typedef union ++{ ++ struct ++ { ++ __u32 reserved_6_0 :7; ++ __u32 collision_test :1; ++ __u32 duplex_mode :1; ++ __u32 restart_auto_negotiate :1; ++ __u32 isolate :1; ++ __u32 power_down :1; ++ __u32 auto_negotiate_enable :1; ++ __u32 speed_select :1; ++ __u32 loopback :1; ++ __u32 reset :1; ++ __u32 reserved_31_16 :16; ++ }bit; ++ __u32 dw; ++}Reg_Phyt_Basic_Ctrl; ++ ++ ++typedef union ++{ ++ struct ++ { ++ __u32 extended_capabilities :1; ++ __u32 jabber_detect :1; ++ __u32 link_status :1; ++ __u32 auto_negotiate_ability :1; ++ __u32 remote_fault :1; ++ __u32 auto_negotiate_complete :1; ++ __u32 reserved_10_6 :5; ++ __u32 base_t_half_duplex_10 :1; ++ __u32 base_t_full_duplex_10 :1; ++ __u32 base_tx_half_duplex_100 :1; ++ __u32 base_tx_full_duplex_100 :1; ++ __u32 base_t_4 :1; ++ __u32 reserved_31_16 :16; ++ }bit; ++ __u32 dw; ++}Reg_Phyt_Basic_Status; ++ ++typedef union ++{ ++ struct ++ { ++ __u32 scramble_disable :1; ++ __u32 reserved_1 :1; ++ __u32 speed_indication :3; ++ __u32 reserved_5 :1; ++ __u32 enable_4b5b :1; ++ __u32 gpo :3; ++ __u32 reserved_11_10 :2; ++ __u32 auto_done :1; ++ __u32 reserved_31_13 :19; ++ }bit; ++ __u32 dw; ++}Reg_Phyt_Special_Status; ++ ++ ++#endif /* FH_GMAC_PHYT_H_ */ +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index a4759576..1c6eed4b 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -749,7 +749,8 @@ void phy_start(struct phy_device *phydev) + phydev->state = PHY_PENDING; + break; + case PHY_READY: +- phydev->state = PHY_UP; ++ phydev->link_timeout = PHY_AN_TIMEOUT; ++ phydev->state = PHY_AN; + break; + case PHY_HALTED: + phydev->state = PHY_RESUMING; +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index ff109fe5..6ede872a 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -845,7 +845,7 @@ static int genphy_config_init(struct phy_device *phydev) + * all possible port types */ + features = (SUPPORTED_TP | SUPPORTED_MII + | SUPPORTED_AUI | SUPPORTED_FIBRE | +- SUPPORTED_BNC); ++ SUPPORTED_BNC | SUPPORTED_Pause); + + /* Do we support autonegotiation? */ + val = phy_read(phydev, MII_BMSR); +diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c +index 52502883..3b5025a1 100644 +--- a/drivers/net/usb/asix.c ++++ b/drivers/net/usb/asix.c +@@ -20,8 +20,8 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +-// #define DEBUG // error path messages, extra info +-// #define VERBOSE // more; success messages ++/* #define DEBUG */ ++/* #define VERBOSE */ + + #include <linux/module.h> + #include <linux/kmod.h> +@@ -39,6 +39,22 @@ + #define DRIVER_VERSION "14-Jun-2006" + static const char driver_name [] = "asix"; + ++/* cpy from linux 49 by zhangy 2018-10-31*/ ++struct asix_rx_fixup_info { ++ struct sk_buff *ax_skb; ++ u32 header; ++ u16 remaining; ++ bool split_head; ++}; ++/* cpy from linux 49 by zhangy 2018-10-31*/ ++struct asix_common_private { ++ void (*resume)(struct usbnet *dev); ++ void (*suspend)(struct usbnet *dev); ++ u16 presvd_phy_advertise; ++ u16 presvd_phy_bmcr; ++ struct asix_rx_fixup_info rx_fixup_info; ++}; ++ + /* ASIX AX8817X based USB 2.0 Ethernet Devices */ + + #define AX_CMD_SET_SW_MII 0x06 +@@ -135,8 +151,8 @@ static const char driver_name [] = "asix"; + #define AX_RX_CTL_MFB_8192 0x0200 + #define AX_RX_CTL_MFB_16384 0x0300 + +-#define AX_DEFAULT_RX_CTL \ +- (AX_RX_CTL_SO | AX_RX_CTL_AB ) ++ ++#define AX_DEFAULT_RX_CTL ( AX_RX_CTL_AB ) + + /* GPIO 0 .. 2 toggles */ + #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ +@@ -163,7 +179,7 @@ static const char driver_name [] = "asix"; + + #define MARVELL_CTRL_TXDELAY 0x0002 + #define MARVELL_CTRL_RXDELAY 0x0080 +- ++struct asix_common_private * get_asix_private(struct usbnet *dev); + /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ + struct asix_data { + u8 multi_filter[AX_MCAST_FILTER_SIZE]; +@@ -266,15 +282,19 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, + int status; + struct urb *urb; + +- netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", ++ netdev_dbg(dev->net, "asix_write_cmd_async()" ++ "cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); + if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { +- netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); ++ netdev_err(dev->net, ++ "Error allocating URB in write_cmd_async!\n"); + return; + } + +- if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { +- netdev_err(dev->net, "Failed to allocate memory for control request\n"); ++ if ((req = kmalloc(sizeof(struct usb_ctrlrequest), ++ GFP_ATOMIC)) == NULL) { ++ netdev_err(dev->net, ++ "Failed to allocate memory for control request\n"); + usb_free_urb(urb); + return; + } +@@ -290,7 +310,7 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, + (void *)req, data, size, + asix_async_cmd_callback, req); + +- if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { ++ if ((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { + netdev_err(dev->net, "Error submitting the control message: status=%d\n", + status); + kfree(req); +@@ -298,98 +318,120 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, + } + } + ++/* cpy from linux 49 by zhangy 2018-10-31*/ + static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) + { +- u8 *head; +- u32 header; +- char *packet; +- struct sk_buff *ax_skb; ++ struct asix_rx_fixup_info *rx; ++ struct asix_common_private *priv; ++ int offset = 0; + u16 size; ++ priv = get_asix_private(dev); ++ rx = &priv->rx_fixup_info; ++ /* When an Ethernet frame spans multiple URB socket buffers, ++ * do a sanity test for the Data header synchronisation. ++ * Attempt to detect the situation of the previous socket buffer having ++ * been truncated or a socket buffer was missing. These situations ++ * cause a discontinuity in the data stream and therefore need to avoid ++ * appending bad data to the end of the current netdev socket buffer. ++ * Also avoid unnecessarily discarding a good current netdev socket ++ * buffer. ++ */ ++ if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) { ++ offset = ((rx->remaining + 1) & 0xfffe); ++ rx->header = get_unaligned_le32(skb->data + offset); ++ offset = 0; ++ ++ size = (u16)(rx->header & 0x7ff); ++ if (size != ((~rx->header >> 16) & 0x7ff)) { ++ netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", ++ rx->remaining); ++ if (rx->ax_skb) { ++ kfree_skb(rx->ax_skb); ++ rx->ax_skb = NULL; ++ /* Discard the incomplete netdev Ethernet frame ++ * and assume the Data header is at the start of ++ * the current URB socket buffer. ++ */ ++ } ++ rx->remaining = 0; ++ } ++ } + +- head = (u8 *) skb->data; +- memcpy(&header, head, sizeof(header)); +- le32_to_cpus(&header); +- packet = head + sizeof(header); ++ while (offset + sizeof(u16) <= skb->len) { ++ u16 copy_length; ++ unsigned char *data; ++ ++ if (!rx->remaining) { ++ if (skb->len - offset == sizeof(u16)) { ++ rx->header = get_unaligned_le16( ++ skb->data + offset); ++ rx->split_head = true; ++ offset += sizeof(u16); ++ break; ++ } + +- skb_pull(skb, 4); ++ if (rx->split_head == true) { ++ rx->header |= (get_unaligned_le16( ++ skb->data + offset) << 16); ++ rx->split_head = false; ++ offset += sizeof(u16); ++ } else { ++ rx->header = get_unaligned_le32(skb->data + ++ offset); ++ offset += sizeof(u32); ++ } + +- while (skb->len > 0) { +- if ((short)(header & 0x0000ffff) != +- ~((short)((header & 0xffff0000) >> 16))) { +- netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); +- } +- /* get the packet length */ +- size = (u16) (header & 0x0000ffff); +- +- if ((skb->len) - ((size + 1) & 0xfffe) == 0) { +- u8 alignment = (unsigned long)skb->data & 0x3; +- if (alignment != 0x2) { +- /* +- * not 16bit aligned so use the room provided by +- * the 32 bit header to align the data +- * +- * note we want 16bit alignment as MAC header is +- * 14bytes thus ip header will be aligned on +- * 32bit boundary so accessing ipheader elements +- * using a cast to struct ip header wont cause +- * an unaligned accesses. +- */ +- u8 realignment = (alignment + 2) & 0x3; +- memmove(skb->data - realignment, +- skb->data, +- size); +- skb->data -= realignment; +- skb_set_tail_pointer(skb, size); ++ /* take frame length from Data header 32-bit word */ ++ size = (u16)(rx->header & 0x7ff); ++ if (size != ((~rx->header >> 16) & 0x7ff)) { ++ netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n", ++ rx->header, offset); ++ return 0; + } +- return 2; +- } ++ if (size > dev->net->mtu + ETH_HLEN + 4) { ++ netdev_dbg(dev->net, "asix_rx_fixup() Bad RX Length %d\n", ++ size); ++ return 0; ++ } ++ ++ /* Sometimes may fail to get a netdev socket buffer but ++ * continue to process the URB socket buffer so that ++ * synchronisation of the Ethernet frame Data header ++ * word is maintained. ++ */ ++ rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size); + +- if (size > dev->net->mtu + ETH_HLEN) { +- netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", +- size); +- return 0; ++ rx->remaining = size; + } +- ax_skb = skb_clone(skb, GFP_ATOMIC); +- if (ax_skb) { +- u8 alignment = (unsigned long)packet & 0x3; +- ax_skb->len = size; +- +- if (alignment != 0x2) { +- /* +- * not 16bit aligned use the room provided by +- * the 32 bit header to align the data +- */ +- u8 realignment = (alignment + 2) & 0x3; +- memmove(packet - realignment, packet, size); +- packet -= realignment; +- } +- ax_skb->data = packet; +- skb_set_tail_pointer(ax_skb, size); +- usbnet_skb_return(dev, ax_skb); ++ ++ if (rx->remaining > skb->len - offset) { ++ copy_length = skb->len - offset; ++ rx->remaining -= copy_length; + } else { +- return 0; ++ copy_length = rx->remaining; ++ rx->remaining = 0; + } + +- skb_pull(skb, (size + 1) & 0xfffe); +- +- if (skb->len == 0) +- break; ++ if (rx->ax_skb) { ++ data = skb_put(rx->ax_skb, copy_length); ++ memcpy(data, skb->data + offset, copy_length); ++ if (!rx->remaining) ++ usbnet_skb_return(dev, rx->ax_skb); ++ } + +- head = (u8 *) skb->data; +- memcpy(&header, head, sizeof(header)); +- le32_to_cpus(&header); +- packet = head + sizeof(header); +- skb_pull(skb, 4); ++ offset += (copy_length + 1) & 0xfffe; + } + +- if (skb->len < 0) { +- netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", +- skb->len); ++ if (skb->len != offset) { ++ netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d, %d\n", ++ skb->len, offset); + return 0; + } ++ + return 1; + } + ++ + static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) + { +@@ -442,7 +484,7 @@ static void asix_status(struct usbnet *dev, struct urb *urb) + if (netif_carrier_ok(dev->net) != link) { + if (link) { + netif_carrier_on(dev->net); +- usbnet_defer_kevent (dev, EVENT_LINK_RESET ); ++ usbnet_defer_kevent(dev, EVENT_LINK_RESET); + } else + netif_carrier_off(dev->net); + netdev_dbg(dev->net, "Link Status is: %d\n", link); +@@ -489,8 +531,7 @@ out: + static int asix_sw_reset(struct usbnet *dev, u8 flags) + { + int ret; +- +- ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); ++ ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); + if (ret < 0) + netdev_err(dev->net, "Failed to send software reset: %02x\n", ret); + +@@ -514,7 +555,6 @@ out: + static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) + { + int ret; +- + netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode); + ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); + if (ret < 0) +@@ -562,9 +602,6 @@ static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) + netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n", + value, ret); + +- if (sleep) +- msleep(sleep); +- + return ret; + } + +@@ -575,7 +612,7 @@ static void asix_set_multicast(struct net_device *net) + { + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; +- u16 rx_ctl = AX_DEFAULT_RX_CTL; ++ u16 rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_SO; + + if (net->flags & IFF_PROMISC) { + rx_ctl |= AX_RX_CTL_PRO; +@@ -729,7 +766,7 @@ static int asix_get_eeprom(struct net_device *net, + eeprom->magic = AX_EEPROM_MAGIC; + + /* ax8817x returns 2 bytes from eeprom on read */ +- for (i=0; i < eeprom->len / 2; i++) { ++ for (i = 0; i < eeprom->len / 2; i++) { + if (asix_read_cmd(dev, AX_CMD_READ_EEPROM, + eeprom->offset + i, 0, 2, &ebuf[i]) < 0) + return -EINVAL; +@@ -757,7 +794,7 @@ static u32 asix_get_link(struct net_device *net) + return mii_link_ok(&dev->mii); + } + +-static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) ++static int asix_ioctl(struct net_device *net, struct ifreq *rq, int cmd) + { + struct usbnet *dev = netdev_priv(net); + +@@ -870,7 +907,7 @@ static const struct net_device_ops ax88172_netdev_ops = { + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, +- .ndo_set_mac_address = eth_mac_addr, ++ .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = asix_ioctl, + .ndo_set_multicast_list = ax88172_set_multicast, +@@ -886,7 +923,7 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) + + data->eeprom_len = AX88172_EEPROM_LEN; + +- usbnet_get_endpoints(dev,intf); ++ usbnet_get_endpoints(dev, intf); + + /* Toggle the GPIOs in a manufacturer/model specific way */ + for (i = 2; i >= 0; i--) { +@@ -894,7 +931,6 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf) + (gpio_bits >> (i * 8)) & 0xff, 0, 0, + NULL)) < 0) + goto out; +- msleep(5); + } + + if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0) +@@ -963,7 +999,7 @@ static int ax88772_link_reset(struct usbnet *dev) + ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); + + asix_write_medium_mode(dev, mode); +- ++ asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL | AX_RX_CTL_SO); + return 0; + } + +@@ -973,12 +1009,46 @@ static const struct net_device_ops ax88772_netdev_ops = { + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, +- .ndo_set_mac_address = asix_set_mac_address, ++ .ndo_set_mac_address = asix_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = asix_ioctl, + .ndo_set_multicast_list = asix_set_multicast, + }; + ++#ifdef ASIX_USE_UNBIND ++/* zhangy add unbind. but crash when usb reconnect */ ++static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx) ++{ ++ if (rx->ax_skb) ++ { ++ kfree_skb(rx->ax_skb); ++ rx->ax_skb = NULL; ++ } ++ rx->remaining = 0; ++ rx->split_head = false; ++ rx->header = 0; ++ ++} ++static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf) ++{ ++ struct asix_common_private *p_private; ++ p_private = dev->driver_info->driver_priv; ++ if (p_private) { ++ reset_asix_rx_fixup_info(&p_private->rx_fixup_info); ++ /*may be add reset first...*/ ++ kfree(p_private); ++ } ++ ++} ++#endif ++ ++struct asix_common_private *get_asix_private(struct usbnet *dev) ++{ ++ if (dev->driver_info->driver_priv) ++ return (struct asix_common_private *)dev->driver_info->driver_priv; ++ return NULL; ++} ++ + static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) + { + int ret, embd_phy; +@@ -989,7 +1059,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) + + data->eeprom_len = AX88772_EEPROM_LEN; + +- usbnet_get_endpoints(dev,intf); ++ usbnet_get_endpoints(dev, intf); + + if ((ret = asix_write_gpio(dev, + AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) +@@ -1002,25 +1072,26 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) + dbg("Select PHY #1 failed: %d", ret); + goto out; + } +- ++ /* malloc private info by zhangy add below*/ ++ if (!dev->driver_info->driver_priv) { ++ dev->driver_info->driver_priv = kzalloc(sizeof(struct asix_common_private), GFP_KERNEL); ++ if (!dev->driver_info->driver_priv) ++ return -ENOMEM; ++ } + if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0) + goto out; + +- msleep(150); + if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0) + goto out; + +- msleep(150); + if (embd_phy) { + if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) + goto out; +- } +- else { ++ } else { + if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0) + goto out; + } + +- msleep(150); + rx_ctl = asix_read_rx_ctl(dev); + dbg("RX_CTL is 0x%04x after software reset", rx_ctl); + if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0) +@@ -1051,13 +1122,9 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) + if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) + goto out; + +- msleep(150); +- + if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0) + goto out; + +- msleep(150); +- + dev->net->netdev_ops = &ax88772_netdev_ops; + dev->net->ethtool_ops = &ax88772_ethtool_ops; + +@@ -1154,13 +1221,13 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) + reg &= 0xfc0f; + + switch (speed) { +- case SPEED_1000: ++ case SPEED_1000: + reg |= 0x03e0; + break; +- case SPEED_100: ++ case SPEED_100: + reg |= 0x03b0; + break; +- default: ++ default: + reg |= 0x02f0; + } + +@@ -1286,7 +1353,7 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) + int gpio0 = 0; + u32 phyid; + +- usbnet_get_endpoints(dev,intf); ++ usbnet_get_endpoints(dev, intf); + + asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); + dbg("GPIO Status: 0x%04x", status); +@@ -1320,10 +1387,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) + } + + asix_sw_reset(dev, 0); +- msleep(150); + + asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); +- msleep(150); + + asix_write_rx_ctl(dev, 0); + +@@ -1352,7 +1417,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf) + + if (data->phymode == PHY_MODE_MARVELL) { + marvell_phy_init(dev); +- msleep(60); + } + + asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, +@@ -1425,10 +1489,13 @@ static const struct driver_info hawking_uf200_info = { + static const struct driver_info ax88772_info = { + .description = "ASIX AX88772 USB 2.0 Ethernet", + .bind = ax88772_bind, ++#ifdef ASIX_USE_UNBIND ++ .unbind = ax88772_unbind, ++#endif + .status = asix_status, + .link_reset = ax88772_link_reset, + .reset = ax88772_link_reset, +- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR, ++ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR , + .rx_fixup = asix_rx_fixup, + .tx_fixup = asix_tx_fixup, + }; +@@ -1444,125 +1511,146 @@ static const struct driver_info ax88178_info = { + .tx_fixup = asix_tx_fixup, + }; + +-static const struct usb_device_id products [] = { ++static const struct usb_device_id products[] = { + { +- // Linksys USB200M + USB_DEVICE (0x077b, 0x2226), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // Netgear FA120 ++}, ++{ + USB_DEVICE (0x0846, 0x1040), + .driver_info = (unsigned long) &netgear_fa120_info, +-}, { +- // DLink DUB-E100 ++}, ++{ + USB_DEVICE (0x2001, 0x1a00), + .driver_info = (unsigned long) &dlink_dub_e100_info, +-}, { +- // Intellinet, ST Lab USB Ethernet ++}, ++{ + USB_DEVICE (0x0b95, 0x1720), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // Hawking UF200, TrendNet TU2-ET100 ++}, ++{ + USB_DEVICE (0x07b8, 0x420a), + .driver_info = (unsigned long) &hawking_uf200_info, +-}, { +- // Billionton Systems, USB2AR ++}, ++{ + USB_DEVICE (0x08dd, 0x90ff), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // ATEN UC210T ++}, ++{ + USB_DEVICE (0x0557, 0x2009), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // Buffalo LUA-U2-KTX ++}, ++{ ++ + USB_DEVICE (0x0411, 0x003d), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // Buffalo LUA-U2-GT 10/100/1000 ++}, ++{ ++ + USB_DEVICE (0x0411, 0x006e), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" ++}, ++{ ++ + USB_DEVICE (0x6189, 0x182d), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // corega FEther USB2-TX ++}, ++{ ++ + USB_DEVICE (0x07aa, 0x0017), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // Surecom EP-1427X-2 ++}, ++{ ++ + USB_DEVICE (0x1189, 0x0893), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // goodway corp usb gwusb2e ++}, ++{ ++ + USB_DEVICE (0x1631, 0x6200), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // JVC MP-PRX1 Port Replicator ++}, ++{ ++ + USB_DEVICE (0x04f1, 0x3008), + .driver_info = (unsigned long) &ax8817x_info, +-}, { +- // ASIX AX88772B 10/100 ++}, ++{ ++ + USB_DEVICE (0x0b95, 0x772b), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // ASIX AX88772 10/100 ++}, ++{ ++ + USB_DEVICE (0x0b95, 0x7720), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // ASIX AX88178 10/100/1000 ++}, ++{ ++ + USB_DEVICE (0x0b95, 0x1780), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // Logitec LAN-GTJ/U2A ++}, ++{ ++ + USB_DEVICE (0x0789, 0x0160), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // Linksys USB200M Rev 2 ++}, ++{ ++ + USB_DEVICE (0x13b1, 0x0018), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // 0Q0 cable ethernet ++}, ++{ ++ + USB_DEVICE (0x1557, 0x7720), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // DLink DUB-E100 H/W Ver B1 ++}, ++{ ++ + USB_DEVICE (0x07d1, 0x3c05), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // DLink DUB-E100 H/W Ver B1 Alternate ++}, ++{ ++ + USB_DEVICE (0x2001, 0x3c05), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // Linksys USB1000 ++}, ++{ ++ + USB_DEVICE (0x1737, 0x0039), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // IO-DATA ETG-US2 +- USB_DEVICE (0x04bb, 0x0930), ++}, ++{ ++ ++ USB_DEVICE(0x04bb, 0x0930), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // Belkin F5D5055 ++}, ++{ ++ + USB_DEVICE(0x050d, 0x5055), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // Apple USB Ethernet Adapter ++}, ++{ ++ + USB_DEVICE(0x05ac, 0x1402), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // Cables-to-Go USB Ethernet Adapter ++}, ++{ ++ + USB_DEVICE(0x0b95, 0x772a), + .driver_info = (unsigned long) &ax88772_info, +-}, { +- // ABOCOM for pci ++}, ++{ ++ + USB_DEVICE(0x14ea, 0xab11), + .driver_info = (unsigned long) &ax88178_info, +-}, { +- // ASIX 88772a ++}, ++{ ++ + USB_DEVICE(0x0db0, 0xa877), + .driver_info = (unsigned long) &ax88772_info, + }, +- { }, // END ++ { }, + }; + MODULE_DEVICE_TABLE(usb, products); + +@@ -1578,13 +1666,13 @@ static struct usb_driver asix_driver = { + + static int __init asix_init(void) + { +- return usb_register(&asix_driver); ++ return usb_register(&asix_driver); + } + module_init(asix_init); + + static void __exit asix_exit(void) + { +- usb_deregister(&asix_driver); ++ usb_deregister(&asix_driver); + } + module_exit(asix_exit); + +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index ce395fe5..1e456a82 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -64,19 +64,18 @@ + * is required, under load. Jumbograms change the equation. + */ + #define RX_MAX_QUEUE_MEMORY (60 * 1518) ++ + #define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ + (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4) + #define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \ + (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4) + +-// reawaken network queue this soon after stopping; else watchdog barks ++ + #define TX_TIMEOUT_JIFFIES (5*HZ) + +-// throttle rx/tx briefly after some faults, so khubd might disconnect() +-// us (it polls at HZ/4 usually) before we report too many false errors. ++ + #define THROTTLE_JIFFIES (HZ/8) + +-// between wakeups + #define UNLINK_TIMEOUT_MS 3 + + /*-------------------------------------------------------------------------*/ +@@ -92,7 +91,7 @@ module_param (msg_level, int, 0); + MODULE_PARM_DESC (msg_level, "Override default message level"); + + /*-------------------------------------------------------------------------*/ +- ++static void usbnet_bh (unsigned long param); + /* handles CDC Ethernet and many other network "bulk data" interfaces */ + int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) + { +@@ -239,13 +238,15 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) + skb->len + sizeof (struct ethhdr), skb->protocol); + memset (skb->cb, 0, sizeof (struct skb_data)); + status = netif_rx (skb); +- if (status != NET_RX_SUCCESS) ++ if (status != NET_RX_SUCCESS){ + netif_dbg(dev, rx_err, dev->net, + "netif_rx status %d\n", status); ++ } ++ + } + EXPORT_SYMBOL_GPL(usbnet_skb_return); + +- ++ + /*------------------------------------------------------------------------- + * + * Network Device Driver (peer link to "Host Device", from USB host) +@@ -283,18 +284,30 @@ EXPORT_SYMBOL_GPL(usbnet_change_mtu); + * completion callbacks. 2.5 should have fixed those bugs... + */ + +-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list) ++static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, ++ struct sk_buff_head *list, enum skb_state state) + { + unsigned long flags; ++ enum skb_state old_state; ++ struct skb_data *entry = (struct skb_data *) skb->cb; + + spin_lock_irqsave(&list->lock, flags); ++ old_state = entry->state; ++ entry->state = state; + __skb_unlink(skb, list); +- spin_unlock(&list->lock); +- spin_lock(&dev->done.lock); ++ ++ /* defer_bh() is never called with list == &dev->done. ++ * spin_lock_nested() tells lockdep that it is OK to take ++ * dev->done.lock here with list->lock held. ++ */ ++ spin_lock_nested(&dev->done.lock, SINGLE_DEPTH_NESTING); ++ + __skb_queue_tail(&dev->done, skb); + if (dev->done.qlen == 1) + tasklet_schedule(&dev->bh); +- spin_unlock_irqrestore(&dev->done.lock, flags); ++ spin_unlock(&dev->done.lock); ++ spin_unlock_irqrestore(&list->lock, flags); ++ return old_state; + } + + /* some work can't be done in tasklets, so we use keventd +@@ -324,12 +337,19 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) + unsigned long lockflags; + size_t size = dev->rx_urb_size; + ++ /* prevent rx skb allocation when error ratio is high */ ++ if (test_bit(EVENT_RX_KILL, &dev->flags)) { ++ usb_free_urb(urb); ++ return -ENOLINK; ++ } ++ + if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { + netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); + usbnet_defer_kevent (dev, EVENT_RX_MEMORY); + usb_free_urb (urb); + return -ENOMEM; + } ++ /* skb_reserve case memleak here */ + skb_reserve (skb, NET_IP_ALIGN); + + entry = (struct skb_data *) skb->cb; +@@ -337,10 +357,8 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) + entry->dev = dev; + entry->state = rx_start; + entry->length = 0; +- + usb_fill_bulk_urb (urb, dev->udev, dev->in, + skb->data, size, rx_complete, skb); +- + spin_lock_irqsave (&dev->rxq.lock, lockflags); + + if (netif_running (dev->net) && +@@ -395,44 +413,41 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) + } + // else network stack removes extra byte if we forced a short packet + +- if (skb->len) { +- /* all data was already cloned from skb inside the driver */ +- if (dev->driver_info->flags & FLAG_MULTI_PACKET) +- dev_kfree_skb_any(skb); +- else +- usbnet_skb_return(dev, skb); ++ /* all data was already cloned from skb inside the driver */ ++ if (dev->driver_info->flags & FLAG_MULTI_PACKET) ++ goto done; ++ ++ if (skb->len < ETH_HLEN) { ++ dev->net->stats.rx_errors++; ++ dev->net->stats.rx_length_errors++; ++ netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); ++ } else { ++ usbnet_skb_return(dev, skb); + return; + } + +- netif_dbg(dev, rx_err, dev->net, "drop\n"); +- dev->net->stats.rx_errors++; + done: + skb_queue_tail(&dev->done, skb); + } + + /*-------------------------------------------------------------------------*/ + ++ + static void rx_complete (struct urb *urb) + { + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct skb_data *entry = (struct skb_data *) skb->cb; + struct usbnet *dev = entry->dev; + int urb_status = urb->status; ++ enum skb_state state; + + skb_put (skb, urb->actual_length); +- entry->state = rx_done; ++ state = rx_done; + entry->urb = NULL; + + switch (urb_status) { + /* success */ + case 0: +- if (skb->len < dev->net->hard_header_len) { +- entry->state = rx_cleanup; +- dev->net->stats.rx_errors++; +- dev->net->stats.rx_length_errors++; +- netif_dbg(dev, rx_err, dev->net, +- "rx length %d\n", skb->len); +- } + break; + + /* stalls need manual reset. this is rare ... except that +@@ -452,9 +467,9 @@ static void rx_complete (struct urb *urb) + "rx shutdown, code %d\n", urb_status); + goto block; + +- /* we get controller i/o faults during khubd disconnect() delays. ++ /* we get controller i/o faults during hub_wq disconnect() delays. + * throttle down resubmits, to avoid log floods; just temporarily, +- * so we still recover when the fault isn't a khubd delay. ++ * so we still recover when the fault isn't a hub_wq delay. + */ + case -EPROTO: + case -ETIME: +@@ -466,7 +481,7 @@ static void rx_complete (struct urb *urb) + "rx throttle %d\n", urb_status); + } + block: +- entry->state = rx_cleanup; ++ state = rx_cleanup; + entry->urb = urb; + urb = NULL; + break; +@@ -477,25 +492,37 @@ block: + // FALLTHROUGH + + default: +- entry->state = rx_cleanup; ++ state = rx_cleanup; + dev->net->stats.rx_errors++; + netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status); + break; + } + +- defer_bh(dev, skb, &dev->rxq); ++ /* stop rx if packet error rate is high */ ++ if (++dev->pkt_cnt > 30) { ++ dev->pkt_cnt = 0; ++ dev->pkt_err = 0; ++ } else { ++ if (state == rx_cleanup) ++ dev->pkt_err++; ++ if (dev->pkt_err > 20) ++ set_bit(EVENT_RX_KILL, &dev->flags); ++ } ++ ++ state = defer_bh(dev, skb, &dev->rxq, state); + + if (urb) { + if (netif_running (dev->net) && +- !test_bit (EVENT_RX_HALT, &dev->flags)) { ++ !test_bit (EVENT_RX_HALT, &dev->flags) && ++ state != unlink_start) { + rx_submit (dev, urb, GFP_ATOMIC); ++ usb_mark_last_busy(dev->udev); + return; + } + usb_free_urb (urb); + } + netif_dbg(dev, rx_err, dev->net, "no read resubmitted\n"); + } +- + static void intr_complete (struct urb *urb) + { + struct usbnet *dev = urb->context; +@@ -573,18 +600,34 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq); + static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) + { + unsigned long flags; +- struct sk_buff *skb, *skbnext; ++ struct sk_buff *skb; + int count = 0; + + spin_lock_irqsave (&q->lock, flags); +- skb_queue_walk_safe(q, skb, skbnext) { ++ while (!skb_queue_empty(q)) { + struct skb_data *entry; + struct urb *urb; + int retval; + +- entry = (struct skb_data *) skb->cb; ++ skb_queue_walk(q, skb) { ++ entry = (struct skb_data *) skb->cb; ++ if (entry->state != unlink_start) ++ goto found; ++ } ++ break; ++found: ++ entry->state = unlink_start; + urb = entry->urb; + ++ /* ++ * Get reference count of the URB to avoid it to be ++ * freed during usb_unlink_urb, which may trigger ++ * use-after-free problem inside usb_unlink_urb since ++ * usb_unlink_urb is always racing with .complete ++ * handler(include defer_bh). ++ */ ++ usb_get_urb(urb); ++ spin_unlock_irqrestore(&q->lock, flags); + // during some PM-driven resume scenarios, + // these (async) unlinks complete immediately + retval = usb_unlink_urb (urb); +@@ -592,6 +635,8 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) + netdev_dbg(dev->net, "unlink urb err, %d\n", retval); + else + count++; ++ usb_put_urb(urb); ++ spin_lock_irqsave(&q->lock, flags); + } + spin_unlock_irqrestore (&q->lock, flags); + return count; +@@ -710,7 +755,6 @@ int usbnet_open (struct net_device *net) + goto done_nopm; + } + +- // put into "known safe" state + if (info->reset && (retval = info->reset (dev)) < 0) { + netif_info(dev, ifup, dev->net, + "open reset fail (%d) usbnet usb-%s-%s, %s\n", +@@ -750,6 +794,11 @@ int usbnet_open (struct net_device *net) + (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" : + "simple"); + ++ /* reset rx error state */ ++ dev->pkt_cnt = 0; ++ dev->pkt_err = 0; ++ clear_bit(EVENT_RX_KILL, &dev->flags); ++ + // delay posting reads until we're fully open + tasklet_schedule (&dev->bh); + if (info->manage_power) { +@@ -884,7 +933,6 @@ kevent (struct work_struct *work) + container_of(work, struct usbnet, kevent); + int status; + +- /* usb_clear_halt() needs a thread context */ + if (test_bit (EVENT_TX_HALT, &dev->flags)) { + unlink_urbs (dev, &dev->txq); + status = usb_autopm_get_interface(dev->intf); +@@ -1023,8 +1071,8 @@ static void tx_complete (struct urb *urb) + + usb_autopm_put_interface_async(dev->intf); + urb->dev = NULL; +- entry->state = tx_done; +- defer_bh(dev, skb, &dev->txq); ++ ++ (void) defer_bh(dev, skb, &dev->txq, tx_done); + } + + /*-------------------------------------------------------------------------*/ +@@ -1082,7 +1130,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, + + usb_fill_bulk_urb (urb, dev->udev, dev->out, + skb->data, skb->len, tx_complete, skb); +- ++ //printk("\n [tx] user complete add is %x\n",(unsigned int)tx_complete); + /* don't assume the hardware handles USB_ZERO_PACKET + * NOTE: strictly conforming cdc-ether devices should expect + * the ZLP here, but ignore the one-byte packet. +@@ -1149,7 +1197,10 @@ drop: + not_drop: + if (skb) + dev_kfree_skb_any (skb); +- usb_free_urb (urb); ++ if (urb) { ++ kfree(urb->sg); ++ usb_free_urb(urb); ++ } + } else + netif_dbg(dev, tx_queued, dev->net, + "> tx, len %d, type 0x%x\n", length, skb->protocol); +@@ -1162,7 +1213,7 @@ EXPORT_SYMBOL_GPL(usbnet_start_xmit); + + /*-------------------------------------------------------------------------*/ + +-// tasklet (work deferred from completions, in_irq) or timer ++ + + static void usbnet_bh (unsigned long param) + { +@@ -1174,11 +1225,14 @@ static void usbnet_bh (unsigned long param) + entry = (struct skb_data *) skb->cb; + switch (entry->state) { + case rx_done: ++ + entry->state = rx_cleanup; + rx_process (dev, skb); + continue; + case tx_done: ++ kfree(entry->urb->sg); + case rx_cleanup: ++ + usb_free_urb (entry->urb); + dev_kfree_skb (skb); + continue; +@@ -1187,7 +1241,9 @@ static void usbnet_bh (unsigned long param) + } + } + +- // waiting for all pending urbs to complete? ++ /* restart RX again after disabling due to high error rate */ ++ clear_bit(EVENT_RX_KILL, &dev->flags); ++ + if (dev->wait) { + if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { + wake_up (dev->wait); +@@ -1196,6 +1252,7 @@ static void usbnet_bh (unsigned long param) + // or are we maybe short a few urbs? + } else if (netif_running (dev->net) && + netif_device_present (dev->net) && ++ netif_carrier_ok(dev->net) && + !timer_pending (&dev->delay) && + !test_bit (EVENT_RX_HALT, &dev->flags)) { + int temp = dev->rxq.qlen; +@@ -1205,7 +1262,6 @@ static void usbnet_bh (unsigned long param) + struct urb *urb; + int i; + +- // don't refill the queue all at once + for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { + urb = usb_alloc_urb (0, GFP_ATOMIC); + if (urb != NULL) { +@@ -1218,12 +1274,17 @@ static void usbnet_bh (unsigned long param) + netif_dbg(dev, link, dev->net, + "rxqlen %d --> %d\n", + temp, dev->rxq.qlen); +- if (dev->rxq.qlen < qlen) ++ if (dev->rxq.qlen < qlen){ + tasklet_schedule (&dev->bh); ++ } ++ + } +- if (dev->txq.qlen < TX_QLEN (dev)) ++ if (dev->txq.qlen < TX_QLEN (dev)){ + netif_wake_queue (dev->net); ++ } ++ + } ++ + } + + +@@ -1237,35 +1298,34 @@ static void usbnet_bh (unsigned long param) + + void usbnet_disconnect (struct usb_interface *intf) + { +- struct usbnet *dev; +- struct usb_device *xdev; +- struct net_device *net; ++ struct usbnet *dev; ++ struct usb_device *xdev; ++ struct net_device *net; + + dev = usb_get_intfdata(intf); + usb_set_intfdata(intf, NULL); + if (!dev) + return; + +- xdev = interface_to_usbdev (intf); ++ xdev = interface_to_usbdev(intf); + + netif_info(dev, probe, dev->net, "unregister '%s' usb-%s-%s, %s\n", +- intf->dev.driver->name, +- xdev->bus->bus_name, xdev->devpath, +- dev->driver_info->description); ++ intf->dev.driver->name, xdev->bus->bus_name, ++ xdev->devpath, dev->driver_info->description); + + net = dev->net; +- unregister_netdev (net); ++ unregister_netdev(net); + + cancel_work_sync(&dev->kevent); + + if (dev->driver_info->unbind) +- dev->driver_info->unbind (dev, intf); ++ dev->driver_info->unbind(dev, intf); + + usb_kill_urb(dev->interrupt); + usb_free_urb(dev->interrupt); + + free_netdev(net); +- usb_put_dev (xdev); ++ usb_put_dev(xdev); + } + EXPORT_SYMBOL_GPL(usbnet_disconnect); + +@@ -1325,7 +1385,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + + status = -ENOMEM; + +- // set up our own records ++ + net = alloc_etherdev(sizeof(*dev)); + if (!net) { + dbg ("can't kmalloc dev"); +@@ -1374,16 +1434,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + net->watchdog_timeo = TX_TIMEOUT_JIFFIES; + net->ethtool_ops = &usbnet_ethtool_ops; + +- // allow device-specific bind/init procedures +- // NOTE net->name still not usable ... ++ + if (info->bind) { + status = info->bind (dev, udev); + if (status < 0) + goto out1; + +- // heuristic: "usb%d" for links we know are two-host, +- // else "eth%d" when there's reasonable doubt. userspace +- // can rename the link if it knows better. + if ((dev->driver_info->flags & FLAG_ETHER) != 0 && + ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 || + (net->dev_addr [0] & 0x02) == 0)) +@@ -1411,11 +1467,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + status = 0; + + } ++#if(1) + if (status >= 0 && dev->status) + status = init_status (dev, udev); + if (status < 0) + goto out3; +- ++#endif + if (!dev->rx_urb_size) + dev->rx_urb_size = dev->hard_mtu; + dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); +@@ -1435,7 +1492,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + dev->driver_info->description, + net->dev_addr); + +- // ok, it's ready to go. ++ + usb_set_intfdata (udev, dev); + + netif_device_attach (net); +@@ -1447,8 +1504,15 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) + + out3: + if (info->unbind) +- info->unbind (dev, udev); ++ info->unbind(dev, udev); + out1: ++ /* subdrivers must undo all they did in bind() if they ++ * fail it, but we may fail later and a deferred kevent ++ * may trigger an error resubmitting itself and, worse, ++ * schedule a timer. So we kill it all just in case. ++ */ ++ cancel_work_sync(&dev->kevent); ++ del_timer_sync(&dev->delay); + free_netdev(net); + out: + usb_put_dev(xdev); +@@ -1465,7 +1529,7 @@ EXPORT_SYMBOL_GPL(usbnet_probe); + + int usbnet_suspend (struct usb_interface *intf, pm_message_t message) + { +- struct usbnet *dev = usb_get_intfdata(intf); ++ struct usbnet *dev = usb_get_intfdata(intf); + + if (!dev->suspend_count++) { + spin_lock_irq(&dev->txq.lock); +@@ -1481,7 +1545,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) + * accelerate emptying of the rx and queues, to avoid + * having everything error out. + */ +- netif_device_detach (dev->net); ++ netif_device_detach(dev->net); + usbnet_terminate_urbs(dev); + usb_kill_urb(dev->interrupt); + +@@ -1489,7 +1553,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) + * reattach so runtime management can use and + * wake the device + */ +- netif_device_attach (dev->net); ++ netif_device_attach(dev->net); + } + return 0; + } +@@ -1497,10 +1561,10 @@ EXPORT_SYMBOL_GPL(usbnet_suspend); + + int usbnet_resume (struct usb_interface *intf) + { +- struct usbnet *dev = usb_get_intfdata(intf); +- struct sk_buff *skb; +- struct urb *res; +- int retval; ++ struct usbnet *dev = usb_get_intfdata(intf); ++ struct sk_buff *skb; ++ struct urb *res; ++ int retval; + + if (!--dev->suspend_count) { + /* resume interrupt URBs */ +@@ -1510,10 +1574,11 @@ int usbnet_resume (struct usb_interface *intf) + spin_lock_irq(&dev->txq.lock); + while ((res = usb_get_from_anchor(&dev->deferred))) { + +- skb = (struct sk_buff *)res->context; ++ skb = (struct sk_buff *) res->context; + retval = usb_submit_urb(res, GFP_ATOMIC); + if (retval < 0) { + dev_kfree_skb_any(skb); ++ kfree(res->sg); + usb_free_urb(res); + usb_autopm_put_interface_async(dev->intf); + } else { +@@ -1529,7 +1594,7 @@ int usbnet_resume (struct usb_interface *intf) + if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { + if (!(dev->txq.qlen >= TX_QLEN(dev))) + netif_start_queue(dev->net); +- tasklet_schedule (&dev->bh); ++ tasklet_schedule(&dev->bh); + } + } + return 0; +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +old mode 100644 +new mode 100755 +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +old mode 100644 +new mode 100755 +diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig +new file mode 100644 +index 00000000..8381f7c0 +--- /dev/null ++++ b/drivers/pwm/Kconfig +@@ -0,0 +1,83 @@ ++menuconfig PWM ++ bool "Pulse-Width Modulation (PWM) Support" ++ help ++ Generic Pulse-Width Modulation (PWM) support. ++ ++ In Pulse-Width Modulation, a variation of the width of pulses ++ in a rectangular pulse signal is used as a means to alter the ++ average power of the signal. Applications include efficient ++ power delivery and voltage regulation. In computer systems, ++ PWMs are commonly used to control fans or the brightness of ++ display backlights. ++ ++ This framework provides a generic interface to PWM devices ++ within the Linux kernel. On the driver side it provides an API ++ to register and unregister a PWM chip, an abstraction of a PWM ++ controller, that supports one or more PWM devices. Client ++ drivers can request PWM devices and use the generic framework ++ to configure as well as enable and disable them. ++ ++ This generic framework replaces the legacy PWM framework which ++ allows only a single driver implementing the required API. Not ++ all legacy implementations have been ported to the framework ++ yet. The framework provides an API that is backward compatible ++ with the legacy framework so that existing client drivers ++ continue to work as expected. ++ ++ If unsure, say no. ++ ++if PWM ++ ++config PWM_FULLHAN ++ tristate "FH PWM support" ++ help ++ To compile this driver as a module, choose M here: the module will ++ be called fh_pwm. ++ ++if PWM_FULLHAN ++if ARCH_FH8626V100 ++config FH_PWM_NUM ++ int ++ prompt "Number of PWMs, range: 1~14" ++ default 2 ++ range 1 14 ++ help ++ Number of PWMs ++ ++config PWM_FULLHAN_V21 ++ bool ++ default y ++ ++endif ++ ++if ARCH_FH8856 ++config FH_PWM_NUM ++ int ++ prompt "Number of PWMs, range: 1~8" ++ default 2 ++ range 1 8 ++ help ++ Number of PWMs ++ ++config PWM_FULLHAN_V20 ++ bool ++ default y ++endif ++ ++if ARCH_FH8830 ++config FH_PWM_NUM ++ int ++ prompt "Number of PWMs, range: 1~8" ++ default 2 ++ range 1 8 ++ help ++ Number of PWMs ++ ++config PWM_FULLHAN_V20 ++ bool ++ default y ++endif ++ ++endif ++ ++endif +diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile +new file mode 100644 +index 00000000..64d42f52 +--- /dev/null ++++ b/drivers/pwm/Makefile +@@ -0,0 +1,20 @@ ++obj-$(CONFIG_PWM) += core.o ++obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o ++obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o ++obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o ++obj-$(CONFIG_PWM_IMX) += pwm-imx.o ++obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o ++obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o ++obj-$(CONFIG_PWM_MXS) += pwm-mxs.o ++obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o ++obj-$(CONFIG_PWM_PXA) += pwm-pxa.o ++obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o ++obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o ++obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o ++obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o ++obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o ++obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o ++obj-$(CONFIG_PWM_TWL) += pwm-twl.o ++obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o ++obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o ++obj-$(CONFIG_PWM_FULLHAN) += pwmv2-fullhan.o +diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c +new file mode 100644 +index 00000000..01e8aba6 +--- /dev/null ++++ b/drivers/pwm/core.c +@@ -0,0 +1,642 @@ ++/* ++ * Generic pwmlib implementation ++ * ++ * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de> ++ * Copyright (C) 2011-2012 Avionic Design GmbH ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; see the file COPYING. If not, write to ++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include <linux/module.h> ++#include <linux/pwm.h> ++#include <linux/radix-tree.h> ++#include <linux/list.h> ++#include <linux/mutex.h> ++#include <linux/err.h> ++#include <linux/slab.h> ++#include <linux/device.h> ++#include <linux/debugfs.h> ++#include <linux/seq_file.h> ++ ++#define MAX_PWMS 1024 ++ ++/* flags in the third cell of the DT PWM specifier */ ++#define PWM_SPEC_POLARITY (1 << 0) ++ ++static DEFINE_MUTEX(pwm_lookup_lock); ++static LIST_HEAD(pwm_lookup_list); ++static DEFINE_MUTEX(pwm_lock); ++static LIST_HEAD(pwm_chips); ++static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); ++static RADIX_TREE(pwm_tree, GFP_KERNEL); ++ ++static struct pwm_device *pwm_to_device(unsigned int pwm) ++{ ++ return radix_tree_lookup(&pwm_tree, pwm); ++} ++ ++static int alloc_pwms(int pwm, unsigned int count) ++{ ++ unsigned int from = 0; ++ unsigned int start; ++ ++ if (pwm >= MAX_PWMS) ++ return -EINVAL; ++ ++ if (pwm >= 0) ++ from = pwm; ++ ++ start = bitmap_find_next_zero_area(allocated_pwms, MAX_PWMS, from, ++ count, 0); ++ ++ if (pwm >= 0 && start != pwm) ++ return -EEXIST; ++ ++ if (start + count > MAX_PWMS) ++ return -ENOSPC; ++ ++ return start; ++} ++ ++static void free_pwms(struct pwm_chip *chip) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < chip->npwm; i++) { ++ struct pwm_device *pwm = &chip->pwms[i]; ++ radix_tree_delete(&pwm_tree, pwm->pwm); ++ } ++ ++ bitmap_clear(allocated_pwms, chip->base, chip->npwm); ++ ++ kfree(chip->pwms); ++ chip->pwms = NULL; ++} ++ ++static struct pwm_chip *pwmchip_find_by_name(const char *name) ++{ ++ struct pwm_chip *chip; ++ ++ if (!name) ++ return NULL; ++ ++ mutex_lock(&pwm_lock); ++ ++ list_for_each_entry(chip, &pwm_chips, list) { ++ const char *chip_name = dev_name(chip->dev); ++ ++ if (chip_name && strcmp(chip_name, name) == 0) { ++ mutex_unlock(&pwm_lock); ++ return chip; ++ } ++ } ++ ++ mutex_unlock(&pwm_lock); ++ ++ return NULL; ++} ++ ++static int pwm_device_request(struct pwm_device *pwm, const char *label) ++{ ++ int err; ++ ++ if (test_bit(PWMF_REQUESTED, &pwm->flags)) ++ return -EBUSY; ++ ++ if (!try_module_get(pwm->chip->ops->owner)) ++ return -ENODEV; ++ ++ if (pwm->chip->ops->request) { ++ err = pwm->chip->ops->request(pwm->chip, pwm); ++ if (err) { ++ module_put(pwm->chip->ops->owner); ++ return err; ++ } ++ } ++ ++ set_bit(PWMF_REQUESTED, &pwm->flags); ++ pwm->label = label; ++ ++ return 0; ++} ++ ++/** ++ * pwm_set_chip_data() - set private chip data for a PWM ++ * @pwm: PWM device ++ * @data: pointer to chip-specific data ++ */ ++int pwm_set_chip_data(struct pwm_device *pwm, void *data) ++{ ++ if (!pwm) ++ return -EINVAL; ++ ++ pwm->chip_data = data; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pwm_set_chip_data); ++ ++/** ++ * pwm_get_chip_data() - get private chip data for a PWM ++ * @pwm: PWM device ++ */ ++void *pwm_get_chip_data(struct pwm_device *pwm) ++{ ++ return pwm ? pwm->chip_data : NULL; ++} ++EXPORT_SYMBOL_GPL(pwm_get_chip_data); ++ ++/** ++ * pwmchip_add() - register a new PWM chip ++ * @chip: the PWM chip to add ++ * ++ * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base ++ * will be used. ++ */ ++int pwmchip_add(struct pwm_chip *chip) ++{ ++ struct pwm_device *pwm; ++ unsigned int i; ++ int ret; ++ ++ if (!chip || !chip->dev || !chip->ops || !chip->ops->config || ++ !chip->ops->enable || !chip->ops->disable) ++ return -EINVAL; ++ ++ mutex_lock(&pwm_lock); ++ ++ ret = alloc_pwms(chip->base, chip->npwm); ++ if (ret < 0) ++ goto out; ++ ++ chip->pwms = kzalloc(chip->npwm * sizeof(*pwm), GFP_KERNEL); ++ if (!chip->pwms) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ chip->base = ret; ++ ++ for (i = 0; i < chip->npwm; i++) { ++ pwm = &chip->pwms[i]; ++ ++ pwm->chip = chip; ++ pwm->pwm = chip->base + i; ++ pwm->hwpwm = i; ++ ++ radix_tree_insert(&pwm_tree, pwm->pwm, pwm); ++ } ++ ++ bitmap_set(allocated_pwms, chip->base, chip->npwm); ++ ++ INIT_LIST_HEAD(&chip->list); ++ list_add(&chip->list, &pwm_chips); ++ ++ ret = 0; ++out: ++ mutex_unlock(&pwm_lock); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwmchip_add); ++ ++/** ++ * pwmchip_remove() - remove a PWM chip ++ * @chip: the PWM chip to remove ++ * ++ * Removes a PWM chip. This function may return busy if the PWM chip provides ++ * a PWM device that is still requested. ++ */ ++int pwmchip_remove(struct pwm_chip *chip) ++{ ++ unsigned int i; ++ int ret = 0; ++ ++ mutex_lock(&pwm_lock); ++ ++ for (i = 0; i < chip->npwm; i++) { ++ struct pwm_device *pwm = &chip->pwms[i]; ++ ++ if (test_bit(PWMF_REQUESTED, &pwm->flags)) { ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ ++ list_del_init(&chip->list); ++ ++ free_pwms(chip); ++ ++out: ++ mutex_unlock(&pwm_lock); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(pwmchip_remove); ++ ++/** ++ * pwm_request() - request a PWM device ++ * @pwm_id: global PWM device index ++ * @label: PWM device label ++ * ++ * This function is deprecated, use pwm_get() instead. ++ */ ++struct pwm_device *pwm_request(int pwm, const char *label) ++{ ++ struct pwm_device *dev; ++ int err; ++ ++ if (pwm < 0 || pwm >= MAX_PWMS) ++ return ERR_PTR(-EINVAL); ++ ++ mutex_lock(&pwm_lock); ++ ++ dev = pwm_to_device(pwm); ++ if (!dev) { ++ dev = ERR_PTR(-ENODEV); ++ goto out; ++ } ++ ++ err = pwm_device_request(dev, label); ++ if (err < 0) ++ dev = ERR_PTR(err); ++ ++out: ++ mutex_unlock(&pwm_lock); ++ ++ return dev; ++} ++EXPORT_SYMBOL_GPL(pwm_request); ++ ++/** ++ * pwm_request_from_chip() - request a PWM device relative to a PWM chip ++ * @chip: PWM chip ++ * @index: per-chip index of the PWM to request ++ * @label: a literal description string of this PWM ++ * ++ * Returns the PWM at the given index of the given PWM chip. A negative error ++ * code is returned if the index is not valid for the specified PWM chip or ++ * if the PWM device cannot be requested. ++ */ ++struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, ++ unsigned int index, ++ const char *label) ++{ ++ struct pwm_device *pwm; ++ int err; ++ ++ if (!chip || index >= chip->npwm) ++ return ERR_PTR(-EINVAL); ++ ++ mutex_lock(&pwm_lock); ++ pwm = &chip->pwms[index]; ++ ++ err = pwm_device_request(pwm, label); ++ if (err < 0) ++ pwm = ERR_PTR(err); ++ ++ mutex_unlock(&pwm_lock); ++ return pwm; ++} ++EXPORT_SYMBOL_GPL(pwm_request_from_chip); ++ ++/** ++ * pwm_free() - free a PWM device ++ * @pwm: PWM device ++ * ++ * This function is deprecated, use pwm_put() instead. ++ */ ++void pwm_free(struct pwm_device *pwm) ++{ ++ pwm_put(pwm); ++} ++EXPORT_SYMBOL_GPL(pwm_free); ++ ++/** ++ * pwm_config() - change a PWM device configuration ++ * @pwm: PWM device ++ * @duty_ns: "on" time (in nanoseconds) ++ * @period_ns: duration (in nanoseconds) of one cycle ++ */ ++int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) ++{ ++ if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns) ++ return -EINVAL; ++ ++ return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); ++} ++EXPORT_SYMBOL_GPL(pwm_config); ++ ++/** ++ * pwm_set_polarity() - configure the polarity of a PWM signal ++ * @pwm: PWM device ++ * @polarity: new polarity of the PWM signal ++ * ++ * Note that the polarity cannot be configured while the PWM device is enabled ++ */ ++int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) ++{ ++ if (!pwm || !pwm->chip->ops) ++ return -EINVAL; ++ ++ if (!pwm->chip->ops->set_polarity) ++ return -ENOSYS; ++ ++ if (test_bit(PWMF_ENABLED, &pwm->flags)) ++ return -EBUSY; ++ ++ return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); ++} ++EXPORT_SYMBOL_GPL(pwm_set_polarity); ++ ++/** ++ * pwm_enable() - start a PWM output toggling ++ * @pwm: PWM device ++ */ ++int pwm_enable(struct pwm_device *pwm) ++{ ++ if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags)) ++ return pwm->chip->ops->enable(pwm->chip, pwm); ++ ++ return pwm ? 0 : -EINVAL; ++} ++EXPORT_SYMBOL_GPL(pwm_enable); ++ ++/** ++ * pwm_disable() - stop a PWM output toggling ++ * @pwm: PWM device ++ */ ++void pwm_disable(struct pwm_device *pwm) ++{ ++ if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags)) ++ pwm->chip->ops->disable(pwm->chip, pwm); ++} ++EXPORT_SYMBOL_GPL(pwm_disable); ++ ++/** ++ * pwm_add_table() - register PWM device consumers ++ * @table: array of consumers to register ++ * @num: number of consumers in table ++ */ ++void __init pwm_add_table(struct pwm_lookup *table, size_t num) ++{ ++ mutex_lock(&pwm_lookup_lock); ++ ++ while (num--) { ++ list_add_tail(&table->list, &pwm_lookup_list); ++ table++; ++ } ++ ++ mutex_unlock(&pwm_lookup_lock); ++} ++ ++/** ++ * pwm_get() - look up and request a PWM device ++ * @dev: device for PWM consumer ++ * @con_id: consumer name ++ * ++ * Lookup is first attempted using DT. If the device was not instantiated from ++ * a device tree, a PWM chip and a relative index is looked up via a table ++ * supplied by board setup code (see pwm_add_table()). ++ * ++ * Once a PWM chip has been found the specified PWM device will be requested ++ * and is ready to be used. ++ */ ++struct pwm_device *pwm_get(struct device *dev, const char *con_id) ++{ ++ struct pwm_device *pwm = ERR_PTR(-ENODEV); ++ const char *dev_id = dev ? dev_name(dev) : NULL; ++ struct pwm_chip *chip = NULL; ++ unsigned int index = 0; ++ unsigned int best = 0; ++ struct pwm_lookup *p; ++ unsigned int match; ++ ++ /* ++ * We look up the provider in the static table typically provided by ++ * board setup code. We first try to lookup the consumer device by ++ * name. If the consumer device was passed in as NULL or if no match ++ * was found, we try to find the consumer by directly looking it up ++ * by name. ++ * ++ * If a match is found, the provider PWM chip is looked up by name ++ * and a PWM device is requested using the PWM device per-chip index. ++ * ++ * The lookup algorithm was shamelessly taken from the clock ++ * framework: ++ * ++ * We do slightly fuzzy matching here: ++ * An entry with a NULL ID is assumed to be a wildcard. ++ * If an entry has a device ID, it must match ++ * If an entry has a connection ID, it must match ++ * Then we take the most specific entry - with the following order ++ * of precedence: dev+con > dev only > con only. ++ */ ++ mutex_lock(&pwm_lookup_lock); ++ ++ list_for_each_entry(p, &pwm_lookup_list, list) { ++ match = 0; ++ ++ if (p->dev_id) { ++ if (!dev_id || strcmp(p->dev_id, dev_id)) ++ continue; ++ ++ match += 2; ++ } ++ ++ if (p->con_id) { ++ if (!con_id || strcmp(p->con_id, con_id)) ++ continue; ++ ++ match += 1; ++ } ++ ++ if (match > best) { ++ chip = pwmchip_find_by_name(p->provider); ++ index = p->index; ++ ++ if (match != 3) ++ best = match; ++ else ++ break; ++ } ++ } ++ ++ if (chip) ++ pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id); ++ ++ mutex_unlock(&pwm_lookup_lock); ++ ++ return pwm; ++} ++EXPORT_SYMBOL_GPL(pwm_get); ++ ++/** ++ * pwm_put() - release a PWM device ++ * @pwm: PWM device ++ */ ++void pwm_put(struct pwm_device *pwm) ++{ ++ if (!pwm) ++ return; ++ ++ mutex_lock(&pwm_lock); ++ ++ if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { ++ pr_warn("PWM device already freed\n"); ++ goto out; ++ } ++ ++ if (pwm->chip->ops->free) ++ pwm->chip->ops->free(pwm->chip, pwm); ++ ++ pwm->label = NULL; ++ ++ module_put(pwm->chip->ops->owner); ++out: ++ mutex_unlock(&pwm_lock); ++} ++EXPORT_SYMBOL_GPL(pwm_put); ++ ++static void devm_pwm_release(struct device *dev, void *res) ++{ ++ pwm_put(*(struct pwm_device **)res); ++} ++ ++/** ++ * devm_pwm_get() - resource managed pwm_get() ++ * @dev: device for PWM consumer ++ * @con_id: consumer name ++ * ++ * This function performs like pwm_get() but the acquired PWM device will ++ * automatically be released on driver detach. ++ */ ++struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) ++{ ++ struct pwm_device **ptr, *pwm; ++ ++ ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ pwm = pwm_get(dev, con_id); ++ if (!IS_ERR(pwm)) { ++ *ptr = pwm; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return pwm; ++} ++EXPORT_SYMBOL_GPL(devm_pwm_get); ++ ++/** ++ * pwm_can_sleep() - report whether PWM access will sleep ++ * @pwm: PWM device ++ * ++ * It returns true if accessing the PWM can sleep, false otherwise. ++ */ ++bool pwm_can_sleep(struct pwm_device *pwm) ++{ ++ return pwm->chip->can_sleep; ++} ++EXPORT_SYMBOL_GPL(pwm_can_sleep); ++ ++#ifdef CONFIG_DEBUG_FS ++static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < chip->npwm; i++) { ++ struct pwm_device *pwm = &chip->pwms[i]; ++ ++ seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); ++ ++ if (test_bit(PWMF_REQUESTED, &pwm->flags)) ++ seq_printf(s, " requested"); ++ ++ if (test_bit(PWMF_ENABLED, &pwm->flags)) ++ seq_printf(s, " enabled"); ++ ++ seq_printf(s, "\n"); ++ } ++} ++ ++static void *pwm_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ mutex_lock(&pwm_lock); ++ s->private = ""; ++ ++ return seq_list_start(&pwm_chips, *pos); ++} ++ ++static void *pwm_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ s->private = "\n"; ++ ++ return seq_list_next(v, &pwm_chips, pos); ++} ++ ++static void pwm_seq_stop(struct seq_file *s, void *v) ++{ ++ mutex_unlock(&pwm_lock); ++} ++ ++static int pwm_seq_show(struct seq_file *s, void *v) ++{ ++ struct pwm_chip *chip = list_entry(v, struct pwm_chip, list); ++ ++ seq_printf(s, "%s%s/%s, %d PWM device%s\n", (char *)s->private, ++ chip->dev->bus ? chip->dev->bus->name : "no-bus", ++ dev_name(chip->dev), chip->npwm, ++ (chip->npwm != 1) ? "s" : ""); ++ ++ if (chip->ops->dbg_show) ++ chip->ops->dbg_show(chip, s); ++ else ++ pwm_dbg_show(chip, s); ++ ++ return 0; ++} ++ ++static const struct seq_operations pwm_seq_ops = { ++ .start = pwm_seq_start, ++ .next = pwm_seq_next, ++ .stop = pwm_seq_stop, ++ .show = pwm_seq_show, ++}; ++ ++static int pwm_seq_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &pwm_seq_ops); ++} ++ ++static const struct file_operations pwm_debugfs_ops = { ++ .owner = THIS_MODULE, ++ .open = pwm_seq_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++ ++static int __init pwm_debugfs_init(void) ++{ ++ debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, ++ &pwm_debugfs_ops); ++ ++ return 0; ++} ++ ++subsys_initcall(pwm_debugfs_init); ++#endif /* CONFIG_DEBUG_FS */ +diff --git a/drivers/pwm/pwm-fullhan.c b/drivers/pwm/pwm-fullhan.c +new file mode 100644 +index 00000000..b1f3c618 +--- /dev/null ++++ b/drivers/pwm/pwm-fullhan.c +@@ -0,0 +1,607 @@ ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/pwm.h> ++#include <linux/printk.h> ++#include <linux/fs.h> ++#include <linux/miscdevice.h> ++#include <linux/decompress/mm.h> ++#include <linux/of_address.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++ ++#include <asm/uaccess.h> ++#include "pwm-fullhan.h" ++ ++#undef FH_PWM_DEBUG ++#ifdef FH_PWM_DEBUG ++#define PRINT_DBG(fmt,args...) printk(fmt,##args) ++#else ++#define PRINT_DBG(fmt,args...) do{} while(0) ++#endif ++ ++struct fh_pwm_chip { ++ struct pwm_chip chip; ++ void __iomem *base; ++ struct clk *clk; ++ struct proc_dir_entry *proc_file; ++}; ++ ++struct fh_pwm_chip fh_pwm = { ++ ++}; ++ ++ ++static int pwm_get_duty_cycle_ns(struct fh_pwm_chip_data *chip_data) ++{ ++ u32 reg, period, duty; ++ u32 clk_rate = clk_get_rate(fh_pwm.clk); ++ ++ reg = readl(fh_pwm.base + REG_PWM_CMD(chip_data->id)); ++ period = reg & 0x0fff; ++ duty = (reg >> 16) & 0xfff; ++ duty = period - duty; //reverse duty cycle ++ ++ if (period == 0) ++ period = duty; ++ ++ chip_data->counter_ns = duty * 1000000000 / clk_rate; ++ chip_data->period_ns = period * 1000000000 / clk_rate; ++ ++ PRINT_DBG("get duty: %d, period: %d, reg: 0x%x\n", duty, period, reg); ++ ++ return 0; ++} ++ ++static int pwm_set_duty_cycle_ns(struct fh_pwm_chip_data *chip_data) ++{ ++ u32 period, duty, reg, clk_rate, duty_revert; ++ clk_rate = clk_get_rate(fh_pwm.clk); ++ if (!clk_rate) { ++ pr_err("PWM: clock rate is 0\n"); ++ return -EINVAL; ++ } ++ period = chip_data->period_ns / (1000000000 / clk_rate); ++ ++ if (period < 8) { ++ pr_err("PWM: min period is 8\n"); ++ return -EINVAL; ++ } ++ ++ duty = chip_data->counter_ns / (1000000000 / clk_rate); ++ ++ if (period < duty) { ++ pr_err("PWM: period < duty\n"); ++ return -EINVAL; ++ } ++ ++ duty_revert = period - duty; ++ ++ if (duty == period) ++ reg = (duty & 0xfff) << 16 | (0 & 0xfff); ++ else ++ reg = (duty_revert & 0xfff) << 16 | (period & 0xfff); ++ ++ PRINT_DBG("set duty_revert: %d, period: %d, reg: 0x%x\n", duty_revert, period, reg); ++ ++ writel(reg, fh_pwm.base + REG_PWM_CMD(chip_data->id)); ++ return 0; ++} ++ ++ ++static int pwm_set_duty_cycle_percent(struct fh_pwm_chip_data *chip_data) ++{ ++ u32 period, duty, reg, clk_rate, duty_revert; ++ clk_rate = clk_get_rate(fh_pwm.clk); ++ if (!clk_rate) { ++ pr_err("PWM: clock rate is 0\n"); ++ return -EINVAL; ++ } ++ ++ if (chip_data->percent > 100 || chip_data->percent < 0) { ++ pr_err("PWM: pwm->percent is out of range\n"); ++ return -EINVAL; ++ } ++ ++ period = chip_data->period_ns / (1000000000 / clk_rate); ++ ++ if (period < 8) { ++ pr_err("PWM: min period is 8\n"); ++ return -EINVAL; ++ } ++ ++ duty = period * 100 / chip_data->percent; ++ ++ if (period < duty) { ++ pr_err("PWM: period < duty\n"); ++ return -EINVAL; ++ } ++ ++ duty_revert = period - duty; ++ ++ if (duty == period) ++ reg = (duty & 0xfff) << 16 | (0 & 0xfff); ++ else ++ reg = (duty_revert & 0xfff) << 16 | (period & 0xfff); ++ ++ PRINT_DBG("set duty_revert: %d, period: %d, reg: 0x%x\n", duty_revert, period, reg); ++ ++ writel(reg, fh_pwm.base + REG_PWM_CMD(chip_data->id)); ++ return 0; ++} ++ ++ ++int fh_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = pwm_get_chip_data(pwm); ++ if (!chip_data) { ++ pr_err("%s: ERROR: PWM %d does NOT exist\n", ++ __func__, pwm->hwpwm); ++ return -ENXIO; ++ } ++ chip_data->counter_ns = duty_ns; ++ chip_data->period_ns = period_ns; ++ pwm_set_duty_cycle_ns(chip_data); ++ return 0; ++} ++ ++static int _fh_pwm_enable(struct fh_pwm_chip_data *chip_data) ++{ ++ int i; ++ unsigned int reg = 0; ++ chip_data->working = 1; ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ chip_data = pwm_get_chip_data(&fh_pwm.chip.pwms[i]); ++ reg |= chip_data->working << i; ++ } ++ ++ writel(reg, fh_pwm.base + REG_PWM_CTRL); ++ return 0; ++} ++ ++int fh_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = pwm_get_chip_data(pwm); ++ if (!chip_data) { ++ pr_err("%s: ERROR: PWM %d does NOT exist\n", ++ __func__, pwm->hwpwm); ++ return -ENXIO; ++ } ++ ++ _fh_pwm_enable(chip_data); ++ ++ return 0; ++} ++ ++static int _fh_pwm_disable(struct fh_pwm_chip_data *chip_data) ++{ ++ int i; ++ unsigned int reg = 0; ++ chip_data->working = 0; ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ chip_data = pwm_get_chip_data(&fh_pwm.chip.pwms[i]); ++ reg |= chip_data->working << i; ++ } ++ ++ writel(reg, fh_pwm.base + REG_PWM_CTRL); ++ return 0; ++} ++ ++void fh_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = pwm_get_chip_data(pwm); ++ if (!chip_data) { ++ pr_err("%s: ERROR: PWM %d does NOT exist\n", ++ __func__, pwm->hwpwm); ++ return; ++ } ++ ++ _fh_pwm_disable(chip_data); ++} ++ ++static int fh_pwm_open(struct inode *inode, struct file *file) ++{ ++ int i; ++ struct fh_pwm_chip_data *chip_data; ++ struct pwm_device *pwm; ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ pwm = &fh_pwm.chip.pwms[i]; ++ ++ if (!pwm) { ++ pr_err("%s: ERROR: PWM %d does NOT exist\n", ++ __func__, i); ++ return -ENXIO; ++ } ++ chip_data = pwm_get_chip_data(pwm); ++ if (!chip_data) ++ chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); ++ ++ chip_data->id = pwm->hwpwm; ++ chip_data->working = 0; ++ pwm->chip_data = chip_data; ++ } ++ return 0; ++} ++ ++static int fh_pwm_release(struct inode *inode, struct file *filp) ++{ ++ int i; ++ struct fh_pwm_chip_data *chip_data; ++ struct pwm_device *pwm; ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ pwm = &fh_pwm.chip.pwms[i]; ++ ++ if (!pwm) { ++ pr_err("%s: ERROR: PWM %d does NOT exist\n", ++ __func__, i); ++ return -ENOTTY; ++ } ++ chip_data = pwm_get_chip_data(pwm); ++ free(chip_data); ++ pwm_set_chip_data(pwm, NULL); ++ } ++ return 0; ++} ++ ++ ++static long fh_pwm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct fh_pwm_chip_data *pwm; ++ ++ if (unlikely(_IOC_TYPE(cmd) != PWM_IOCTL_MAGIC)) { ++ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n", ++ __func__, _IOC_TYPE(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (unlikely(_IOC_NR(cmd) > PWM_IOCTL_MAXNR)) { ++ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++ ++ if (ret) { ++ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -EACCES); ++ return -EACCES; ++ } ++ ++ switch (cmd) { ++ case ENABLE_PWM: ++ pwm = (struct fh_pwm_chip_data __user *)arg; ++ _fh_pwm_enable(pwm); ++ break; ++ case DISABLE_PWM: ++ pwm = (struct fh_pwm_chip_data __user *)arg; ++ _fh_pwm_disable(pwm); ++ break; ++ case SET_PWM_DUTY_CYCLE: ++ pwm = (struct fh_pwm_chip_data __user *)arg; ++ printk("ioctl: pwm addr: %p, pwm->period: %d ns\n", pwm, pwm->period_ns); ++ pwm_set_duty_cycle_ns(pwm); ++ break; ++ case GET_PWM_DUTY_CYCLE: ++ pwm = (struct fh_pwm_chip_data __user *)arg; ++ printk("ioctl: pwm->id: %d, pwm->counter: %d, pwm->period: %d\n", pwm->id, pwm->counter_ns, ++ pwm->period_ns); ++ pwm_get_duty_cycle_ns(pwm); ++ break; ++ case SET_PWM_DUTY_CYCLE_PERCENT: ++ pwm = (struct fh_pwm_chip_data __user *)arg; ++ printk("ioctl: pwm->id: %d, pwm->counter: %d, pwm->period: %d\n", pwm->id, pwm->counter_ns, ++ pwm->period_ns); ++ pwm_set_duty_cycle_percent(pwm); ++ break; ++ } ++ ++ ++ return ret; ++} ++ ++static const struct file_operations fh_pwm_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_pwm_open, ++ .release = fh_pwm_release, ++ .unlocked_ioctl = fh_pwm_ioctl, ++}; ++ ++static struct miscdevice fh_pwm_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEVICE_NAME, ++ .fops = &fh_pwm_fops, ++}; ++ ++static const struct pwm_ops fh_pwm_ops = { ++ .config = fh_pwm_config, ++ .enable = fh_pwm_enable, ++ .disable = fh_pwm_disable, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static void del_char(char *str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) ++ *p++ = *q; ++ q++; ++ } ++ *p = '\0'; ++} ++ ++static ssize_t fh_pwm_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off) ++{ ++ int i; ++ char message[32] = {0}; ++ char *const delim = ","; ++ char *cur = message; ++ char *param_str[4]; ++ unsigned int param[4]; ++ struct fh_pwm_chip_data *chip_data; ++ ++ len = (len > 32) ? 32 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ for (i = 0; i < 4; i++) { ++ param_str[i] = strsep(&cur, delim); ++ if (!param_str[i]) { ++ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i); ++ return -EINVAL; ++ } else { ++ del_char(param_str[i], ' '); ++ del_char(param_str[i], '\n'); ++ param[i] = (u32)simple_strtoul(param_str[i], NULL, 10); ++ if (param[i] < 0) { ++ pr_err("%s: ERROR: parameter[%d] is incorrect\n", __func__, i); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ printk("set pwm %d to %s, duty cycle: %u ns, period cycle: %u\n", param[0], ++ param[1] ? "enable" : "disable", param[2], param[3]); ++ chip_data = pwm_get_chip_data(&fh_pwm.chip.pwms[param[0]]); ++ chip_data->counter_ns = param[2]; ++ chip_data->period_ns = param[3]; ++ ++ param[1] ? fh_pwm_enable(&fh_pwm.chip, &fh_pwm.chip.pwms[param[0]]) : fh_pwm_disable(&fh_pwm.chip, ++ &fh_pwm.chip.pwms[param[0]]); ++ pwm_set_duty_cycle_ns(chip_data); ++ ++ return len; ++} ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter = 0; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ int i; ++ seq_printf(sfile, "\nPWM Status:\n"); ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = pwm_get_chip_data(&fh_pwm.chip.pwms[i]); ++ seq_printf(sfile, "id: %d \t%s, duty_ns: %u, period_ns: %u\n", ++ chip_data->id, ++ (chip_data->working) ? "ENABLE" : "DISABLE", ++ chip_data->counter_ns, ++ chip_data->period_ns); ++ } ++ return 0; ++} ++ ++static const struct seq_operations isp_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_pwm_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &isp_seq_ops); ++} ++ ++ ++static struct file_operations fh_pwm_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_pwm_proc_open, ++ .read = seq_read, ++ .write = fh_pwm_proc_write, ++ .release = seq_release, ++}; ++ ++static int __devinit fh_pwm_probe(struct platform_device *pdev) ++{ ++ int err, i; ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ err = -ENXIO; ++ goto fail_no_mem_resource; ++ } ++ ++ res = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (res == NULL) { ++ err = -EBUSY; ++ goto fail_no_mem_resource; ++ } ++ ++ fh_pwm.base = ioremap(res->start, resource_size(res)); ++ if (fh_pwm.base == NULL) { ++ err = -ENXIO; ++ goto fail_no_ioremap; ++ } ++ ++ fh_pwm.clk = clk_get(&pdev->dev, "pwm_clk"); ++ ++ if (IS_ERR(fh_pwm.clk)) { ++ err = PTR_ERR(fh_pwm.clk); ++ goto fail_no_clk; ++ } ++ ++ clk_enable(fh_pwm.clk); ++ ++ err = misc_register(&fh_pwm_misc); ++ if (err < 0) { ++ pr_err("%s: ERROR: %s registration failed", ++ __func__, DEVICE_NAME); ++ return -ENXIO; ++ } ++ ++ fh_pwm.chip.dev = &pdev->dev; ++ fh_pwm.chip.ops = &fh_pwm_ops; ++ fh_pwm.chip.base = pdev->id; ++ fh_pwm.chip.npwm = CONFIG_FH_PWM_NUM; ++ ++ err = pwmchip_add(&fh_pwm.chip); ++ if (err < 0) { ++ pr_err("%s: ERROR: %s pwmchip_add failed", ++ __func__, DEVICE_NAME); ++ return err; ++ } ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) { ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL); ++ if (chip_data == NULL) { ++ pr_err("pwm[%d], chip data malloced failed\n", i); ++ continue; ++ } ++ ++ chip_data->id = i; ++ chip_data->working = 0; ++ ++ pwm_set_chip_data(&fh_pwm.chip.pwms[i], chip_data); ++ } ++ ++ platform_set_drvdata(pdev, &fh_pwm); ++ ++ /* disable pwm at startup. Avoids zero value. */ ++ writel(0x0, fh_pwm.base + REG_PWM_CTRL); ++ ++ pr_info("PWM driver, Number: %d, IO base addr: 0x%p\n", ++ fh_pwm.chip.npwm, fh_pwm.base); ++ ++ fh_pwm.proc_file = create_proc_entry(FH_PWM_PROC_FILE, 0644, NULL); ++ ++ if (fh_pwm.proc_file) ++ fh_pwm.proc_file->proc_fops = &fh_pwm_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, DEVICE_NAME); ++ ++ dev_dbg(&pdev->dev, "PWM probe successful, IO base addr: %p\n", ++ fh_pwm.base); ++ return 0; ++ ++fail_no_clk: ++ iounmap(fh_pwm.base); ++fail_no_ioremap: ++ release_mem_region(res->start, resource_size(res)); ++fail_no_mem_resource: ++ return err; ++} ++ ++static int __exit fh_pwm_remove(struct platform_device *pdev) ++{ ++ int err, i; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ for (i = 0; i < fh_pwm.chip.npwm; i++) ++ kfree(fh_pwm.chip.pwms[i].chip_data); ++ ++ err = pwmchip_remove(&fh_pwm.chip); ++ if (err < 0) ++ return err; ++ ++ dev_dbg(&pdev->dev, "pwm driver removed\n"); ++ ++ writel(0x0, fh_pwm.base + REG_PWM_CTRL); ++ clk_disable(fh_pwm.clk); ++ ++ iounmap(fh_pwm.base); ++ release_mem_region(res->start, resource_size(res)); ++ platform_set_drvdata(pdev, NULL); ++ misc_deregister(&fh_pwm_misc); ++ return 0; ++} ++ ++static struct platform_driver fh_pwm_driver = { ++ .driver = ++ { ++ .name = DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_pwm_probe, ++ .remove = __exit_p(fh_pwm_remove), ++}; ++ ++static int __init fh_pwm_init(void) ++{ ++ return platform_driver_register(&fh_pwm_driver); ++} ++ ++static void __exit fh_pwm_exit(void) ++{ ++ ++ platform_driver_unregister(&fh_pwm_driver); ++ ++} ++ ++module_init(fh_pwm_init); ++module_exit(fh_pwm_exit); ++ ++ ++MODULE_AUTHOR("fullhan"); ++ ++MODULE_DESCRIPTION("FH PWM driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR); +diff --git a/drivers/pwm/pwm-fullhan.h b/drivers/pwm/pwm-fullhan.h +new file mode 100644 +index 00000000..cb81ac09 +--- /dev/null ++++ b/drivers/pwm/pwm-fullhan.h +@@ -0,0 +1,31 @@ ++#ifndef FH_PMU_H_ ++#define FH_PMU_H_ ++ ++#include <linux/slab.h> ++#include <linux/ioctl.h> ++ ++#define DEVICE_NAME "fh_pwm" ++#define FH_PWM_PROC_FILE "driver/pwm" ++ ++#define REG_PWM_CTRL (0x00) ++#define REG_PWM_CMD(n) (((n) * 4) + REG_PWM_CTRL + 4) ++ ++#define PWM_IOCTL_MAGIC 'p' ++#define ENABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 0, __u32) ++#define DISABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 1, __u32) ++ ++#define SET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 2, __u32) ++#define GET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 3, __u32) ++#define SET_PWM_DUTY_CYCLE_PERCENT _IOWR(PWM_IOCTL_MAGIC, 4, __u32) ++#define PWM_IOCTL_MAXNR 8 ++ ++struct fh_pwm_chip_data ++{ ++ int id; ++ int working; ++ u32 period_ns; ++ u32 counter_ns; ++ int percent; ++}; ++ ++#endif /* FH_PMU_H_ */ +diff --git a/drivers/pwm/pwmv2-fullhan.c b/drivers/pwm/pwmv2-fullhan.c +new file mode 100644 +index 00000000..d2dc6bba +--- /dev/null ++++ b/drivers/pwm/pwmv2-fullhan.c +@@ -0,0 +1,1043 @@ ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/pwm.h> ++#include <linux/printk.h> ++#include <linux/fs.h> ++#include <linux/miscdevice.h> ++#include <linux/decompress/mm.h> ++#include <linux/of_address.h> ++#include <linux/proc_fs.h> ++#include <linux/seq_file.h> ++#include <linux/time.h> ++#include <linux/interrupt.h> ++#include <linux/wait.h> ++#include <linux/sched.h> ++#include <linux/delay.h> ++ ++#include <linux/uaccess.h> ++#include "pwmv2-fullhan.h" ++#include "mach/fh_predefined.h" ++ ++#define FH_PWM_DEBUG ++#ifdef FH_PWM_DEBUG ++#define PRINT_DBG(fmt, args...) printk(fmt, ##args) ++#else ++#define PRINT_DBG(fmt, args...) do {} while (0) ++#endif ++ ++#define STATUS_INT (1<<31) ++#define STATUS_FINALL0 (1<<0) ++#define STATUS_FINALL1 (1<<1) ++#define STATUS_FINALL2 (1<<2) ++#define STATUS_FINALL3 (1<<3) ++#define STATUS_FINALL4 (1<<4) ++#define STATUS_FINALL5 (1<<5) ++#define STATUS_FINALL6 (1<<6) ++#define STATUS_FINALL7 (1<<7) ++#define STATUS_FINONCE0 (1<<8) ++#define STATUS_FINONCE1 (1<<9) ++#define STATUS_FINONCE2 (1<<10) ++#define STATUS_FINONCE3 (1<<11) ++#define STATUS_FINONCE4 (1<<12) ++#define STATUS_FINONCE5 (1<<13) ++#define STATUS_FINONCE6 (1<<14) ++#define STATUS_FINONCE7 (1<<15) ++ ++#define OFFSET_PWM_BASE(n) (0x100 + 0x100 * n) ++ ++#define OFFSET_PWM_GLOBAL_CTRL0 (0x000) ++#define OFFSET_PWM_GLOBAL_CTRL1 (0x004) ++#define OFFSET_PWM_GLOBAL_CTRL2 (0x008) ++#define OFFSET_PWM_INT_ENABLE (0x010) ++#define OFFSET_PWM_INT_STATUS (0x014) ++ ++#define OFFSET_PWM_CTRL(n) (0x000 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_CFG0(n) (0x004 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_CFG1(n) (0x008 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_CFG2(n) (0x00c + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_CFG3(n) (0x010 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_CFG4(n) (0x014 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_STATUS0(n) (0x020 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_STATUS1(n) (0x024 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_STATUS2(n) (0x028 + OFFSET_PWM_BASE(n)) ++#define OFFSET_PWM_STOPTIME_BIT(n) (8 + 16 * ((n) / 8) + ((n) % 8)) ++#define OFFSET_PWM_FINSHALL_BIT(n) (0 + 16 * ((n) / 8) + ((n) % 8)) ++#define OFFSET_PWM_FINSHONCE_BIT(n) (8 + 16 * ((n) / 8) + ((n) % 8)) ++ ++struct fh_pwm_driver { ++ unsigned int irq; ++ struct pwm_chip chip; ++ void __iomem *base; ++ struct clk *clk; ++ struct proc_dir_entry *proc_file; ++}; ++ ++struct fh_pwm_driver *fh_pwm_drv; ++ ++static void fh_pwm_output_mask(unsigned int mask) ++{ ++ writel(mask, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2); ++} ++ ++static void fh_pwm_output_enable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2); ++ reg |= (1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2); ++} ++ ++static void fh_pwm_output_disable(unsigned int n) ++{ ++ unsigned int reg; ++/* ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++ reg |= 1 << (8 + n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++*/ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2); ++ reg &= ~(1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2); ++} ++ ++static void fh_pwm_config_enable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0); ++ reg |= (1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0); ++} ++ ++static void fh_pwm_config_disable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0); ++ reg &= ~(1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0); ++} ++#ifdef DEBUG ++static void fh_pwm_shadow_enable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++ reg |= (1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++} ++ ++static void fh_pwm_shadow_disable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++ reg &= ~(1 << n); ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++} ++#endif ++ ++static void fh_pwm_interrupt_finishall_enable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++ ++ reg |= (1 << OFFSET_PWM_FINSHALL_BIT(n)); ++ ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++} ++ ++static void fh_pwm_interrupt_finishall_disable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++ ++ reg &= ~(1 << OFFSET_PWM_FINSHALL_BIT(n)); ++ ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++} ++ ++static void fh_pwm_interrupt_finishonce_enable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++ ++ reg |= (1 << OFFSET_PWM_FINSHONCE_BIT(n)); ++ ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++} ++ ++static void fh_pwm_interrupt_finishonce_disable(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++ ++ reg &= ~(1 << OFFSET_PWM_FINSHONCE_BIT(n)); ++ ++ writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++} ++ ++static unsigned int fh_pwm_interrupt_get_status(void) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS); ++ ++ reg &= readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE); ++ ++ return reg; ++} ++ ++static void fh_pwm_interrupt_finishonce_clear(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS); ++#ifdef CONFIG_PWM_FULLHAN_V21 ++ reg |= (1 << OFFSET_PWM_FINSHONCE_BIT(n)); ++#else ++ reg &= ~(1 << OFFSET_PWM_FINSHONCE_BIT(n)); ++#endif ++ ++ return writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_STATUS); ++} ++ ++static void fh_pwm_interrupt_finishall_clear(unsigned int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS); ++ ++#ifdef CONFIG_PWM_FULLHAN_V21 ++ reg |= (1 << OFFSET_PWM_FINSHALL_BIT(n)); ++#else ++ reg &= ~(1 << OFFSET_PWM_FINSHALL_BIT(n)); ++#endif ++ ++ return writel(reg, fh_pwm_drv->base + OFFSET_PWM_INT_STATUS); ++} ++ ++ ++static void fh_pwm_get_status(struct fh_pwm_chip_data *chip_data) ++{ ++ unsigned int status0, status1, status2; ++ status0 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS0(chip_data->id)); ++ status1 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS1(chip_data->id)); ++ status2 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS2(chip_data->id)); ++ chip_data->status.busy = (status2 >> 4) & 0x1; ++ chip_data->status.error = (status2 >> 3) & 0x1; ++ chip_data->status.total_cnt = status1; ++ chip_data->status.done_cnt = status0; ++} ++ ++static int fh_pwm_wait_done(struct fh_pwm_chip_data *chip_data) ++{ ++ if (chip_data) ++ fh_pwm_get_status(chip_data); ++ ++ if (chip_data->status.busy == 0) ++ return chip_data->status.done_cnt; ++ ++ if (chip_data->config.finish_all) { ++ wait_event_interruptible(chip_data->wait_done, chip_data->status.busy == 0); ++ } else { ++ while (chip_data->status.busy == 1) { ++ mdelay(10); ++ fh_pwm_get_status(chip_data); ++ } ++ } ++ return chip_data->status.done_cnt; ++} ++ ++static int fh_pwm_set_config(struct fh_pwm_chip_data *chip_data) ++{ ++ unsigned int clk_rate = clk_get_rate(fh_pwm_drv->clk); ++ unsigned int ctrl = 0, period, duty, delay, phase, reg; ++ unsigned int period_used, duty_used, phase_used, busy; ++ ++ fh_pwm_config_disable(chip_data->id); ++ ++ period_used = readl(fh_pwm_drv->base + OFFSET_PWM_CFG0(chip_data->id)); ++ duty_used = readl(fh_pwm_drv->base + OFFSET_PWM_CFG1(chip_data->id)); ++ phase_used = readl(fh_pwm_drv->base + OFFSET_PWM_CFG2(chip_data->id)); ++ busy = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS2(chip_data->id)) \ ++ & (0x10); ++ period = chip_data->config.period_ns / (NSEC_PER_SEC / clk_rate); ++ duty = chip_data->config.duty_ns / (NSEC_PER_SEC / clk_rate); ++ delay = chip_data->config.delay_ns / (NSEC_PER_SEC / clk_rate); ++ phase = chip_data->config.phase_ns / (NSEC_PER_SEC / clk_rate); ++ ++ if (period > 0x1ffffff) { ++ pr_err("PWM: period exceed 24-bit\n"); ++ return -EINVAL; ++ } ++ ++ if (duty > 0x1ffffff) { ++ pr_err("PWM: duty exceed 24-bit\n"); ++ return -EINVAL; ++ } ++ ++ if (duty > period) { ++ pr_err("PWM: duty is over period\n"); ++ return -EINVAL; ++ } ++ ++ PRINT_DBG("set period: 0x%x\n", period); ++ PRINT_DBG("set duty: 0x%x\n", duty); ++ PRINT_DBG("set phase: 0x%x\n", phase); ++ PRINT_DBG("set delay: 0x%x\n", delay); ++ ++ writel(period, fh_pwm_drv->base + OFFSET_PWM_CFG0(chip_data->id)); ++ writel(duty, fh_pwm_drv->base + OFFSET_PWM_CFG1(chip_data->id)); ++ writel(phase, fh_pwm_drv->base + OFFSET_PWM_CFG2(chip_data->id)); ++ writel(delay, fh_pwm_drv->base + OFFSET_PWM_CFG3(chip_data->id)); ++ writel(chip_data->config.pulses, ++ fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id)); ++ ++ if (chip_data->config.delay_ns) ++ ctrl |= 1 << 3; ++ ++ if (!chip_data->config.pulses) ++ ctrl |= 1 << 0; ++ ++ ctrl |= (chip_data->config.stop & 0x3) << 1; ++ ++ writel(ctrl, fh_pwm_drv->base + OFFSET_PWM_CTRL(chip_data->id)); ++ ++ PRINT_DBG("set ctrl: 0x%x\n", ctrl); ++ ++ ctrl = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++ ++ reg = (chip_data->config.stop >> 4) & 0x1; ++ if (reg) ++ ctrl |= (1 << OFFSET_PWM_STOPTIME_BIT(chip_data->id)); ++ else ++ ctrl &= ~(1 << OFFSET_PWM_STOPTIME_BIT(chip_data->id)); ++ ++ writel(ctrl, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1); ++ ++ writel(chip_data->config.pulses, ++ fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id)); ++ PRINT_DBG("set pulses: 0x%x\n", chip_data->config.pulses); ++ ++ if (chip_data->config.finish_once) ++ fh_pwm_interrupt_finishonce_enable(chip_data->id); ++ else ++ fh_pwm_interrupt_finishonce_disable(chip_data->id); ++ ++ if (chip_data->config.finish_all) { ++ init_waitqueue_head(&chip_data->wait_done); ++ fh_pwm_interrupt_finishall_enable(chip_data->id); ++ } else ++ fh_pwm_interrupt_finishall_disable(chip_data->id); ++ ++ if (busy && \ ++ (((duty + phase) < period) ^ ((duty_used + phase_used) < period_used))) ++ fh_pwm_output_disable(chip_data->id); ++ ++ fh_pwm_config_enable(chip_data->id); ++ ++ return 0; ++} ++ ++static void fh_pwm_get_config(struct fh_pwm_chip_data *chip_data) ++{ ++ unsigned int clk_rate = clk_get_rate(fh_pwm_drv->clk); ++ unsigned int ctrl = 0, period, duty, delay, phase, pulses, ++ status0, status1, status2; ++ ++ period = readl(fh_pwm_drv->base + OFFSET_PWM_CFG0(chip_data->id)); ++ duty = readl(fh_pwm_drv->base + OFFSET_PWM_CFG1(chip_data->id)); ++ phase = readl(fh_pwm_drv->base + OFFSET_PWM_CFG2(chip_data->id)); ++ delay = readl(fh_pwm_drv->base + OFFSET_PWM_CFG3(chip_data->id)); ++ pulses = readl(fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id)); ++ ctrl = readl(fh_pwm_drv->base + OFFSET_PWM_CTRL(chip_data->id)); ++ status0 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS0(chip_data->id)); ++ status1 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS1(chip_data->id)); ++ status2 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS2(chip_data->id)); ++ ++ ++ PRINT_DBG("==============================\n"); ++ PRINT_DBG("pwm%d register config:\n", chip_data->id); ++ PRINT_DBG("\t\tperiod: 0x%x\n", period); ++ PRINT_DBG("\t\tduty: 0x%x\n", duty); ++ PRINT_DBG("\t\tphase: 0x%x\n", phase); ++ PRINT_DBG("\t\tdelay: 0x%x\n", delay); ++ PRINT_DBG("\t\tpulses: 0x%x\n", pulses); ++ PRINT_DBG("\t\tctrl: 0x%x\n", ctrl); ++ PRINT_DBG("\t\tstatus0: 0x%x\n", status0); ++ PRINT_DBG("\t\tstatus1: 0x%x\n", status1); ++ PRINT_DBG("\t\tstatus2: 0x%x\n", status2); ++ ++ chip_data->config.period_ns = period * (NSEC_PER_SEC / clk_rate); ++ chip_data->config.duty_ns = duty * (NSEC_PER_SEC / clk_rate); ++ ++ PRINT_DBG("\t\tclk_rate: %d\n", clk_rate); ++ PRINT_DBG("\t\tconfig.period_ns: %d\n", chip_data->config.period_ns); ++ PRINT_DBG("\t\tconfig.duty_ns: %d\n", chip_data->config.duty_ns); ++ PRINT_DBG("==============================\n\n"); ++ ++ chip_data->config.phase_ns = phase * (NSEC_PER_SEC / clk_rate); ++ chip_data->config.delay_ns = delay * (NSEC_PER_SEC / clk_rate); ++ chip_data->config.pulses = pulses; ++ chip_data->config.stop = (ctrl >> 1) & 0x3; ++ chip_data->config.percent = chip_data->config.duty_ns / ++ (chip_data->config.period_ns / 100); ++ ++ chip_data->status.busy = (status2 >> 4) & 0x1; ++ chip_data->status.error = (status2 >> 3) & 0x1; ++ chip_data->status.total_cnt = status1; ++ chip_data->status.done_cnt = status0; ++} ++ ++int fh_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL); ++ if (chip_data == NULL) { ++ pr_err("pwm[%d], chip data malloc failed\n", pwm->hwpwm); ++ return -ENOMEM; ++ } ++ ++ chip_data->id = pwm->hwpwm; ++ chip_data->config.duty_ns = duty_ns; ++ chip_data->config.period_ns = period_ns; ++ ++ fh_pwm_set_config(chip_data); ++ ++ kfree(chip_data); ++ ++ return 0; ++} ++ ++int fh_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ fh_pwm_output_enable(pwm->hwpwm); ++ return 0; ++} ++ ++void fh_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ fh_pwm_output_disable(pwm->hwpwm); ++} ++ ++static int fh_pwm_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_pwm_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++ ++static long fh_pwm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct fh_pwm_chip_data chip_data = {0}; ++ unsigned int val; ++ ++ if (unlikely(_IOC_TYPE(cmd) != PWM_IOCTL_MAGIC)) { ++ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n", ++ __func__, _IOC_TYPE(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (unlikely(_IOC_NR(cmd) > PWM_IOCTL_MAXNR)) { ++ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -ENOTTY); ++ return -ENOTTY; ++ } ++ ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ ret = !access_ok(VERIFY_WRITE, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++ ret = !access_ok(VERIFY_READ, ++ (void __user *)arg, _IOC_SIZE(cmd)); ++ ++ if (ret) { ++ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n", ++ __func__, _IOC_NR(cmd), -EACCES); ++ return -EACCES; ++ } ++ ++ switch (cmd) { ++ case SET_PWM_ENABLE: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_output_enable(val); ++ break; ++ case ENABLE_PWM: ++ ret = copy_from_user((void *)&chip_data, ++ (void __user *)arg, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("ioctrl:Get chip data from user space failed\n"); ++ return -EFAULT; ++ } ++ ++ if (chip_data.id >= fh_pwm_drv->chip.npwm) { ++ pr_err("ioctrl:PWM Channel Error\n"); ++ return -EFAULT; ++ } ++ ++ memcpy( ++ fh_pwm_drv->chip.pwms[chip_data.id].chip_data, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ ++ fh_pwm_output_enable(chip_data.id); ++ break; ++ case DISABLE_PWM: ++ ret = copy_from_user((void *)&chip_data, ++ (void __user *)arg, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("ioctrl:Get chip data from user space failed\n"); ++ return -EFAULT; ++ } ++ ++ if (chip_data.id >= fh_pwm_drv->chip.npwm) { ++ pr_err("ioctrl:PWM Channel Error\n"); ++ return -EFAULT; ++ } ++ memcpy( ++ fh_pwm_drv->chip.pwms[chip_data.id].chip_data, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ ++ fh_pwm_output_disable(chip_data.id); ++ break; ++ case SET_PWM_DUTY_CYCLE: ++ ret = copy_from_user((void *)&chip_data, ++ (void __user *)arg, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("ioctrl:Get chip data from user space failed\n"); ++ return -EFAULT; ++ } ++ if (chip_data.id >= fh_pwm_drv->chip.npwm) { ++ pr_err("ioctrl:PWM Channel Error\n"); ++ return -EFAULT; ++ } ++ memcpy( ++ fh_pwm_drv->chip.pwms[chip_data.id].chip_data, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ ++ printk("ioctl: SET_PWM_DUTY_CYCLE, " ++ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n", ++ chip_data.id, chip_data.config.duty_ns, ++ chip_data.config.period_ns); ++ ++ ret = fh_pwm_set_config(fh_pwm_drv->chip.pwms[chip_data.id].chip_data); ++ break; ++ case GET_PWM_DUTY_CYCLE: ++ ret = copy_from_user((void *)&chip_data, ++ (void __user *)arg, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("ioctrl:Get chip data from user space failed\n"); ++ return -EFAULT; ++ } ++ if (chip_data.id >= fh_pwm_drv->chip.npwm) { ++ pr_err("ioctrl:PWM Channel Error\n"); ++ return -EFAULT; ++ } ++ memcpy( ++ fh_pwm_drv->chip.pwms[chip_data.id].chip_data, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ pr_info("ioctl: GET_PWM_DUTY_CYCLE, " ++ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n", ++ chip_data.id, chip_data.config.duty_ns, ++ chip_data.config.period_ns); ++ ++ fh_pwm_get_config(&chip_data); ++ ret = copy_to_user((void __user *)arg, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("ioctrl:Copy chip data to user space failed\n"); ++ return -EFAULT; ++ } ++ break; ++ case SET_PWM_DUTY_CYCLE_PERCENT: ++ ret = copy_from_user((void *)&chip_data, ++ (void __user *)arg, ++ sizeof(struct fh_pwm_chip_data)); ++ if (ret != 0) { ++ pr_err("Get chip data from user space failed\n"); ++ return -EFAULT; ++ } ++ ++ if (chip_data.id >= fh_pwm_drv->chip.npwm) { ++ pr_err("ioctrl:PWM Channel Error\n"); ++ return -EFAULT; ++ } ++ ++ if (chip_data.config.percent > 100) { ++ pr_err("ERROR: percentage is over 100\n"); ++ return -EIO; ++ } ++ chip_data.config.duty_ns = chip_data.config.period_ns * ++ chip_data.config.percent / 100; ++ pr_info("ioctl: SET_PWM_DUTY_CYCLE_PERCENT, " ++ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n", ++ chip_data.id, chip_data.config.duty_ns, ++ chip_data.config.period_ns); ++ ++ memcpy( ++ fh_pwm_drv->chip.pwms[chip_data.id].chip_data, ++ (void *)&chip_data, ++ sizeof(struct fh_pwm_chip_data)); ++ ++ ret = fh_pwm_set_config(&chip_data); ++ break; ++ case ENABLE_MUL_PWM: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_output_mask(val); ++ break; ++ case ENABLE_FINSHALL_INTR: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_interrupt_finishall_enable(val); ++ break; ++ case ENABLE_FINSHONCE_INTR: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_interrupt_finishonce_enable(val); ++ break; ++ case DISABLE_FINSHALL_INTR: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_interrupt_finishall_disable(val); ++ break; ++ case DISABLE_FINSHONCE_INTR: ++ get_user(val, (unsigned int __user *)arg); ++ fh_pwm_interrupt_finishonce_disable(val); ++ break; ++ case WAIT_PWM_FINSHALL: ++ get_user(val, (unsigned int __user *)arg); ++ ret = fh_pwm_wait_done(fh_pwm_drv->chip.pwms[val].chip_data); ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct file_operations fh_pwm_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_pwm_open, ++ .release = fh_pwm_release, ++ .unlocked_ioctl = fh_pwm_ioctl, ++}; ++ ++static struct miscdevice fh_pwm_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEVICE_NAME, ++ .fops = &fh_pwm_fops, ++}; ++ ++static const struct pwm_ops fh_pwm_ops = { ++ .config = fh_pwm_config, ++ .enable = fh_pwm_enable, ++ .disable = fh_pwm_disable, ++ .owner = THIS_MODULE, ++}; ++ ++ ++static void del_char(char *str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) ++ *p++ = *q; ++ q++; ++ } ++ *p = '\0'; ++} ++ ++static ssize_t fh_pwm_proc_write(struct file *filp, ++ const char *buf, size_t len, loff_t *off) ++{ ++ int i; ++ char message[64] = {0}; ++ char *const delim = ","; ++ char *cur = message; ++ char *param_str[8]; ++ unsigned int param[8]; ++ struct fh_pwm_chip_data *chip_data; ++ ++ len = (len > 64) ? 64 : len; ++ ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ ++ for (i = 0; i < 8; i++) { ++ param_str[i] = strsep(&cur, delim); ++ if (!param_str[i]) { ++ pr_err("%s: ERROR: parameter[%d] is empty\n", ++ __func__, i); ++ pr_err("id, switch_mask, duty_ns, period_ns, " ++ "numofpules, delay_ns, phase_ns, stop_status\n"); ++ pr_err("eg. echo '0,1,5000,10000,0,0,1000,0' > /proc/driver/pwm\n"); ++ return -EINVAL; ++ } else { ++ del_char(param_str[i], ' '); ++ del_char(param_str[i], '\n'); ++ param[i] = (unsigned int)simple_strtoul(param_str[i], NULL, 10); ++ if (param[i] < 0) { ++ pr_err("%s: ERROR: parameter[%d] is incorrect\n", __func__, i); ++ pr_err("id, switch_mask, duty_ns, period_ns, numofpules, " ++ "delay_ns, phase_ns, stop_status\n"); ++ pr_err("eg. echo '0,1,5000,10000,0,0,1000,0' > /proc/driver/pwm\n"); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL); ++ if (chip_data == NULL) { ++ pr_err("pwm[%d], chip data malloc failed\n", i); ++ return 0; ++ } ++ ++ chip_data->id = param[0]; ++ chip_data->config.duty_ns = param[2]; ++ chip_data->config.period_ns = param[3]; ++ chip_data->config.pulses = param[4]; ++ chip_data->config.delay_ns = param[5]; ++ chip_data->config.phase_ns = param[6]; ++ chip_data->config.stop = param[7]; ++ ++ fh_pwm_set_config(chip_data); ++ ++ printk("set pwm %d, enable: 0x%x, duty cycle: %u ns, period cycle: %u," ++ "numofpulse: %d, delay: %d ns, phase: %d ns, stop: %d\n", ++ param[0], param[1], param[2], param[3], ++ param[4], param[5], param[6], param[7]); ++ ++ fh_pwm_output_mask(param[1]); ++ ++ kfree(chip_data); ++ ++ return len; ++} ++ ++static void *v_seq_start(struct seq_file *s, loff_t *pos) ++{ ++ static unsigned long counter; ++ if (*pos == 0) ++ return &counter; ++ else { ++ *pos = 0; ++ return NULL; ++ } ++} ++ ++static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos) ++{ ++ (*pos)++; ++ return NULL; ++} ++ ++static void v_seq_stop(struct seq_file *s, void *v) ++{ ++ ++} ++ ++static int v_seq_show(struct seq_file *sfile, void *v) ++{ ++ int i; ++ seq_printf(sfile, "\nPWM Status:\n"); ++ ++ seq_printf(sfile, "global_ctrl0: 0x%x\n", ++ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0)); ++ seq_printf(sfile, "global_ctrl1: 0x%x\n", ++ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1)); ++ seq_printf(sfile, "global_ctrl2: 0x%x\n", ++ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2)); ++ ++ for (i = 0; i < fh_pwm_drv->chip.npwm; i++) { ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = pwm_get_chip_data(&fh_pwm_drv->chip.pwms[i]); ++ fh_pwm_get_config(chip_data); ++ ++ seq_printf(sfile, "id: %d \t%s, duty_ns: %u, period_ns: %u\n", ++ chip_data->id, ++ (chip_data->status.busy) ? "ENABLE" : "DISABLE", ++ chip_data->config.duty_ns, ++ chip_data->config.period_ns); ++ } ++ return 0; ++} ++ ++static const struct seq_operations pwm_seq_ops = { ++ .start = v_seq_start, ++ .next = v_seq_next, ++ .stop = v_seq_stop, ++ .show = v_seq_show ++}; ++ ++static int fh_pwm_proc_open(struct inode *inode, struct file *file) ++{ ++ return seq_open(file, &pwm_seq_ops); ++} ++ ++ ++static const struct file_operations fh_pwm_proc_ops = { ++ .owner = THIS_MODULE, ++ .open = fh_pwm_proc_open, ++ .read = seq_read, ++ .write = fh_pwm_proc_write, ++ .release = seq_release, ++}; ++ ++static irqreturn_t fh_pwm_interrupt(int this_irq, void *param) ++{ ++#ifdef CONFIG_PWM_FULLHAN_V21 ++ unsigned int status, stat_once_l, stat_once_h, stat_all_l, stat_all_h; ++ unsigned int irq; ++ struct fh_pwm_chip_data *fh_chip_data; ++ ++ status = fh_pwm_interrupt_get_status(); ++ status &= 0xffffffff; ++ stat_once_l = (status >> 8) & 0xff; ++ stat_all_l = status & 0xff; ++ stat_once_h = (status >> 24) & 0x3f; ++ stat_all_h = (status >> 16) & 0x3f; ++ ++ if (stat_once_l) { ++ irq = fls(stat_once_l); ++ fh_pwm_interrupt_finishonce_clear(irq - 1); ++ } ++ if (stat_once_h) { ++ irq = fls(stat_once_h) + 8; ++ fh_pwm_interrupt_finishonce_clear(irq - 1); ++ } ++ if (stat_all_l) { ++ irq = fls(stat_all_l); ++ fh_pwm_interrupt_finishall_clear(irq - 1); ++ fh_chip_data = (struct fh_pwm_chip_data *)fh_pwm_drv->chip.pwms[irq - 1].chip_data; ++ fh_pwm_get_status(fh_chip_data); ++ wake_up_interruptible(&fh_chip_data->wait_done); ++ } ++ if (stat_all_h) { ++ irq = fls(stat_all_h) + 8; ++ fh_pwm_interrupt_finishall_clear(irq - 1); ++ fh_chip_data = (struct fh_pwm_chip_data *)fh_pwm_drv->chip.pwms[irq - 1].chip_data; ++ fh_pwm_get_status(fh_chip_data); ++ wake_up_interruptible(&fh_chip_data->wait_done); ++ } ++#endif ++#ifdef CONFIG_PWM_FULLHAN_V20 ++ unsigned int status, stat_once, stat_all; ++ struct fh_pwm_chip_data *chip_data; ++ unsigned int irq; ++ ++ status = fh_pwm_interrupt_get_status(); ++ ++ status &= 0xffff; ++ ++ stat_once = (status >> 8) & 0xff; ++ stat_all = status & 0xff; ++ ++ if (stat_once) { ++ irq = fls(stat_once); ++ chip_data = pwm_get_chip_data(&fh_pwm_drv->chip.pwms[irq - 1]); ++ fh_pwm_interrupt_finishonce_clear(irq - 1); ++ } ++ ++ if (stat_all) { ++ irq = fls(stat_all); ++ chip_data = pwm_get_chip_data(&fh_pwm_drv->chip.pwms[irq - 1]); ++ fh_pwm_interrupt_finishall_clear(irq - 1); ++ fh_pwm_get_status(chip_data); ++ wake_up_interruptible(&chip_data->wait_done); ++ } ++#endif ++ return IRQ_HANDLED; ++} ++ ++static int __devinit fh_pwm_probe(struct platform_device *pdev) ++{ ++ int err, i; ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ err = -ENXIO; ++ goto fail_no_mem_resource; ++ } ++ ++ res = request_mem_region(res->start, resource_size(res), pdev->name); ++ if (res == NULL) { ++ err = -EBUSY; ++ goto fail_no_mem_resource; ++ } ++ ++ fh_pwm_drv = kzalloc(sizeof(struct fh_pwm_driver), GFP_KERNEL); ++ ++ fh_pwm_drv->base = ioremap(res->start, resource_size(res)); ++ if (fh_pwm_drv->base == NULL) { ++ err = -ENXIO; ++ goto fail_no_ioremap; ++ } ++ ++ fh_pwm_drv->clk = clk_get(&pdev->dev, "pwm_clk"); ++ ++ if (IS_ERR(fh_pwm_drv->clk)) { ++ err = PTR_ERR(fh_pwm_drv->clk); ++ goto fail_no_clk; ++ } ++ ++ clk_enable(fh_pwm_drv->clk); ++ ++ PRINT_DBG("%s: clk_rate: %lu\n", __func__, clk_get_rate(fh_pwm_drv->clk)); ++ ++ err = platform_get_irq(pdev, 0); ++ if (err < 0) { ++ dev_err(&pdev->dev, "no irq resource?\n"); ++ goto fail_no_clk; ++ } ++ ++ fh_pwm_drv->irq = err; ++ ++ err = request_irq(fh_pwm_drv->irq, ++ fh_pwm_interrupt, IRQF_DISABLED, ++ dev_name(&pdev->dev), fh_pwm_drv); ++ if (err) { ++ dev_err(&pdev->dev, "failure requesting irq %i\n", fh_pwm_drv->irq); ++ goto fail_no_clk; ++ } ++ ++ err = misc_register(&fh_pwm_misc); ++ if (err < 0) { ++ pr_err("%s: ERROR: %s registration failed", ++ __func__, DEVICE_NAME); ++ return -ENXIO; ++ } ++ ++ fh_pwm_drv->chip.dev = &pdev->dev; ++ fh_pwm_drv->chip.ops = &fh_pwm_ops; ++ fh_pwm_drv->chip.base = pdev->id; ++ fh_pwm_drv->chip.npwm = CONFIG_FH_PWM_NUM; ++ ++ err = pwmchip_add(&fh_pwm_drv->chip); ++ if (err < 0) { ++ pr_err("%s: ERROR: %s pwmchip_add failed", ++ __func__, DEVICE_NAME); ++ return err; ++ } ++ ++ for (i = 0; i < fh_pwm_drv->chip.npwm; i++) { ++ struct fh_pwm_chip_data *chip_data; ++ ++ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL); ++ if (chip_data == NULL) { ++ pr_err("pwm[%d], chip data malloc failed\n", i); ++ continue; ++ } ++ ++ chip_data->id = i; ++ ++ pwm_set_chip_data(&fh_pwm_drv->chip.pwms[i], chip_data); ++ } ++ ++ fh_pwm_output_mask(0); ++ ++ platform_set_drvdata(pdev, fh_pwm_drv); ++ ++ pr_info("PWM driver, Number: %d, IO base addr: 0x%p\n", ++ fh_pwm_drv->chip.npwm, fh_pwm_drv->base); ++ ++ fh_pwm_drv->proc_file = create_proc_entry(FH_PWM_PROC_FILE, 0644, NULL); ++ ++ if (fh_pwm_drv->proc_file) ++ fh_pwm_drv->proc_file->proc_fops = &fh_pwm_proc_ops; ++ else ++ pr_err("%s: ERROR: %s proc file create failed", ++ __func__, DEVICE_NAME); ++ ++ dev_dbg(&pdev->dev, "PWM probe successful, IO base addr: %p\n", ++ fh_pwm_drv->base); ++ return 0; ++ ++fail_no_clk: ++ iounmap(fh_pwm_drv->base); ++fail_no_ioremap: ++ release_mem_region(res->start, resource_size(res)); ++fail_no_mem_resource: ++ return err; ++} ++ ++static int __exit fh_pwm_remove(struct platform_device *pdev) ++{ ++ int err, i; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ for (i = 0; i < fh_pwm_drv->chip.npwm; i++) ++ kfree(fh_pwm_drv->chip.pwms[i].chip_data); ++ ++ err = pwmchip_remove(&fh_pwm_drv->chip); ++ if (err < 0) ++ return err; ++ ++ dev_dbg(&pdev->dev, "pwm driver removed\n"); ++ ++ fh_pwm_output_mask(0); ++ clk_disable(fh_pwm_drv->clk); ++ free_irq(fh_pwm_drv->irq, NULL); ++ iounmap(fh_pwm_drv->base); ++ release_mem_region(res->start, resource_size(res)); ++ platform_set_drvdata(pdev, NULL); ++ misc_deregister(&fh_pwm_misc); ++ ++ free(fh_pwm_drv); ++ fh_pwm_drv = NULL; ++ ++ return 0; ++} ++ ++static struct platform_driver fh_pwm_driver = { ++ .driver = { ++ .name = DEVICE_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fh_pwm_probe, ++ .remove = __exit_p(fh_pwm_remove), ++}; ++ ++static int __init fh_pwm_init(void) ++{ ++ return platform_driver_register(&fh_pwm_driver); ++} ++ ++static void __exit fh_pwm_exit(void) ++{ ++ ++ platform_driver_unregister(&fh_pwm_driver); ++ ++} ++ ++module_init(fh_pwm_init); ++module_exit(fh_pwm_exit); ++ ++ ++MODULE_AUTHOR("fullhan"); ++ ++MODULE_DESCRIPTION("FH PWM driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR); +diff --git a/drivers/pwm/pwmv2-fullhan.h b/drivers/pwm/pwmv2-fullhan.h +new file mode 100644 +index 00000000..6d05dcc8 +--- /dev/null ++++ b/drivers/pwm/pwmv2-fullhan.h +@@ -0,0 +1,70 @@ ++#ifndef FH_PMU_H_ ++#define FH_PMU_H_ ++ ++#include <linux/slab.h> ++#include <linux/ioctl.h> ++#include <linux/wait.h> ++ ++#define DEVICE_NAME "fh_pwm" ++#define FH_PWM_PROC_FILE "driver/pwm" ++ ++#define REG_PWM_CTRL (0x00) ++#define REG_PWM_CMD(n) (((n) * 4) + REG_PWM_CTRL + 4) ++ ++#define PWM_IOCTL_MAGIC 'p' ++#define ENABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 0, __u32) ++#define DISABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 1, __u32) ++ ++#define SET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 2, __u32) ++#define GET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 3, __u32) ++#define SET_PWM_DUTY_CYCLE_PERCENT _IOWR(PWM_IOCTL_MAGIC, 4, __u32) ++#define SET_PWM_ENABLE _IOWR(PWM_IOCTL_MAGIC, 5, __u32) ++#define ENABLE_MUL_PWM _IOWR(PWM_IOCTL_MAGIC, 6, __u32) ++#define ENABLE_FINSHALL_INTR _IOWR(PWM_IOCTL_MAGIC, 7, __u32) ++#define ENABLE_FINSHONCE_INTR _IOWR(PWM_IOCTL_MAGIC, 8, __u32) ++#define DISABLE_FINSHALL_INTR _IOWR(PWM_IOCTL_MAGIC, 9, __u32) ++#define DISABLE_FINSHONCE_INTR _IOWR(PWM_IOCTL_MAGIC, 10, __u32) ++#define WAIT_PWM_FINSHALL _IOWR(PWM_IOCTL_MAGIC, 12, __u32) ++ ++#define PWM_IOCTL_MAXNR 16 ++ ++struct fh_pwm_config ++{ ++ unsigned int period_ns; ++ unsigned int duty_ns; ++ unsigned int pulses; ++#define FH_PWM_STOPLVL_LOW (0x0) ++#define FH_PWM_STOPLVL_HIGH (0x3) ++#define FH_PWM_STOPLVL_KEEP (0x1) ++ ++#define FH_PWM_STOPCTRL_ATONCE (0x10) ++#define FH_PWM_STOPCTRL_AFTERFINISH (0x00) ++ unsigned int stop; ++ unsigned int delay_ns; ++ unsigned int phase_ns; ++ unsigned int percent; ++ unsigned int finish_once; ++ unsigned int finish_all; ++}; ++ ++struct fh_pwm_status ++{ ++ unsigned int done_cnt; ++ unsigned int total_cnt; ++ unsigned int busy; ++ unsigned int error; ++}; ++ ++struct fh_pwm_chip_data ++{ ++ int id; ++ struct fh_pwm_config config; ++ struct fh_pwm_status status; ++ wait_queue_head_t wait_done; ++ void (*finishall_callback)(struct fh_pwm_chip_data *data); ++ void (*finishonce_callback)(struct fh_pwm_chip_data *data); ++}; ++ ++ ++ ++#endif /* FH_PMU_H_ */ +diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig +index ce2aabf5..96fa8993 100644 +--- a/drivers/rtc/Kconfig ++++ b/drivers/rtc/Kconfig +@@ -1060,4 +1060,37 @@ config RTC_DRV_PUV3 + This drive can also be built as a module. If so, the module + will be called rtc-puv3. + ++ ++config RTC_DRV_FH ++ tristate "FH On-Chip RTC" ++ depends on RTC_CLASS ++ depends on ! (ARCH_FH8856 || ARCH_ZY2 || ARCH_FH8626V100) ++ help ++ Say Y here to enable support for the on-chip RTC found in ++ FH processors. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rtc-fh. ++ ++config RTC_DRV_FH_V2 ++ tristate "FH On-Chip RTC" ++ depends on RTC_CLASS ++ depends on ARCH_FH8856 || ARCH_ZY2 || ARCH_FH8626V100 ++ help ++ Say Y here to enable support for the on-chip RTC found in ++ FH processors. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rtc-fh. ++if RTC_DRV_FH_V2 ++ config USE_TSENSOR ++ bool 'USE TSENSOR' ++ default n ++ ++ config USE_TSENSOR_OFFSET ++ bool 'USE ENHANCEMENT TSENSOR' ++ default n ++endif ++ ++ + endif # RTC_CLASS +diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile +index 0ffefe87..337f688e 100644 +--- a/drivers/rtc/Makefile ++++ b/drivers/rtc/Makefile +@@ -108,3 +108,6 @@ obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o + obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o + obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o + obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o ++ ++obj-$(CONFIG_RTC_DRV_FH) += rtc-fh_v1.o ++obj-$(CONFIG_RTC_DRV_FH_V2) += rtc-fh_v2.o +diff --git a/drivers/rtc/rtc-fh_v1.c b/drivers/rtc/rtc-fh_v1.c +new file mode 100644 +index 00000000..b9ae1cdf +--- /dev/null ++++ b/drivers/rtc/rtc-fh_v1.c +@@ -0,0 +1,902 @@ ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/string.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/interrupt.h> ++#include <linux/rtc.h> ++#include <linux/bcd.h> ++#include <linux/clk.h> ++#include <linux/log2.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <mach/fh_rtc_v1.h> ++#include <mach/fh_sadc.h> ++#include <linux/delay.h> ++#include <linux/proc_fs.h> ++ ++/* #define FH_RTC_DEBUG_PRINT */ ++ ++#ifdef FH_RTC_DEBUG_PRINT ++#define RTC_PRINT_DBG(fmt, args...) \ ++ printk(KERN_INFO "[FH_RTC_DEBUG]: "); \ ++ printk(fmt, ## args) ++#else ++#define RTC_PRINT_DBG(fmt, args...) do { } while (0) ++#endif ++ ++#define RTC_MAGIC 0x55555555 ++#define RTC_PHASE 0x03840384 ++ ++#define SYNC_LOOP_COUNT 100 ++ ++struct fh_rtc_controller { ++ void * __iomem regs; ++ unsigned int irq; ++ unsigned int paddr; ++ unsigned int base_year; ++ unsigned int base_month; ++ unsigned int base_day; ++ struct rtc_device *rtc; ++ struct clk *clk; ++ struct proc_dir_entry *proc_rtc_entry; ++ int sadc_channel; ++ ++ struct workqueue_struct *wq; ++ struct delayed_work self_adjust; ++}; ++ ++struct fh_rtc_controller *fh_rtc; ++ ++enum { ++ ++ TIME_FUNC = 0, ++ ALARM_FUNC, ++ ++}; ++ ++/* value of SADC channel for reference to get current temperature */ ++long SadcValue[28] = { ++ 260, 293, 332, 375, 426, ++ 483, 548, 621, 706, 800, ++ 906, 1022, 1149, 1287, 1435, ++ 1590, 1750, 1913, 2075, 2233, ++ 2385, 2527, 2656, 2772, 2873, ++ 2960, 3034, 3094 ++}; ++ ++/* value of temperature for reference */ ++int Temperature1[28] = { ++ 95000, 90000, 85000, 80000, 75000, ++ 70000, 65000, 60000, 55000, 50000, ++ 45000, 40000, 35000, 30000, 25000, ++ 20000, 15000, 10000, 4000, 0, ++ -5000, -10000, -15000, -20000, -25000, ++ -30000, -35000, -40000 ++}; ++ ++/* value of temperature for reference to get current deviation */ ++int Temperature2[136] = { ++ -40000, -39000, -38000, -37000, -36000, -35000, ++ -34000, -33000, -32000, -31000, -30000, -29000, ++ -28000, -27000, -26000, -25000, -24000, -23000, ++ -22000, -21000, -20000, -19000, -18000, -17000, ++ -16000, -15000, -14000, -13000, -12000, -11000, ++ -10000, -9000, -8000, -7000, -6000, -5000, -4000, ++ -3000, -2000, -1000, 0, 1000, 2000, 3000, 4000, ++ 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, ++ 13000, 14000, 15000, 16000, 17000, 18000, 19000, ++ 20000, 21000, 22000, 23000, 24000, 25000, 26000, ++ 27000, 28000, 29000, 30000, 31000, 32000, 33000, ++ 34000, 35000, 36000, 37000, 38000, 39000, 40000, ++ 41000, 42000, 43000, 44000, 45000, 46000, 47000, ++ 48000, 49000, 50000, 51000, 52000, 53000, 54000, ++ 55000, 56000, 57000, 58000, 59000, 60000, 61000, ++ 62000, 63000, 64000, 65000, 66000, 67000, 68000, ++ 69000, 70000, 71000, 72000, 73000, 74000, 75000, ++ 76000, 77000, 78000, 79000, 80000, 81000, 82000, ++ 83000, 84000, 85000, 86000, 87000, 88000, 89000, ++ 90000, 91000, 92000, 93000, 94000, 95000 ++}; ++ ++/* the value of deviation to adjust rtc clock */ ++long Deviation[136] = { ++ 1690000, 1638400, 1587600, 1537600, 1488400, 1440000, ++ 1392400, 1345600, 1299600, 1254400, 1210000, 1166400, ++ 1123600, 1081600, 1040400, 1000000, 960400, 921600, ++ 883600, 846400, 810000, 774400, 739600, 705600, 672400, ++ 640000, 608400, 577600, 547600, 518400, 490000, 462400, ++ 435600, 409600, 384400, 360000, 336400, 313600, 291600, ++ 270400, 250000, 230400, 211600, 193600, 176400, 160000, ++ 144400, 129600, 115600, 102400, 90000, 78400, 67600, 57600, ++ 48400, 40000, 32400, 25600, 19600, 14400, 10000, 6400, ++ 3600, 1600, 400, 0, 400, 1600, 3600, 6400, 10000, 14400, ++ 19600, 25600, 32400, 40000, 48400, 57600, 67600, 78400, ++ 90000, 102400, 115600, 129600, 144400, 160000, 176400, ++ 193600, 211600, 230400, 250000, 270400, 291600, 313600, ++ 336400, 360000, 384400, 409600, 435600, 462400, 490000, ++ 518400, 547600, 577600, 608400, 640000, 672400, 705600, ++ 739600, 774400, 810000, 846400, 883600, 921600, 960400, ++ 1000000, 1040400, 1081600, 1123600, 1166400, 1210000, ++ 1254400, 1299600, 1345600, 1392400, 1440000, 1488400, ++ 1537600, 1587600, 1638400, 1690000, 1742400, 1795600, ++ 1849600, 1904400, 1960000 ++}; ++ ++static int accelerate_second_rtc(int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_rtc->regs + FH_RTC_OFFSET); ++ reg &= ~(0x7000000); ++ reg |= 0x30000000 | ((n & 0x7) << 24); ++ writel(reg, fh_rtc->regs + FH_RTC_OFFSET); ++ return 0; ++} ++ ++static int accelerate_minute_rtc(int m) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_rtc->regs + FH_RTC_OFFSET); ++ reg &= ~(0x3F0000); ++ reg |= 0x30000000 | ((m & 0x3f) << 16); ++ writel(reg, fh_rtc->regs + FH_RTC_OFFSET); ++ return 0; ++} ++ ++static int slow_down_second_rtc(int n) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_rtc->regs + FH_RTC_OFFSET); ++ reg &= ~(0x7000000); ++ reg |= 0x10000000 | ((n & 0x7) << 24); ++ writel(reg, fh_rtc->regs + FH_RTC_OFFSET); ++ return 0; ++} ++ ++static int slow_down_minute_rtc(int m) ++{ ++ unsigned int reg; ++ ++ reg = readl(fh_rtc->regs + FH_RTC_OFFSET); ++ reg &= ~(0x3F0000); ++ reg |= 0x10000000 | ((m & 0x3f) << 16); ++ writel(reg, fh_rtc->regs + FH_RTC_OFFSET); ++ return 0; ++} ++ ++static unsigned int fh_rtc_get_hw_sec_data(unsigned int func_switch) ++{ ++ ++ unsigned int ret_sec, raw_value, sec_value; ++ unsigned int min_value, hour_value, day_value; ++ ++ if (func_switch == TIME_FUNC) ++ raw_value = fh_rtc_get_time(fh_rtc->regs); ++ else ++ raw_value = fh_rtc_get_alarm_time(fh_rtc->regs); ++ ++ sec_value = FH_GET_RTC_SEC(raw_value); ++ min_value = FH_GET_RTC_MIN(raw_value); ++ hour_value = FH_GET_RTC_HOUR(raw_value); ++ day_value = FH_GET_RTC_DAY(raw_value); ++ ret_sec = (day_value * 86400) + (hour_value * 3600) ++ + (min_value * 60) + sec_value; ++ ++ return ret_sec; ++ ++} ++ ++static void fh_rtc_set_hw_sec_data(struct rtc_time *rtc_tm, ++ unsigned int func_switch) { ++ ++ unsigned int raw_value, sec_value, min_value; ++ unsigned int hour_value, day_value; ++ ++ day_value = rtc_year_days(rtc_tm->tm_mday, rtc_tm->tm_mon, ++ rtc_tm->tm_year+1900); ++ day_value += (rtc_tm->tm_year-70)*365 ++ + ELAPSED_LEAP_YEARS(rtc_tm->tm_year); ++ ++ hour_value = rtc_tm->tm_hour; ++ min_value = rtc_tm->tm_min; ++ sec_value = rtc_tm->tm_sec; ++ ++ raw_value = (day_value << DAY_BIT_START) ++ | (hour_value << HOUR_BIT_START) ++ | (min_value << MIN_BIT_START) ++ | (sec_value << SEC_BIT_START); ++ ++ if (func_switch == TIME_FUNC) ++ fh_rtc_set_time(fh_rtc->regs, raw_value); ++ else ++ fh_rtc_set_alarm_time(fh_rtc->regs, raw_value); ++ ++} ++ ++static int fh_rtc_exam_magic(void) ++{ ++ unsigned int magic, status; ++ int i; ++ ++ for (i = 0; i < 10; i++) { ++ magic = GET_REG(fh_rtc->regs + FH_RTC_USER_REG); ++ ++ if (magic != RTC_MAGIC) { ++ status = GET_REG(fh_rtc->regs+FH_RTC_SYNC); ++ status &= 0x2; ++ SET_REG(fh_rtc->regs+FH_RTC_SYNC, status); ++ ++ msleep(30); ++ } else { ++ return 0; ++ } ++ } ++ ++ printk(KERN_INFO "ERROR: read rtc failed: 0x%x\n", magic); ++ ++ return -EAGAIN; ++ ++} ++ ++static int fh_rtc_open(struct device *dev) ++{ ++ return 0; ++} ++ ++static void fh_rtc_release(struct device *dev) ++{ ++ return; ++} ++ ++static int fh_rtc_tm_compare(struct rtc_time *tm0, struct rtc_time *tm1) ++{ ++ unsigned long read = 0, write = 0; ++ ++ rtc_tm_to_time(tm0, &read); ++ rtc_tm_to_time(tm1, &write); ++ ++ if (write > read || write < read - 2) { ++ RTC_PRINT_DBG("ERROR: read(%d-%d-%d %d:%d:%d) vs " ++ "write(%d-%d-%d %d:%d:%d)\n", ++ tm0->tm_year + 1900, ++ tm0->tm_mon + 1, ++ tm0->tm_mday, ++ tm0->tm_hour, ++ tm0->tm_min, ++ tm0->tm_sec, ++ tm1->tm_year + 1900, ++ tm1->tm_mon + 1, ++ tm1->tm_mday, ++ tm1->tm_hour, ++ tm1->tm_min, ++ tm1->tm_sec); ++ return -1; ++ } ++ return 0; ++} ++ ++static int fh_rtc_gettime_nosync(struct device *dev, struct rtc_time *rtc_tm) ++{ ++ unsigned int temp; ++ ++ temp = fh_rtc_get_hw_sec_data(TIME_FUNC); ++ rtc_time_to_tm(temp, rtc_tm); ++ RTC_PRINT_DBG("rtc read date:0x%x\n", temp); ++ return 0; ++} ++ ++ ++static int fh_rtc_gettime_sync(struct device *dev, struct rtc_time *rtc_tm) ++{ ++ unsigned int status; ++ unsigned int loop_count; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(pdev); ++ ++ status = GET_REG(fh_rtc->regs+FH_RTC_SYNC); ++ status &= 0x2; ++ ++ SET_REG(fh_rtc->regs+FH_RTC_SYNC, status); ++ msleep(30); ++ ++ for (loop_count = 0; ++ loop_count <= SYNC_LOOP_COUNT; ++ loop_count++) { ++ udelay(100); ++ status = GET_REG(fh_rtc->regs+FH_RTC_SYNC); ++ status &= 0x1; ++ if(status == 1) { ++ unsigned int temp; ++ temp = fh_rtc_get_hw_sec_data(TIME_FUNC); ++ rtc_time_to_tm(temp, rtc_tm); ++ RTC_PRINT_DBG("rtc read date:0x%x\n", temp); ++ return 0; ++ } ++ ++ } ++ ++ printk(KERN_INFO "rtc read sync fail!\n"); ++ return -EAGAIN; ++} ++ ++static int fh_rtc_settime(struct device *dev, struct rtc_time *tm) ++{ ++ struct rtc_time rtc_tm_read0; ++ unsigned int status; ++ unsigned int loop_count; ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(pdev); ++ int cnt, ret, read_count = 0; ++ ++ RTC_PRINT_DBG("rtc write %d-%d-%d %d:%d:%d\n", ++ tm->tm_year + 1900, ++ tm->tm_mon + 1, ++ tm->tm_mday, ++ tm->tm_hour, ++ tm->tm_min, ++ tm->tm_sec); ++ ++ SET_REG(fh_rtc->regs + FH_RTC_USER_REG, RTC_MAGIC); ++ msleep(3); ++ ++ for (cnt = 0; cnt < 5; cnt++) { ++ int rewrite_count = 0; ++REWRITE: ++ ret = 0; ++ ++ fh_rtc_set_hw_sec_data(tm, TIME_FUNC); ++ ++ /*spin_lock_irqsave(&rtc_lock, flag);*/ ++ ++ for (loop_count = 0; ++ loop_count <= SYNC_LOOP_COUNT; ++ loop_count++) { ++ udelay(100); ++ ++ status = GET_REG(fh_rtc->regs+FH_RTC_SYNC); ++ status &= 0x2; ++ if (status == 0x2) { ++ printk(KERN_INFO "rtc write loop_count :%d\n", ++ loop_count); ++ if(loop_count > 20) { ++ RTC_PRINT_DBG("error: rewrite: %d, " ++ "rtc write loop_count :%d\n", ++ rewrite_count, ++ loop_count); ++ msleep(3); ++ rewrite_count++; ++ if (rewrite_count < 5) { ++ goto REWRITE; ++ } else { ++ RTC_PRINT_DBG("rtc write retry exceed\n"); ++ msleep(3); ++ break; ++ } ++ } ++ /*spin_unlock_irqrestore(&rtc_lock, flag);*/ ++ msleep(3); ++ break; ++ } ++ } ++ ++ if (loop_count >= SYNC_LOOP_COUNT) { ++ printk(KERN_INFO "rtc write sync fail!\n"); ++ return -EAGAIN; ++ } ++ ++ for (read_count = 0; read_count < 5; read_count++) { ++ fh_rtc_gettime_sync(dev, &rtc_tm_read0); ++ ret += fh_rtc_tm_compare(&rtc_tm_read0, tm); ++ } ++ ++ if (!ret) { ++ return 0; ++ } ++ ++ } ++ ++ return -1; ++} ++ ++static int fh_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_time *rtc_tm = &alrm->time; ++ ++ rtc_time_to_tm(fh_rtc_get_hw_sec_data(ALARM_FUNC), rtc_tm); ++ ++ return 0; ++} ++ ++static int fh_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_time *rtc_tm = &alrm->time; ++ ++ fh_rtc_set_hw_sec_data(rtc_tm, ALARM_FUNC); ++ ++ return 0; ++} ++ ++ ++ ++static int fh_rtc_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(pdev); ++ ++ if (enabled) { ++ fh_rtc_enable_interrupt(fh_rtc->regs, ++ FH_RTC_ISR_SEC_POS | FH_RTC_ISR_ALARM_POS); ++ } ++ else{ ++ ++ fh_rtc_disenable_interrupt(fh_rtc->regs, ++ FH_RTC_ISR_SEC_POS | FH_RTC_ISR_ALARM_POS); ++ } ++ ++ return 0; ++} ++ ++ ++ ++ ++static irqreturn_t fh_rtc_irq(int irq, void *dev_id) ++{ ++ ++ struct fh_rtc_controller *fh_rtc = (struct fh_rtc_controller *)dev_id; ++ unsigned long events = 0; ++ unsigned int isr_status; ++ struct rtc_device *rtc = fh_rtc->rtc; ++ ++ isr_status = fh_rtc_get_enabled_interrupt(fh_rtc->regs); ++ ++ fh_rtc_clear_interrupt_status(fh_rtc->regs, isr_status); ++ ++ if (isr_status & FH_RTC_ISR_SEC_POS) { ++ ++ events |= RTC_IRQF | RTC_UF; ++ } ++ else if(isr_status & FH_RTC_ISR_ALARM_POS){ ++ events |= RTC_IRQF | RTC_AF; ++ } ++ else{ ++ pr_info("rtc unknown isr...\n"); ++ return IRQ_HANDLED; ++ } ++ rtc_update_irq(rtc, 1, events); ++ ++ return IRQ_HANDLED; ++ ++} ++ ++static const struct rtc_class_ops fh_rtcops = { ++ .open = fh_rtc_open, ++ .release = fh_rtc_release, ++ .read_time = fh_rtc_gettime_nosync, ++ .set_time = fh_rtc_settime, ++ .read_alarm = fh_rtc_getalarm, ++ .set_alarm = fh_rtc_setalarm, ++ .alarm_irq_enable = fh_rtc_irq_enable, ++}; ++ ++/*get the read of SADC and adjust RTC clock*/ ++int fh_adjust_rtc(void) ++{ ++ int m, n; /*m:MinuteOffset, n:SecondOffset*/ ++ long T = 25000; ++ int i, j, temp; ++ long Ppm = 0; ++ long value[7]; ++ int flag = 0; ++ long sum = 0; ++ long v; ++ int num; ++ ++ for (i = 0; i < 7; i++) { ++ value[i] = fh_sadc_get_value(fh_rtc->sadc_channel); ++ if(!value[i]) ++ { ++ printk("ERROR: %s, sadc value %lu is incorrect\n", ++ __func__, value[i]); ++ return -EIO; ++ } ++ mdelay(100); ++ } ++ for (i = 0; i < 7; i++) { ++ for (j = i + 1; j < 7; j++) { ++ if (value[j] < value[i]) { ++ temp = value[i]; ++ value[i] = value[j]; ++ value[j] = temp; ++ } ++ } ++ } ++ sum = value[2] + value[3] + value[4]; ++ v = sum / 3; ++ printk("the average value of SADC is:%ld\n", v); ++ if(v >= 3094) { /*if temperature is lower than -40℃,adjust by -40℃*/ ++ Ppm = 1690000; ++ n = Ppm / 305176; ++ Ppm -= 305176 * n; ++ m = Ppm / 5086; ++ printk("SecondOffset is: %d\n", n); ++ printk("MinuteOffset is: %d\n", m); ++ if ((n <= 7) && (m <= 63)) { ++ accelerate_second_rtc(n); ++ accelerate_minute_rtc(m); ++ printk("rtc clock has been adjusted!\n"); ++ } else { ++ printk("beyond range of adjust\n"); ++ } ++ return 0; ++ } ++ if(v < 260) { /*if temperature is higher than 95℃,adjust by 95℃*/ ++ Ppm = 1960000; ++ n = Ppm / 305176; ++ Ppm -= 305176 * n; ++ m = Ppm / 5086; ++ printk("SecondOffset is: %d\n", n); ++ printk("MinuteOffset is: %d\n", m); ++ if ((n <= 7) && (m <= 63)) { ++ accelerate_second_rtc(n); ++ accelerate_minute_rtc(m); ++ printk("rtc clock has been adjusted!\n"); ++ } else { ++ printk("beyond range of adjust\n"); ++ } ++ ++ return 0; ++ } ++ for (i = 0; i < 27; i++) { /*calculate temperature by voltage*/ ++ if ((v >= SadcValue[i]) && (v < SadcValue[i+1])) { ++ T = Temperature1[i] - ((Temperature1[i] - Temperature1[i+1]) * ++ (SadcValue[i] - v) / (SadcValue[i] - SadcValue[i+1])); ++ } else { ++ //printk("the reading of SADC is beyond of voltage range\n"); ++ continue; ++ } ++ } ++ for (i = 0; i < 135; i++) { /*get deviation by temperature*/ ++ if ((T >= Temperature2[i]) && (T < Temperature2[i+1])) { ++ num = i; ++ flag = 1; ++ if ((Temperature2[num+1] - T) <= 500) { ++ T = Temperature2[num + 1]; ++ Ppm = Deviation[num + 1]; ++ } else if ((Temperature2[num+1] - T) > 500) { ++ T = Temperature2[num]; ++ Ppm = Deviation[num]; ++ } ++ printk("current temperature is: %ld\n", T); ++ printk("current deviation of RTC crystal oscillator is: %ld\n", Ppm); ++ } ++ } ++ if (flag == 1) { ++ n = Ppm / 305176; ++ Ppm -= 305176 * n; ++ m = Ppm / 5086; ++ printk("SecondOffset is: %d\n", n); ++ printk("MinuteOffset is: %d\n", m); ++ if ((n <= 7) && (m <= 63)) { ++ accelerate_second_rtc(n); ++ accelerate_minute_rtc(m); ++ printk("rtc clock has been adjusted!\n"); ++ } else { ++ printk("beyond range of adjust\n"); ++ } ++ } ++ return 0; ++} ++ ++long get_rtc_temperature(void) ++{ ++ long T = 0; ++ int i, j, temp; ++ long value[7]; ++ long sum = 0; ++ long v; ++ for (i = 0; i < 7; i++) { ++ value[i] = fh_sadc_get_value(fh_rtc->sadc_channel); ++ if(!value[i]) ++ { ++ printk("ERROR: %s, sadc value %lu is incorrect\n", ++ __func__, value[i]); ++ return -EIO; ++ } ++ mdelay(100); ++ } ++ for (i = 0; i < 7; i++) { ++ for (j = i + 1; j < 7; j++) { ++ if (value[j] < value[i]) { ++ temp = value[i]; ++ value[i] = value[j]; ++ value[j] = temp; ++ } ++ } ++ } ++ sum = value[2] + value[3] + value[4]; ++ v = sum / 3; ++ printk("the average value of SADC is:%ld\n", v); ++ for (i = 0; i < 27; i++) { ++ if ((v >= SadcValue[i]) && (v < SadcValue[i+1])) { ++ T = Temperature1[i] - ((Temperature1[i] - Temperature1[i+1]) * ++ (SadcValue[i] - v) / (SadcValue[i] - SadcValue[i+1])); ++ } else { ++ //printk("the reading of SADC is beyond of voltage range\n"); ++ continue; ++ } ++ } ++ printk("current temperature is: %ld\n", T); ++ return 0; ++} ++ ++void fh_rtc_self_adjustment(struct work_struct *work) ++{ ++ fh_adjust_rtc(); ++ ++ queue_delayed_work(fh_rtc->wq, &fh_rtc->self_adjust, 5000); ++} ++ ++ ++static void create_proc_rtc(struct fh_rtc_controller *rtc); ++static void remove_proc(void); ++static int __devinit fh_rtc_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct resource *ioarea; ++ struct fh_rtc_platform_data * rtc_platform_info; ++ struct rtc_device *rtc; ++ struct resource *res; ++ ++ fh_rtc = kzalloc(sizeof(struct fh_rtc_controller), GFP_KERNEL); ++ if (!fh_rtc) ++ return -ENOMEM; ++ ++ memset(fh_rtc, 0, sizeof(struct fh_rtc_controller)); ++ ++ /* board info below */ ++ rtc_platform_info = (struct fh_rtc_platform_data *)pdev->dev.platform_data; ++ if(rtc_platform_info == NULL){ ++ dev_err(&pdev->dev, "%s, rtc platform error.\n", ++ __func__); ++ err = -ENODEV; ++ goto err_nores; ++ } ++ fh_rtc->base_year = rtc_platform_info->base_year; ++ fh_rtc->base_month = rtc_platform_info->base_month; ++ fh_rtc->base_day = rtc_platform_info->base_day; ++ fh_rtc->sadc_channel = rtc_platform_info->sadc_channel; ++ ++ /* find the IRQs */ ++ fh_rtc->irq = platform_get_irq(pdev, 0); ++ if (fh_rtc->irq < 0) { ++ dev_err(&pdev->dev, "%s, rtc irq error.\n", ++ __func__); ++ err = fh_rtc->irq; ++ goto err_nores; ++ } ++ ++ /* get the memory region */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "failed to get memory region resource\n"); ++ err = -ENOENT; ++ goto err_nores; ++ } ++ ++ fh_rtc->paddr = res->start; ++ ioarea = request_mem_region(res->start, resource_size(res), ++ pdev->name); ++ if(!ioarea) { ++ dev_err(&pdev->dev, "rtc region already claimed\n"); ++ err = -EBUSY; ++ goto err_nores; ++ } ++ ++ fh_rtc->regs = ioremap(res->start, resource_size(res)); ++ if (!fh_rtc->regs) { ++ dev_err(&pdev->dev, "rtc already mapped\n"); ++ err = -EINVAL; ++ goto err_nores; ++ } ++ ++ /* register RTC and exit */ ++ platform_set_drvdata(pdev, fh_rtc); ++ rtc = rtc_device_register(rtc_platform_info->dev_name, &pdev->dev, &fh_rtcops, ++ THIS_MODULE); ++ ++ if (IS_ERR(rtc)) { ++ dev_err(&pdev->dev, "cannot attach rtc\n"); ++ err = PTR_ERR(rtc); ++ goto err_nores; ++ } ++ fh_rtc->rtc = rtc; ++ ++ err = request_irq(fh_rtc->irq , fh_rtc_irq, 0, ++ dev_name(&pdev->dev), fh_rtc); ++ if (err) { ++ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err); ++ goto err_nores; ++ } ++ ++ create_proc_rtc(fh_rtc); ++ ++ SET_REG(fh_rtc->regs + FH_RTC_DEBUG, RTC_PHASE); ++ ++ if(fh_rtc->sadc_channel >= 0) ++ { ++ pr_info("RTC: start self adjustment\n"); ++ fh_rtc->wq = create_workqueue("rtc_wq"); ++ if(!fh_rtc->wq) ++ { ++ dev_err(&pdev->dev, "no memory to create rtc workqueue\n"); ++ return -ENOMEM; ++ } ++ INIT_DELAYED_WORK(&fh_rtc->self_adjust, fh_rtc_self_adjustment); ++ ++ queue_delayed_work(fh_rtc->wq, &fh_rtc->self_adjust, 5000); ++ } ++ ++ err = fh_rtc_exam_magic(); ++ ++ if(err) ++ return -1; ++ ++ ++err_nores: ++ return err; ++ ++ return 0; ++} ++ ++static int __devexit fh_rtc_remove(struct platform_device *dev) ++{ ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(dev); ++ ++ remove_proc(); ++ free_irq(fh_rtc->irq, fh_rtc); ++ rtc_device_unregister(fh_rtc->rtc); ++ ++ iounmap(fh_rtc->regs); ++ platform_set_drvdata(dev, NULL); ++ kfree(fh_rtc); ++ return 0; ++} ++ ++ ++ ++#ifdef CONFIG_PM ++ ++/* RTC Power management control */ ++ ++static int fh_rtc_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int fh_rtc_resume(struct platform_device *pdev) ++{ ++ return 0; ++} ++#else ++#define fh_rtc_suspend NULL ++#define fh_rtc_resume NULL ++#endif ++ ++ ++ ++static struct platform_driver fh_rtc_driver = { ++ .probe = fh_rtc_probe, ++ .remove = __devexit_p(fh_rtc_remove), ++ .suspend = fh_rtc_suspend, ++ .resume = fh_rtc_resume, ++ .driver = { ++ .name = "fh_rtc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++ ++static int __init fh_rtc_init(void) { ++ ++ return platform_driver_register(&fh_rtc_driver); ++} ++ ++static void __exit fh_rtc_exit(void) { ++ platform_driver_unregister(&fh_rtc_driver); ++} ++ ++static void del_char(char *str, char ch) ++{ ++ char *p = str; ++ char *q = str; ++ while (*q) { ++ if (*q != ch) { ++ *p++ = *q; ++ } ++ q++; ++ } ++ *p = '\0'; ++} ++ ++ssize_t proc_read(char *page, char **start, off_t off, int count, ++ int *eof, struct fh_rtc_controller *data) { ++ ssize_t len = 0; ++ ++ printk(KERN_INFO "------------- dump register -------------\n"); ++ printk(KERN_INFO "cnt:0x%x\n",fh_rtc_get_time(data->regs) ); ++ printk(KERN_INFO "offset:0x%x\n",fh_rtc_get_offset(data->regs)); ++ printk(KERN_INFO "fail:0x%x\n",fh_rtc_get_power_fail(data->regs)); ++ printk(KERN_INFO "alarm_cnt:0x%x\n",fh_rtc_get_alarm_time(data->regs)); ++ printk(KERN_INFO "int stat:0x%x\n",fh_rtc_get_int_status(data->regs)); ++ printk(KERN_INFO "int en:0x%x\n",fh_rtc_get_enabled_interrupt(data->regs)); ++ printk(KERN_INFO "sync:0x%x\n",fh_rtc_get_sync(data->regs)); ++ printk(KERN_INFO "debug:0x%x\n",fh_rtc_get_debug(data->regs)); ++ printk(KERN_INFO "-------------------------------------------\n"); ++ ++ return len; ++} ++ ++ ++static ssize_t fh_rtc_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off) ++{ ++ char message[32] = {0}; ++ char * const delim = ","; ++ char *cur = message, *power_str; ++ int power; ++ len = (len > 32) ? 32 : len; ++ if (copy_from_user(message, buf, len)) ++ return -EFAULT; ++ power_str = strsep(&cur, delim); ++ if (!power_str) { ++ pr_err("%s: ERROR: parameter is empty\n", __func__); ++ return -EINVAL; ++ } else { ++ del_char(power_str, ' '); ++ del_char(power_str, '\n'); ++ power = (unsigned int)simple_strtoul(power_str, NULL, 10); ++ if (power < 0) { ++ pr_err("%s: ERROR: parameter is incorrect\n", __func__); ++ return -EINVAL; ++ } ++ printk(KERN_INFO "the diff between rtc and sys is %d\n", ++ power); ++ if (power == 0) ++ fh_adjust_rtc(); ++ else if (power == 1) ++ get_rtc_temperature(); ++ } ++ return len; ++} ++ ++static void create_proc_rtc(struct fh_rtc_controller *rtc) ++{ ++ fh_rtc->proc_rtc_entry = ++ create_proc_entry(FH_RTC_PROC_FILE, ++ S_IRUGO, NULL); ++ ++ if (!fh_rtc->proc_rtc_entry) { ++ printk(KERN_ERR"create proc failed\n"); ++ } else { ++ fh_rtc->proc_rtc_entry->read_proc = ++ (read_proc_t *)proc_read; ++ fh_rtc->proc_rtc_entry->write_proc = ++ (write_proc_t *)fh_rtc_proc_write; ++ fh_rtc->proc_rtc_entry->data = rtc; ++ } ++} ++ ++static void remove_proc(void) { ++ remove_proc_entry(FH_RTC_PROC_FILE, NULL); ++} ++ ++module_init(fh_rtc_init); ++module_exit(fh_rtc_exit); ++ ++MODULE_DESCRIPTION("FH SOC RTC Driver"); ++MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:fh-rtc"); +diff --git a/drivers/rtc/rtc-fh_v2.c b/drivers/rtc/rtc-fh_v2.c +new file mode 100644 +index 00000000..1967c2e4 +--- /dev/null ++++ b/drivers/rtc/rtc-fh_v2.c +@@ -0,0 +1,1385 @@ ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/string.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/interrupt.h> ++#include <linux/rtc.h> ++#include <linux/bcd.h> ++#include <linux/clk.h> ++#include <linux/log2.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <mach/fh_rtc_v2.h> ++#include <mach/fh_sadc.h> ++#include <linux/delay.h> ++#include <linux/proc_fs.h> ++#include <linux/workqueue.h> ++#include <linux/irqreturn.h> ++/* #define FH_RTC_DEBUG_PRINT */ ++ ++#ifdef FH_RTC_DEBUG_PRINT ++#define RTC_PRINT_DBG(fmt, args...) \ ++ do { ++ printk(KERN_INFO "[FH_RTC_DEBUG]: "); \ ++ printk(fmt, ## args) ++ } while (0) ++#else ++#define RTC_PRINT_DBG(fmt, args...) do { } while (0) ++#endif ++ ++unsigned int rtc_use_efuse_viture_addr; ++ ++#ifdef CONFIG_USE_TSENSOR ++#define USE_TSENSOR ++#ifdef CONFIG_USE_TSENSOR_OFFSET ++#define USE_TSENSOR_OFFSET ++#endif ++#endif ++/* ++#define USE_TSENSOR_OFFSET ++#define USE_TSENSOR ++*/ ++/* #define USE_DEBUG_REGISTER */ ++ ++struct fh_rtc_controller { ++ void * __iomem regs; ++ unsigned int v_addr; ++ unsigned int irq; ++ unsigned int paddr; ++ unsigned int base_year; ++ unsigned int base_month; ++ unsigned int base_day; ++ struct rtc_device *rtc; ++ struct clk *clk; ++ struct proc_dir_entry *proc_rtc_entry; ++ int sadc_channel; ++ ++ struct workqueue_struct *wq; ++ struct delayed_work self_adjust; ++}; ++struct fh_rtc_core_int_status { ++ unsigned int core_int_en; ++ unsigned int core_int_status; ++}; ++struct fh_rtc_controller *fh_rtc; ++struct fh_rtc_core_int_status fh_core_int; ++enum { ++ ++ TIME_FUNC = 0, ALARM_FUNC, ++ ++}; ++#ifdef USE_TSENSOR ++#define LUT_COF 58 ++#define LUT_OFFSET 0xff ++#define TSENSOR_OFFSET 55 ++#define TSENSOR_COF 58 ++#define TSENSOR_STEP 3 ++#define TEMP_CP 25 ++#define TSENSOR_CP_DEFAULT_OUT 0x993 ++ ++unsigned int TSENSOR_LUT[12] = {0x1b1e2023, ++ 0x11131618, ++ 0x090b0d0f, ++ 0x03040607, ++ 0x00010202, ++ 0x01000000, ++ 0x04030201, ++ 0x0b090706, ++ 0x1713100e, ++ 0x27221e1a, ++ 0x3e37322c, ++ 0x5b534c44}; ++#endif ++ ++ ++ ++static int fh_rtc_get_core(unsigned int base_addr, unsigned int reg_num); ++#ifdef USE_TSENSOR_OFFSET ++#define RTC_USE_EFUSE_CMD (0x0000) ++#define RTC_USE_EFUSE_CONFIG (0x0004) ++#define RTC_USE_EFUSE_MATCH_KEY (0x0008) ++#define RTC_USE_EFUSE_TIMING0 (0x000C) ++#define RTC_USE_EFUSE_TIMING1 (0x0010) ++#define RTC_USE_EFUSE_TIMING2 (0x0014) ++#define RTC_USE_EFUSE_TIMING3 (0x0018) ++#define RTC_USE_EFUSE_TIMING4 (0x001C) ++#define RTC_USE_EFUSE_TIMING5 (0x0020) ++#define RTC_USE_EFUSE_TIMING6 (0x0024) ++#define RTC_USE_EFUSE_DOUT (0x0028) ++#define RTC_USE_EFUSE_STATUS0 (0x002C) ++#define RTC_USE_EFUSE_STATUS1 (0x0030) ++#define RTC_USE_EFUSE_STATUS2 (0x0034) ++#define RTC_USE_EFUSE_STATUS3 (0x0038) ++#define RTC_USE_EFUSE_STATUS4 (0x003C) ++#define RTC_USE_EFUSE_MEM_INFO (0x0100) ++static int tsensor_detect_complete(unsigned int i) ++{ ++ unsigned int rdata; ++ unsigned int loop_count; ++ ++ rdata = 0 ++ loop_count = 0; ++ while ((rdata&(1<<i)) != 1<<i) { ++ rdata = readl(rtc_use_efuse_viture_addr + ++ RTC_USE_EFUSE_STATUS3); ++ ++ if (rdata != 0x0) { ++ ++ pr_info("detect complet status 0x%x\n", rdata); ++ break; ++ } ++ rdata = readl(rtc_use_efuse_viture_addr + ++ RTC_USE_EFUSE_STATUS0); ++ loop_count++; ++ usleep_range(1000, 2000); ++ if (loop_count >= 100) { ++ ++ pr_err("RTC: can't detect completed!\n"); ++ return -EBUSY; ++ } ++ } ++ ++ return 0; ++} ++int tsensor_load_usrcmd(void) ++{ ++ unsigned rdata; ++ int status; ++ ++ status = 0; ++ rdata = readl(rtc_use_efuse_viture_addr + RTC_USE_EFUSE_STATUS0); ++ if ((rdata&(1<<31)) != 1<<31) { ++ writel(0x1, rtc_use_efuse_viture_addr+RTC_USE_EFUSE_CMD); ++ status = tsensor_detect_complete(1); ++ if (status < 0) { ++ pr_err("RTC:load usrcmd error!\n"); ++ return -EBUSY; ++ } ++ ++ rdata = readl(rtc_use_efuse_viture_addr+RTC_USE_EFUSE_DOUT); ++ } ++ ++ return 0; ++} ++int tsensor_efuse_read(int entry) ++{ ++ unsigned rdata; ++ int status = 0; ++ ++ status = tsensor_load_usrcmd(); ++ if (status < 0) { ++ pr_err("RTC:tsensor_efuse_read load usrcmd error!\n"); ++ return -EBUSY; ++ } ++ writel((entry<<4)+0x3, rtc_use_efuse_viture_addr+RTC_USE_EFUSE_CMD); ++ status = 0; ++ status = tsensor_detect_complete(3); ++ if (status < 0) { ++ pr_err("RTC:tsensor_efuse_read load data error!\n"); ++ return -EBUSY; ++ } ++ rdata = readl(rtc_use_efuse_viture_addr+RTC_USE_EFUSE_DOUT); ++ ++ return rdata; ++} ++int tsensor_adjust_lut(void) ++{ ++ unsigned int tsensor_init_data; ++ unsigned int tsensor_12bit; ++ unsigned int low_data, high_data; ++ int temp_diff; ++ int tsensor_out_value_diff; ++ ++ low_data = tsensor_efuse_read(60); ++ high_data = tsensor_efuse_read(61); ++ tsensor_init_data = (high_data<<8)|low_data; ++ tsensor_12bit = tsensor_init_data&0xfff; ++ tsensor_out_value_diff = tsensor_12bit - TSENSOR_CP_DEFAULT_OUT; ++ ++ temp_diff = tsensor_out_value_diff*LUT_COF/4096; ++ ++ return temp_diff; ++} ++#endif ++#ifdef USE_TSENSOR ++static int fh_rtc_temp_cfg_coef_offset(unsigned int coef, unsigned int offset); ++static int fh_rtc_temp_cfg_thl_thh(unsigned int thl, unsigned int thh); ++#if 0 ++static int fh_rtc_temp_cfg_update_time(unsigned int time); ++#endif ++#endif ++static int fh_rtc_set_core(unsigned int base_addr, unsigned int reg_num,\ ++ unsigned int value); ++#ifdef USE_TSENSOR ++static void rtc_adjust(void) ++{ ++ int i; ++ int offset_index; ++ char offset_lut[48]; ++ ++ for (i = 0; i < 12; i++) ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET_LUT+(i<<4), ++ TSENSOR_LUT[i]); ++ ++ for (i = 0; i < 12; i++) { ++ offset_lut[i*4] = TSENSOR_LUT[i]&0xff; ++ offset_lut[i*4+1] = (TSENSOR_LUT[i]>>4); ++ offset_lut[i*4+2] = (TSENSOR_LUT[i]>>8); ++ offset_lut[i*4+3] = (TSENSOR_LUT[i]>>12); ++ } ++ ++ offset_index = 0; ++ for (i = 0; i < 46; i++) { ++ if (offset_lut[i] > offset_lut[i+1]) ++ offset_index = i + 1; ++ else ++ offset_lut[i+1] = offset_lut[i]; ++ } ++ ++#ifdef USE_TSENSOR_OFFSET ++ i = tsensor_adjust_lut(); ++ if ((i < 0) || (i > 5)) ++ i = 0; ++ fh_rtc_temp_cfg_coef_offset(LUT_COF, LUT_OFFSET-i); ++ pr_info("tsensor diff value : %d\n", i); ++#else ++ fh_rtc_temp_cfg_coef_offset(LUT_COF, LUT_OFFSET); ++#endif ++ fh_rtc_temp_cfg_thl_thh(0, 47); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET, ++ (offset_index<<2) | (offset_index<<10)| ++ OFFSET_BK_EN|OFFSET_BK_AUTO); ++} ++#endif ++ ++static int fh_rtc_core_idle(unsigned int base_addr) ++{ ++ unsigned int status; ++ ++ status = GET_REG(base_addr+FH_RTC_INT_STATUS); ++ if (status & FH_RTC_INT_STATUS_CORE_IDLE) ++ return 0; ++ else ++ return -1; ++} ++ ++static int fh_rtc_core_wr(unsigned int base_addr) ++{ ++ int reg; ++ ++ reg = GET_REG(base_addr+FH_RTC_INT_STATUS); ++ reg &= (~FH_RTC_INT_STATUS_CORE_IDLE); ++ SET_REG(base_addr+FH_RTC_INT_STATUS, reg); ++ ++ return 0; ++} ++ ++static int fh_rtc_get_time(unsigned int base_addr) ++{ ++ int reg, count, status; ++ ++ if (fh_rtc_core_idle(base_addr) < 0) { ++ pr_info("fh rtc get time error\n"); ++ return -1; ++ } ++ fh_rtc_core_wr(base_addr); ++ SET_REG(base_addr+FH_RTC_CMD, RTC_READ); ++ for (count = 0; count < 250; count++) { ++ status = fh_rtc_core_idle(base_addr); ++ if (status == 0) { ++ reg = GET_REG(base_addr+FH_RTC_RD_DATA); ++ return reg; ++ } ++ udelay(100); ++ ++ } ++ pr_info("rtc core busy can't get time\n"); ++ ++ return -1; ++} ++ ++static int fh_rtc_set_core(unsigned int base_addr, unsigned int reg_num,\ ++ unsigned int value) ++{ ++ int count, status; ++ ++ if (fh_rtc_core_idle(base_addr) < 0) { ++ pr_info("rtc get time:rtc core busy\n"); ++ return -1; ++ } ++ fh_rtc_core_wr(base_addr); ++ ++ SET_REG(base_addr+FH_RTC_WR_DATA, value); ++ SET_REG(base_addr+FH_RTC_CMD, reg_num|RTC_WRITE); ++ for (count = 0; count < 250; count++) { ++ status = fh_rtc_core_idle(base_addr); ++ if (status == 0) ++ return 0; ++ ++ udelay(100); ++ ++ } ++ pr_info("rtc SET CORE REG TIMEOUT\n"); ++ ++ return -1; ++} ++ ++static int fh_rtc_get_core(unsigned int base_addr, unsigned int reg_num) ++{ ++ int reg, count, status; ++ ++ if (fh_rtc_core_idle(base_addr) < 0) { ++ pr_info("rtc get time:rtc core busy %d\n", __LINE__); ++ return -1; ++ } ++ fh_rtc_core_wr(base_addr); ++ SET_REG(base_addr+FH_RTC_CMD, reg_num|RTC_READ); ++ for (count = 0; count < 150; count++) { ++ status = fh_rtc_core_idle(base_addr); ++ if (status == 0) { ++ reg = GET_REG(base_addr+FH_RTC_RD_DATA); ++ return reg; ++ } ++ udelay(100); ++ ++ } ++ pr_info("rtc GET CORE REG TIMEOUT line %d\n", __LINE__); ++ ++ return -1; ++} ++ ++static int fh_rtc_get_temp(unsigned int base_addr) ++{ ++ int reg, count, status; ++ ++ if (fh_rtc_core_idle(base_addr) < 0) { ++ pr_info("rtc get time:rtc core busy %d\n", __LINE__); ++ ++ return -1; ++ } ++ fh_rtc_core_wr(base_addr); ++ SET_REG(base_addr+FH_RTC_CMD, RTC_TEMP); ++ for (count = 0; count < 150; count++) { ++ status = fh_rtc_core_idle(base_addr); ++ if (status == 0) { ++ reg = GET_REG(base_addr+FH_RTC_RD_DATA); ++ ++ return reg; ++ } ++ udelay(100); ++ ++ } ++ pr_info("rtc GET CORE REG TIMEOUT line %d\n", __LINE__); ++ ++ return -1; ++} ++ ++static int fh_rtc_set_time(unsigned int base_addr, unsigned int value) ++{ ++ int count; ++ ++ if (fh_rtc_core_idle(base_addr) < 0) { ++ pr_info("set time :rtc core busy\n"); ++ ++ return -1; ++ } ++ fh_rtc_core_wr(base_addr); ++ SET_REG(base_addr+FH_RTC_WR_DATA, value); ++ SET_REG(base_addr+FH_RTC_CMD, RTC_WRITE); ++ for (count = 0; count < 150; count++) { ++ if (fh_rtc_core_idle(base_addr) == 0) ++ return 0; ++ ++ udelay(100); ++ } ++ pr_info("rtc core busy can't set time\n"); ++ ++ return -1; ++} ++#ifdef DRIVER_TEST ++static int fh_rtc_set_time_first(unsigned int base_addr, unsigned int value) ++{ ++ ++ SET_REG(base_addr+FH_RTC_WR_DATA, value); ++ SET_REG(base_addr+FH_RTC_CMD, RTC_WRITE); ++ ++} ++#endif ++ ++static int fh_rtc_alarm_enable_interrupt(unsigned int base_addr) ++{ ++ int status; ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ status & (~FH_RTC_ISR_ALARM_POS)); ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN, ++ (status | FH_RTC_CORE_INT_EN_ALM_INT)); ++ ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, status& ++ (~FH_RTC_INT_STATUS_CORE)); ++ ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_EN); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, status & ++ (~FH_RTC_INT_CORE_INT_ERR_MASK)); ++ return 0; ++} ++ ++static int fh_rtc_alarm_disable_interrupt(unsigned int base_addr, ++ unsigned int value) ++{ ++ int rtc_core_status; ++ ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN, (rtc_core_status & (~FH_RTC_CORE_INT_EN_ALM_INT))); ++ ++ return 0; ++} ++ ++static int fh_rtc_set_alarm_time(unsigned int base_addr, unsigned int value) ++{ ++ int status; ++ ++#ifdef USE_DEBUG_REGISTER ++ int rtc_core_status, cys_count; ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_COUNTER); ++ if (rtc_core_status > value) { ++ pr_info("alarm time > now time\n"); ++ return -ETIME; ++ } ++#endif ++ status = fh_rtc_set_core(base_addr, ++ FH_RTC_CMD_ALARM_CFG, value); ++ if (status < 0) { ++ pr_info("set alarm time failed\n"); ++ ++ return -1; ++ } ++#ifdef USE_DEBUG_REGISTER ++ if (rtc_core_status == value) { ++ cys_count = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_DEBUG); ++ if (cys_count > 0x3e00) ++ return -ETIME; ++ } ++#endif ++ return 0; ++} ++ ++static int fh_rtc_get_alarm_time(unsigned int base_addr) ++{ ++ int data; ++ ++ data = fh_rtc_get_core(base_addr, FH_RTC_CMD_ALARM_CFG); ++ ++ return data; ++} ++static unsigned int fh_rtc_get_hw_sec_data(unsigned int func_switch) ++{ ++ ++ unsigned int ret_sec, raw_value, sec_value; ++ unsigned int min_value, hour_value, day_value; ++ ++ if (func_switch == TIME_FUNC) ++ raw_value = fh_rtc_get_time((unsigned int)fh_rtc->regs); ++ else ++ raw_value = fh_rtc_get_alarm_time((unsigned int)fh_rtc->regs); ++ ++ sec_value = FH_GET_RTC_SEC(raw_value); ++ min_value = FH_GET_RTC_MIN(raw_value); ++ hour_value = FH_GET_RTC_HOUR(raw_value); ++ day_value = FH_GET_RTC_DAY(raw_value); ++ ret_sec = (day_value * 86400) + (hour_value * 3600) + (min_value * 60)\ ++ + sec_value; ++ ++ return ret_sec; ++ ++} ++ ++#ifdef DRIVER_TEST ++#define TEMP_DATA 0x203 ++static unsigned int fh_rtc_get_tmp(void) ++{ ++ unsigned int value; ++ value = GET_REG((unsigned int)fh_rtc->regs + FH_RTC_CMD_TEMP_INFO); ++ return value; ++} ++static void fh_rtc_tmp_en(void) ++{ ++ fh_rtc_set_core((unsigned int)fh_rtc->regs, FH_RTC_CMD_OFFSET, ++ TEMP_DATA); ++} ++#endif ++ ++static int fh_rtc_set_hw_sec_data(struct rtc_time *rtc_tm, ++ unsigned int func_switch) ++{ ++ ++ unsigned int raw_value, sec_value, min_value; ++ unsigned int hour_value, day_value; ++ unsigned long now; ++ int status; ++ ++ if (func_switch == ALARM_FUNC) { ++ rtc_tm_to_time(rtc_tm, &now); ++ now--; ++ rtc_time_to_tm(now, rtc_tm); ++ } ++ ++ day_value = rtc_year_days(rtc_tm->tm_mday, rtc_tm->tm_mon, ++ rtc_tm->tm_year + 1900); ++ day_value += (rtc_tm->tm_year - 70) ++ * 365 + ELAPSED_LEAP_YEARS(rtc_tm->tm_year); ++ ++ hour_value = rtc_tm->tm_hour; ++ min_value = rtc_tm->tm_min; ++ sec_value = rtc_tm->tm_sec; ++ ++ raw_value = (day_value << DAY_BIT_START) | \ ++ (hour_value << HOUR_BIT_START)\ ++ | (min_value << MIN_BIT_START) | \ ++ (sec_value << SEC_BIT_START); ++ ++ if (func_switch == TIME_FUNC) { ++ fh_rtc_set_time((unsigned int)fh_rtc->regs, raw_value); ++ return 0; ++ } else { ++ status = fh_rtc_set_alarm_time((unsigned int)fh_rtc->regs, ++ raw_value); ++ return status; ++ } ++} ++ ++static int fh_rtc_open(struct device *dev) ++{ ++ return 0; ++} ++ ++static void fh_rtc_release(struct device *dev) ++{ ++ return; ++} ++ ++#ifdef DRIVER_TEST ++static int fh_rtc_tm_compare(struct rtc_time *tm0, struct rtc_time *tm1) ++{ ++ unsigned long read = 0, write = 0; ++ ++ rtc_tm_to_time(tm0, &read); ++ rtc_tm_to_time(tm1, &write); ++ ++ if (write > read || write < read - 2) { ++ RTC_PRINT_DBG( ++ "ERROR: read(%d-%d-%d %d:%d:%d) vs "\ ++ "write(%d-%d-%d %d:%d:%d)\n",\ ++ tm0->tm_year + 1900, tm0->tm_mon + 1, \ ++ tm0->tm_mday,\ ++ tm0->tm_hour, tm0->tm_min, \ ++ tm0->tm_sec, tm1->tm_year + 1900,\ ++ tm1->tm_mon + 1, tm1->tm_mday, \ ++ tm1->tm_hour, tm1->tm_min,\ ++ tm1->tm_sec); ++ ++ return -1; ++ } ++ ++ return 0; ++} ++#endif ++static int fh_rtc_gettime_nosync(struct device *dev, struct rtc_time *rtc_tm) ++{ ++ unsigned int temp; ++ ++ temp = fh_rtc_get_hw_sec_data(TIME_FUNC); ++ rtc_time_to_tm(temp, rtc_tm); ++ RTC_PRINT_DBG("rtc read date:0x%x\n", temp); ++ ++ return 0; ++} ++ ++static int fh_rtc_settime(struct device *dev, struct rtc_time *tm) ++{ ++ RTC_PRINT_DBG("rtc write %d-%d-%d %d:%d:%d\n", tm->tm_year + 1900, ++ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, \ ++ tm->tm_min, tm->tm_sec); ++ ++ fh_rtc_set_hw_sec_data(tm, TIME_FUNC); ++ ++ return 0; ++} ++ ++static int fh_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_time *rtc_tm = &alrm->time; ++ ++ rtc_time_to_tm(fh_rtc_get_hw_sec_data(ALARM_FUNC), rtc_tm); ++ ++ return 0; ++} ++ ++static int fh_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct rtc_time *rtc_tm = &alrm->time; ++ int status; ++ ++ status = fh_rtc_set_hw_sec_data(rtc_tm, ALARM_FUNC); ++ if (status) ++ return status; ++ if (alrm->enabled) ++ fh_rtc_alarm_enable_interrupt(fh_rtc->v_addr); ++ else ++ fh_rtc_alarm_disable_interrupt(fh_rtc->v_addr, ++ FH_RTC_ISR_ALARM_POS); ++ return 0; ++} ++ ++#ifdef DRIVER_TEST ++static int dump_interrput_status(unsigned int base_addr) ++{ ++ int status; ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ pr_info("core int status : %x\n", status); ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN); ++ pr_info("core int en : %x\n", status); ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS); ++ pr_info("wrapper int status : 0x%x\n", status); ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_EN); ++ pr_info("wrapper int en : 0x%x\n", status); ++ ++ return 0; ++} ++#endif ++ ++static int fh_rtc_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(pdev); ++ int status; ++ ++ if (enabled) { ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ status & (~FH_RTC_ISR_ALARM_POS)); ++ ++ status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN, ++ (status | FH_RTC_CORE_INT_EN_ALM_INT)); ++ ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, status& ++ (~FH_RTC_INT_STATUS_CORE)); ++ ++ status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_EN); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, status & ++ (~FH_RTC_INT_CORE_INT_ERR_MASK)); ++ ++ } else ++ fh_rtc_alarm_disable_interrupt(fh_rtc->v_addr, ++ FH_RTC_ISR_ALARM_POS); ++ ++ return 0; ++} ++ ++static void fh_rtc_clear_interrupt_status(unsigned int base_addr, ++ unsigned int value) ++{ ++ unsigned int int_en, int_status; ++ ++ int_en = GET_REG((unsigned int)base_addr+FH_RTC_INT_EN); ++ int_en &= 0x7f; ++ SET_REG(base_addr+FH_RTC_INT_EN,\ ++ (((value)\ ++ & 0x7f)<<16)|int_en|\ ++ FH_RTC_INT_CORE_IDLE_ERR_MASK|FH_RTC_INT_CORE_INT_ERR_MASK); ++ int_status = value & 0x10a0; ++ SET_REG(base_addr+FH_RTC_INT_STATUS, int_status); ++} ++static struct work_struct rtc_int_wq; ++ ++static void rtc_core_int_handler(struct work_struct *work) ++{ ++ unsigned long events = 0; ++ int rtc_int_status, rtc_int_en; ++ unsigned int wr_int_status; ++ unsigned int wr_int_status_clr; ++ int rtc_core_status; ++ struct rtc_device *rtc = fh_rtc->rtc; ++ ++ /* get core interrupt status */ ++ rtc_int_en = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN); ++ wr_int_status_clr = GET_REG(fh_rtc->v_addr + ++ FH_RTC_INT_STATUS); ++ rtc_int_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ /* get core interrupt failed */ ++ if (rtc_int_en < 0) { ++ pr_info("can't get core int en\n"); ++ return; ++ } ++ if (rtc_int_status < 0) { ++ pr_info("can't get core int status\n"); ++ return; ++ } ++ /* do interrupt */ ++ if (rtc_int_en & rtc_int_status & FH_RTC_ISR_ALARM_POS) { ++ pr_info("ALARM INT\n"); ++ /* clear core alarm interrupt status */ ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & ++ (~FH_RTC_ISR_ALARM_POS)); ++ /* eanble interrupt */ ++ wr_int_status = GET_REG(fh_rtc->v_addr+ ++ FH_RTC_INT_EN); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN,\ ++ wr_int_status& ++ (FH_RTC_INT_CORE_INT_ALL_COV)); ++ /* updata to RTC CORE alarm work */ ++ events |= RTC_IRQF | RTC_AF; ++ rtc_update_irq(rtc, 1, events); ++ ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_SEC_POS) { ++ ++ pr_info("FH_RTC_ISR_SEC_POS\n"); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & (~FH_RTC_ISR_SEC_POS)); ++ wr_int_status = GET_REG(fh_rtc->v_addr+ ++ FH_RTC_INT_EN); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN,\ ++ wr_int_status& ++ (FH_RTC_INT_CORE_INT_STATUS_COV)); ++ ++ events |= RTC_IRQF | RTC_UF; ++ rtc_update_irq(rtc, 1, events); ++ ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_MIN_POS) { ++ ++ pr_info("FH_RTC_ISR_MIN_POS\n"); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & (~FH_RTC_ISR_MIN_POS)); ++ wr_int_status = GET_REG(fh_rtc->regs+ ++ FH_RTC_INT_EN); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, ++ wr_int_status&\ ++ (FH_RTC_INT_CORE_INT_ERR_MASK_COV)); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, ++ wr_int_status_clr&\ ++ (FH_RTC_INT_CORE_INT_STATUS_COV)); ++ ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_HOUR_POS) { ++ pr_info("FH_RTC_ISR_HOUR_POS\n"); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & (~FH_RTC_ISR_HOUR_POS)); ++ wr_int_status = GET_REG(fh_rtc->v_addr+ ++ FH_RTC_INT_EN); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, ++ wr_int_status&\ ++ (FH_RTC_INT_CORE_INT_ERR_MASK_COV)); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, ++ wr_int_status_clr&\ ++ (FH_RTC_INT_CORE_INT_STATUS_COV)); ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_DAY_POS) { ++ pr_info("FH_RTC_ISR_DAY_POS\n"); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & (~FH_RTC_ISR_DAY_POS)); ++ wr_int_status = GET_REG(fh_rtc->v_addr+ ++ FH_RTC_INT_EN); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, ++ wr_int_status&\ ++ (FH_RTC_INT_CORE_INT_ERR_MASK_COV)); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, ++ wr_int_status_clr&\ ++ (FH_RTC_INT_CORE_INT_STATUS_COV)); ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_POWERFAIL_POS) { ++ pr_info("FH_RTC_ISR_POWERFAIL_POS\n"); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & ++ (~FH_RTC_ISR_POWERFAIL_POS)); ++ ++ wr_int_status = GET_REG(fh_rtc->v_addr+ ++ FH_RTC_INT_EN); ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, ++ wr_int_status_clr&\ ++ (FH_RTC_INT_CORE_INT_STATUS_COV)); ++ ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_RX_CRC_ERR_INT) { ++ pr_info("FH_RTC_ISR_RX_CRC_ERR_INT\n"); ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_RX_COM_ERR_INT) { ++ pr_info("FH_RTC_ISR_RX_COM_ERR_INT\n"); ++ } else if (rtc_int_en & rtc_int_status & FH_RTC_LEN_ERR_INT) { ++ pr_info("FH_RTC_LEN_ERR_INT\n"); ++ } else { ++ pr_info("unexpect isr\n"); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, rtc_int_en & (~rtc_int_status)); ++ } ++ ++ ++} ++ ++static irqreturn_t fh_rtc_irq(int irq, void *dev_id) ++{ ++ ++ struct fh_rtc_controller *fh_rtc = (struct fh_rtc_controller *) dev_id; ++ unsigned int isr_status; ++ /* ++ * 1.clear wrapper interrput status ++ * 2.mask core int ++ * 3.schedule interrput work ++ */ ++ isr_status = GET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS); ++ fh_rtc_clear_interrupt_status(fh_rtc->v_addr, isr_status); ++ ++ if (isr_status & FH_RTC_INT_STATUS_CORE) { ++ schedule_work(&rtc_int_wq); ++ } else if (isr_status & FH_RTC_INT_STATUS_RX_CRC_ERR) ++ pr_info("FH_RTC_INT_STATUS_RX_CRC_ERR\n"); ++ else if (isr_status & FH_RTC_INT_STATUS_RX_COM_ERR) { ++ pr_info("FH_RTC_INT_STATUS_RX_COM_ERR\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_RX_LEN_ERR) { ++ pr_info("FH_RTC_INT_STATUS_RX_LEN_ERR\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_CNT_THL) { ++ pr_info("FH_RTC_INT_STATUS_CNT_THL\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_CNT_THH) { ++ pr_info("FH_RTC_INT_STATUS_CNT_THH\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_CORE_IDLE) { ++ pr_info("FH_RTC_INT_STATUS_CORE_IDLE\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_WRAPPER_BUSY) { ++ pr_info("FH_RTC_INT_STATUS_WRAPPER_BUSY\n"); ++ } else if (isr_status & FH_RTC_INT_STATUS_CORE_BUSY) { ++ pr_info("FH_RTC_INT_STATUS_CORE_BUSY\n"); ++ } else { ++ pr_info("rtc unknown isr...\n"); ++ ++ return IRQ_NONE; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct rtc_class_ops fh_rtcops = { ++ .open = fh_rtc_open, ++ .release = fh_rtc_release, ++ .read_time = fh_rtc_gettime_nosync, ++ .set_time = fh_rtc_settime, ++ .read_alarm = fh_rtc_getalarm, ++ .set_alarm = fh_rtc_setalarm, ++ .alarm_irq_enable = fh_rtc_irq_enable, ++}; ++ ++/*get the read of SADC and adjust RTC clock*/ ++static struct miscdevice fh_rtc_misc; ++static void create_proc_rtc(struct fh_rtc_controller *rtc); ++static void remove_proc(void); ++static int fh_rtc_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct fh_rtc_platform_data *rtc_platform_info; ++ struct rtc_device *rtc; ++ struct resource *res; ++ int rtc_core_status; ++ ++ /* malloc mem region */ ++ fh_rtc = kzalloc(sizeof(struct fh_rtc_controller), GFP_KERNEL); ++ if (!fh_rtc) ++ return -ENOMEM; ++ ++ memset(fh_rtc, 0, sizeof(struct fh_rtc_controller)); ++ ++ /* board info below */ ++ rtc_platform_info = (struct fh_rtc_platform_data *)\ ++ pdev->dev.platform_data; ++ if (rtc_platform_info == NULL) { ++ dev_err(&pdev->dev, "%s, rtc platform error.\n", ++ __func__); ++ err = -ENODEV; ++ goto err_nores; ++ } ++ fh_rtc->base_year = rtc_platform_info->base_year; ++ fh_rtc->base_month = rtc_platform_info->base_month; ++ fh_rtc->base_day = rtc_platform_info->base_day; ++ fh_rtc->sadc_channel = rtc_platform_info->sadc_channel; ++ ++ /* find the IRQs */ ++ fh_rtc->irq = platform_get_irq(pdev, 0); ++ if (fh_rtc->irq < 0) { ++ dev_err(&pdev->dev, "%s, rtc irq error.\n", ++ __func__); ++ err = fh_rtc->irq; ++ goto err_nores; ++ } ++ ++ /* get the memory region */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "failed to get memory region resource\n"); ++ err = -ENOENT; ++ goto err_nores; ++ } ++ ++ fh_rtc->paddr = res->start; ++ ++ fh_rtc->regs = ioremap(res->start, resource_size(res)); ++ fh_rtc->v_addr = (unsigned int)fh_rtc->regs; ++ if (!fh_rtc->regs) { ++ dev_err(&pdev->dev, "rtc already mapped\n"); ++ err = -EINVAL; ++ goto err_nores; ++ } ++ ++ fh_rtc->clk = clk_get(&pdev->dev, "rtc_pclk_gate"); ++ ++ if (IS_ERR(fh_rtc->clk)) ++ printk(KERN_INFO "cannot get rtc_pclk\n"); ++ else ++ clk_enable(fh_rtc->clk); ++ ++ /* efuse mem map */ ++ rtc_use_efuse_viture_addr = (unsigned int)ioremap(EFUSE_REG_BASE, ++ resource_size(res)); ++ ++ /* init int status */ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_EN, ++ FH_RTC_INT_CORE_INT_ERR_EN|\ ++ FH_RTC_INT_CORE_IDLE_ERR_EN | \ ++ FH_RTC_INT_CORE_INT_ERR_MASK |\ ++ FH_RTC_INT_CORE_IDLE_ERR_MASK ++ ); ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, ++ FH_RTC_INT_STATUS_CORE |\ ++ FH_RTC_INT_STATUS_CORE_IDLE); ++ ++ ++ SET_REG(fh_rtc->v_addr+FH_RTC_INT_STATUS, 0x20); ++ mdelay(1); ++ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS); ++ if (rtc_core_status & FH_RTC_ISR_POWERFAIL_POS) { ++ RTC_PRINT_DBG("rtc powerfailed !\n"); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & ++ (~FH_RTC_ISR_POWERFAIL_POS)); ++ } ++ /* clear all core's irq status an enable */ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_EN, ++ rtc_core_status & ++ (~FH_RTC_INT_CORE_INT_ALL_COV)); ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_INT_STATUS, ++ rtc_core_status & ++ (~FH_RTC_INT_CORE_INT_ALL_COV)); ++ ++ platform_set_drvdata(pdev, fh_rtc); ++ ++ /* register RTC and exit */ ++ rtc = rtc_device_register(rtc_platform_info->dev_name, \ ++ &pdev->dev, &fh_rtcops, THIS_MODULE); ++ if (IS_ERR(rtc)) { ++ dev_err(&pdev->dev, "cannot attach rtc\n"); ++ err = PTR_ERR(rtc); ++ goto err_nores; ++ } ++ fh_rtc->rtc = rtc; ++ ++ INIT_WORK(&rtc_int_wq, rtc_core_int_handler); ++ /* register RTC IRQs */ ++ err = request_irq(fh_rtc->irq , fh_rtc_irq, 0, ++ dev_name(&pdev->dev), fh_rtc); ++ if (err) { ++ RTC_PRINT_DBG("request_irq failed, %d\n", err); ++ goto err_nores; ++ } ++ ++ /* register RTC MISC device */ ++ err = misc_register(&fh_rtc_misc); ++ if (err < 0) ++ RTC_PRINT_DBG("register rtc misc device error\n"); ++ /* register RTC PROC FILE */ ++ create_proc_rtc(fh_rtc); ++ ++#ifdef USE_TSENSOR ++ rtc_adjust(); ++#endif ++ ++ return 0; ++ ++err_nores: ++ return err; ++} ++ ++static int fh_rtc_remove(struct platform_device *dev) ++{ ++ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(dev); ++ ++ remove_proc(); ++ free_irq(fh_rtc->irq, fh_rtc); ++ rtc_device_unregister(fh_rtc->rtc); ++ iounmap(fh_rtc->regs); ++ platform_set_drvdata(dev, NULL); ++ kfree(fh_rtc); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++ ++/* RTC Power management control */ ++ ++static int fh_rtc_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ return 0; ++} ++ ++static int fh_rtc_resume(struct platform_device *pdev) ++{ ++ return 0; ++} ++#else ++#define fh_rtc_suspend NULL ++#define fh_rtc_resume NULL ++#endif ++#define FH_RTC_MISC_DEVICE_NAME "fh_rtc_misc" ++ ++static int fh_rtc_misc_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int fh_rtc_misc_release(struct inode *inode, struct file *filp) ++{ ++ return 0; ++} ++ ++long fh_rtc_misc_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int current_tsensor_data, current_offset, current_idx; ++ int status; ++ int count; ++ int lut[12] = { 0 }; ++ int reg[2] = {0}; ++ ++ switch (cmd) { ++ /* get temperature data from tsensor */ ++ case GET_TSENSOR_DATA: ++ current_tsensor_data = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_INFO); ++ status = copy_to_user((int __user *)(arg), ++ ¤t_tsensor_data, ++ 4); ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ /* get current used offset data */ ++ case GET_CURRENT_OFFSET_DATA: ++ current_offset = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET); ++ current_offset = current_offset&(0xff<<16); ++ current_offset = current_offset>>16; ++ status = copy_to_user((int __user *)(arg), ++ ¤t_offset, 4); ++ ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ /* get current used offset index of lut */ ++ case GET_CURRENT_OFFSET_IDX: ++ current_offset = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET); ++ current_idx = current_offset&(0x3f<<10); ++ current_idx = current_idx>>10; ++ status = copy_to_user((int __user *)(arg), ++ ¤t_idx, 4); ++ ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ /* updata all of lut */ ++ case RTC_GET_LUT: ++ for (count = 0; count < 12; count++) ++ lut[count] = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET_LUT + (count<<4)); ++ ++ status = copy_to_user((int __user *)(arg), &lut[0], ++ count*4); ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ /* modify lut */ ++ case RTC_SET_LUT: ++ status = copy_from_user(&lut[0], (int __user *)(arg), ++ 48); ++ if (status < 0) ++ pr_info("copy from user failed\n"); ++ for (count = 0; count < 12; count++) ++ fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET_LUT + (count<<4), lut[count]); ++ break; ++ /* get RTC core reg value */ ++ case GET_REG_VALUE: ++ for (count = 0; count < 9; count++) ++ lut[count] = fh_rtc_get_core(fh_rtc->v_addr, ++ (count&0xf)<<4); ++ ++ status = copy_to_user((int __user *)(arg), &lut[0], ++ count*4); ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ /* set RTC core reg value */ ++ case SET_REG_VALUE: ++ status = copy_from_user(®[0], (int __user *)(arg), 8); ++ if (status < 0) ++ pr_info("copy from user failed\n"); ++ ++ fh_rtc_set_core(fh_rtc->v_addr, ++ reg[0], ++ reg[1]); ++ pr_info("set reg addr :%x, value: %x\n", ++ reg[0], reg[1]); ++ break; ++ /* get temperature value */ ++ case GET_TEMP_VALUE: ++ status = fh_rtc_get_temp(fh_rtc->v_addr); ++ lut[0] = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_INFO); ++ pr_info("temp value is %x\n", lut[0]); ++ status = copy_to_user((int __user *)(arg), ++ &lut[0], 4); ++ if (status < 0) ++ pr_info("copy to user failed\n"); ++ break; ++ default: ++ pr_info("val is invalied\n"); ++ break; ++ } ++ ++ return 0; ++ ++} ++static const struct file_operations fh_rtc_misc_fops = { ++ .owner = THIS_MODULE, ++ .open = fh_rtc_misc_open, ++ .release = fh_rtc_misc_release, ++ .unlocked_ioctl = fh_rtc_misc_ioctl, ++}; ++ ++static struct miscdevice fh_rtc_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = FH_RTC_MISC_DEVICE_NAME, ++ /*.nodename = FH_EFUSE_MISC_DEVICE_NODE_NAME,*/ ++ .fops = &fh_rtc_misc_fops, ++}; ++static struct platform_driver fh_rtc_driver = { ++ .probe = fh_rtc_probe, ++ .remove = __devexit_p(fh_rtc_remove), ++ .suspend = fh_rtc_suspend, ++ .resume = fh_rtc_resume, ++ .driver = { ++ .name = "fh_rtc", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init fh_rtc_init(void) ++{ ++ ++ return platform_driver_register(&fh_rtc_driver); ++} ++ ++static void __exit fh_rtc_exit(void) ++{ ++ platform_driver_unregister(&fh_rtc_driver); ++} ++ ++#ifdef USE_TSENSOR ++static int fh_rtc_temp_cfg_coef_offset(unsigned int coef, unsigned int offset) ++{ ++ unsigned int temp_cfg; ++ int status; ++ ++ if (coef > 0xff) { ++ pr_err("coef invalid\n"); ++ return -1; ++ } ++ if (offset > 0xffff) { ++ pr_err("offset invalid\n"); ++ return -1; ++ } ++ temp_cfg = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG); ++ temp_cfg &= 0xffff0000; ++ temp_cfg |= coef; ++ temp_cfg |= (offset<<8); ++ ++ status = fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG, temp_cfg); ++ ++ return status; ++} ++ ++static int fh_rtc_temp_cfg_thl_thh(unsigned int thl, unsigned int thh) ++{ ++ unsigned int temp_cfg; ++ int status; ++ ++ if (thl > 0x3f) { ++ pr_err("thl invalid\n"); ++ return -1; ++ } ++ if (thh > 0x3f) { ++ pr_err("thh invalid\n"); ++ return -1; ++ } ++ ++ temp_cfg = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG); ++ temp_cfg &= 0xf000ffff; ++ temp_cfg |= (thl<<16); ++ temp_cfg |= (thh<<22); ++ ++ status = fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG, ++ temp_cfg); ++ ++ return status; ++} ++#if 0 ++static int fh_rtc_temp_cfg_update_time(unsigned int time) ++{ ++ unsigned int temp_cfg; ++ int status; ++ ++ if (time > 5) { ++ pr_err("update time invalid\n"); ++ return -1; ++ } ++ ++ temp_cfg = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG); ++ temp_cfg &= 0xf0000000; ++ temp_cfg |= time; ++ ++ status = fh_rtc_set_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG, temp_cfg); ++ ++ return status; ++} ++#endif ++#endif ++ssize_t zy_rtc_proc_read(char *page, char **start, off_t off, \ ++ int count, int *eof, struct fh_rtc_controller *data) ++{ ++#ifdef USE_TSENSOR ++ int current_offset, current_idx, current_tsensor_data, current_cfg; ++ ++ current_offset = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_OFFSET); ++ current_cfg = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_CFG); ++ current_offset = current_offset&(0xff<<16); ++ current_idx = current_offset&(0x3f<<10); ++ current_tsensor_data = fh_rtc_get_core(fh_rtc->v_addr, ++ FH_RTC_CMD_TEMP_INFO); ++ current_tsensor_data = current_tsensor_data*210; ++ current_tsensor_data = (int)(current_tsensor_data/4096); ++ pr_info("[RTC]:current offset:%x\n", current_offset>>16); ++ pr_info("[RTC]:current temp:%d\n", current_tsensor_data-56); ++#endif ++ ++ return 0; ++} ++ ++static ssize_t fh_rtc_proc_write(struct file *filp, \ ++ const char *buf, size_t len,\ ++loff_t *off) ++{ ++ return 0; ++} ++ ++static void create_proc_rtc(struct fh_rtc_controller *rtc) ++{ ++ fh_rtc->proc_rtc_entry = create_proc_entry(FH_RTC_PROC_FILE,\ ++ S_IRUGO, NULL); ++ ++ if (!fh_rtc->proc_rtc_entry) { ++ pr_err("create proc failed\n"); ++ } else { ++ fh_rtc->proc_rtc_entry->read_proc = \ ++ (read_proc_t *) zy_rtc_proc_read; ++ fh_rtc->proc_rtc_entry->write_proc = \ ++ (write_proc_t *) fh_rtc_proc_write; ++ fh_rtc->proc_rtc_entry->data = rtc; ++ } ++} ++ ++static void remove_proc(void) ++{ ++ remove_proc_entry(FH_RTC_PROC_FILE, NULL); ++} ++ ++module_init(fh_rtc_init); ++module_exit(fh_rtc_exit); ++ ++ ++MODULE_DESCRIPTION("FH SOC RTC Driver"); ++MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:fh-rtc"); +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index de35c3ad..ca24baf2 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -442,6 +442,15 @@ config SPI_DW_MMIO + tristate "Memory-mapped io interface driver for DW SPI core" + depends on SPI_DESIGNWARE && HAVE_CLK + ++ ++config SPI_FH ++ tristate "fh spi driver for DW SPI core" ++ depends on SPI_MASTER ++ ++config SPI_FH_SLAVE ++ tristate "fh spi slave driver for DW SPI core" ++ ++ + # + # There are lots of SPI device types, with sensors and memory + # being probably the most widely used ones. +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 0f8c69b6..463ffaed 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -22,7 +22,13 @@ obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o + obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o + obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o + dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o ++ + obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o ++ ++obj-$(CONFIG_SPI_FH) += fh_spi.o ++obj-$(CONFIG_SPI_FH_SLAVE) += fh_spi_slave.o ++ ++ + obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o + obj-$(CONFIG_SPI_GPIO) += spi_gpio.o + obj-$(CONFIG_SPI_IMX) += spi_imx.o +diff --git a/drivers/spi/fh_spi.c b/drivers/spi/fh_spi.c +new file mode 100644 +index 00000000..4e4bd2dc +--- /dev/null ++++ b/drivers/spi/fh_spi.c +@@ -0,0 +1,2115 @@ ++/** @file fh_spi.c ++ * @note ShangHai FullHan Co., Ltd. All Right Reserved. ++ * @brief fh driver ++ * @author yu.zhang ++ * @date 2015/1/11 ++ * @note history ++ * @note 2014-1-11 V1.0.0 create the file. ++ */ ++/***************************************************************************** ++ * Include Section ++ * add all #include here ++ *****************************************************************************/ ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/spi/spi.h> ++#include <linux/scatterlist.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/workqueue.h> ++#include <linux/bug.h> ++#include <linux/completion.h> ++#include <linux/gpio.h> ++#include <linux/dmaengine.h> ++#include <mach/spi.h> ++#include <mach/fh_dmac.h> ++#include <linux/dma-mapping.h> ++#include <mach/fh_dmac_regs.h> ++/***************************************************************************** ++ * Define section ++ * add all #define here ++ *****************************************************************************/ ++#define lift_shift_bit_num(bit_num) (1<<bit_num) ++#define SPI_IRQ_TXEIS (lift_shift_bit_num(0)) ++#define SPI_IRQ_TXOIS (lift_shift_bit_num(1)) ++#define SPI_IRQ_RXUIS (lift_shift_bit_num(2)) ++#define SPI_IRQ_RXOIS (lift_shift_bit_num(3)) ++#define SPI_IRQ_RXFIS (lift_shift_bit_num(4)) ++#define SPI_IRQ_MSTIS (lift_shift_bit_num(5)) ++#define SPI_STATUS_BUSY (lift_shift_bit_num(0)) ++#define SPI_STATUS_TFNF (lift_shift_bit_num(1)) ++#define SPI_STATUS_TFE (lift_shift_bit_num(2)) ++#define SPI_STATUS_RFNE (lift_shift_bit_num(3)) ++#define SPI_STATUS_RFF (lift_shift_bit_num(4)) ++#define SPI_STATUS_TXE (lift_shift_bit_num(5)) ++#define SPI_STATUS_DCOL (lift_shift_bit_num(6)) ++#define CACHE_LINE_SIZE (32) ++#define PUMP_DATA_NONE_MODE (0x00) ++#define PUMP_DATA_DMA_MODE (0x11) ++#define PUMP_DATA_ISR_MODE (0x22) ++#define PUMP_DATA_POLL_MODE (0x33) ++#define DMA_TRANS_GATE_LEVEL 1024 ++#define SPI_DATA_REG_OFFSET (0x60) ++#define SPI_RX_ONLY_ONE_TIME_SIZE (0x10000) ++#define MAX_SG_LEN 128 ++#if (SPI_RX_ONLY_ONE_TIME_SIZE > 2048) ++#define SG_ONE_TIME_MAX_SIZE 2048 ++#else ++#define SG_ONE_TIME_MAX_SIZE SPI_RX_ONLY_ONE_TIME_SIZE ++#endif ++#define SPI_DMA_PROTCTL_DATA 6 ++/**************************************************************************** ++ * ADT section ++ * add definition of user defined Data Type that only be used in this file here ++ ***************************************************************************/ ++enum { ++ CONFIG_OK = 0, CONFIG_PARA_ERROR = lift_shift_bit_num(0), ++ CONFIG_BUSY = lift_shift_bit_num(1), ++ WRITE_READ_OK = 0, ++ WRITE_READ_ERROR = lift_shift_bit_num(2), ++ WRITE_READ_TIME_OUT = lift_shift_bit_num(3), ++ WRITE_ONLY_OK = 0, ++ WRITE_ONLY_ERROR = lift_shift_bit_num(4), ++ WRITE_ONLY_TIME_OUT = lift_shift_bit_num(5), ++ READ_ONLY_OK = 0, ++ READ_ONLY_ERROR = lift_shift_bit_num(6), ++ READ_ONLY_TIME_OUT = lift_shift_bit_num(7), ++ EEPROM_OK = 0, ++ EEPROM_ERROR = lift_shift_bit_num(8), ++ EEPROM_TIME_OUT = lift_shift_bit_num(9), ++ MULTI_MASTER_ERROR = lift_shift_bit_num(10), ++ TX_OVERFLOW_ERROR = lift_shift_bit_num(11), ++ RX_OVERFLOW_ERROR = lift_shift_bit_num(12), ++}; ++ ++typedef enum enum_spi_enable { ++SPI_DISABLE = 0, ++SPI_ENABLE = (lift_shift_bit_num(0)), ++} spi_enable_e; ++ ++typedef enum enum_spi_polarity { ++SPI_POLARITY_LOW = 0, ++SPI_POLARITY_HIGH = (lift_shift_bit_num(7)), ++SPI_POLARITY_RANGE = (lift_shift_bit_num(7)), ++} spi_polarity_e; ++ ++typedef enum enum_spi_phase { ++SPI_PHASE_RX_FIRST = 0, ++SPI_PHASE_TX_FIRST = (lift_shift_bit_num(6)), ++SPI_PHASE_RANGE = (lift_shift_bit_num(6)), ++} spi_phase_e; ++ ++typedef enum enum_spi_format { ++SPI_MOTOROLA_MODE = 0x00, ++SPI_TI_MODE = 0x10, ++SPI_MICROWIRE_MODE = 0x20, ++SPI_FRAME_FORMAT_RANGE = 0x30, ++} spi_format_e; ++ ++ ++typedef enum enum_spi_data_size { ++SPI_DATA_SIZE_4BIT = 0x03, ++SPI_DATA_SIZE_5BIT = 0x04, ++SPI_DATA_SIZE_6BIT = 0x05, ++SPI_DATA_SIZE_7BIT = 0x06, ++SPI_DATA_SIZE_8BIT = 0x07, ++SPI_DATA_SIZE_9BIT = 0x08, ++SPI_DATA_SIZE_10BIT = 0x09, ++SPI_DATA_SIZE_16BIT = 0x0f, ++SPI_DATA_SIZE_RANGE = 0x0f, ++} spi_data_size_e; ++ ++typedef enum enum_spi_transfer_mode { ++SPI_TX_RX_MODE = 0x000, ++SPI_ONLY_TX_MODE = 0x100, ++SPI_ONLY_RX_MODE = 0x200, ++SPI_EEPROM_MODE = 0x300, ++SPI_TRANSFER_MODE_RANGE = 0x300, ++} spi_transfer_mode_e; ++ ++typedef enum enum_spi_baudrate { ++SPI_SCLKIN = 50000000, ++SPI_SCLKOUT_27000000 = (SPI_SCLKIN / 27000000), ++SPI_SCLKOUT_13500000 = (SPI_SCLKIN / 13500000), ++SPI_SCLKOUT_6750000 = (SPI_SCLKIN / 6750000), ++SPI_SCLKOUT_4500000 = (SPI_SCLKIN / 4500000), ++SPI_SCLKOUT_3375000 = (SPI_SCLKIN / 3375000), ++SPI_SCLKOUT_2700000 = (SPI_SCLKIN / 2700000), ++SPI_SCLKOUT_1500000 = (SPI_SCLKIN / 1500000), ++SPI_SCLKOUT_500000 = (SPI_SCLKIN / 500000), ++SPI_SCLKOUT_100000 = (SPI_SCLKIN / 100000), ++} spi_baudrate_e; ++ ++typedef enum enum_spi_irq { ++SPI_IRQ_TXEIM = (lift_shift_bit_num(0)), ++SPI_IRQ_TXOIM = (lift_shift_bit_num(1)), ++SPI_IRQ_RXUIM = (lift_shift_bit_num(2)), ++SPI_IRQ_RXOIM = (lift_shift_bit_num(3)), ++SPI_IRQ_RXFIM = (lift_shift_bit_num(4)), ++SPI_IRQ_MSTIM = (lift_shift_bit_num(5)), ++SPI_IRQ_ALL = 0x3f, ++} spi_irq_e; ++ ++typedef enum enum_spi_slave { ++SPI_SLAVE_PORT0 = (lift_shift_bit_num(0)), ++SPI_SLAVE_PORT1 = (lift_shift_bit_num(1)), ++} spi_slave_e; ++ ++typedef enum enum_spi_dma_control_mode { ++SPI_DMA_RX_POS = (lift_shift_bit_num(0)), ++SPI_DMA_TX_POS = (lift_shift_bit_num(1)), ++SPI_DMA_CONTROL_RANGE = 0x03, ++} spi_dma_control_mode_e; ++ ++/*read wire mode*/ ++typedef enum enum_spi_read_wire_mode { ++STANDARD_READ = 0x00, ++DUAL_OUTPUT = 0x01, ++DUAL_IO = 0x02, ++QUAD_OUTPUT = 0x03, ++QUAD_IO = 0x04, ++} spi_read_wire_mode_e; ++ ++/*program wire mode*/ ++typedef enum enum_spi_prog_wire_mode { ++STANDARD_PROG = 0x00, ++QUAD_INPUT = 0x01, ++} spi_prog_wire_mode_e; ++ ++/*ahb Xip config*/ ++typedef enum enum_spi_xip_config { ++XIP_DISABLE = 0, ++XIP_ENABLE = 1, ++} spi_xip_config_e; ++ ++/*ahb DPI config*/ ++typedef enum enum_spi_dpi_config { ++DPI_DISABLE = 0, ++DPI_ENABLE = 1, ++} spi_dpi_config_e; ++ ++/*ahb QPI config*/ ++typedef enum enum_spi_qpi_config { ++QPI_DISABLE = 0, ++QPI_ENABLE = 1, ++} spi_qpi_config_e; ++ ++struct fh_spi_reg { ++ u32 ctrl0; ++ u32 ctrl1; ++ u32 ssienr; ++ u32 mwcr; ++ u32 ser; ++ u32 baudr; ++ u32 txfltr; ++ u32 rxfltr; ++ u32 txflr; ++ u32 rxflr; ++ u32 sr; ++ u32 imr; ++ u32 isr; ++ u32 risr; ++ u32 txoicr; ++ u32 rxoicr; ++ u32 rxuicr; ++ u32 msticr; ++ u32 icr; ++ u32 dmacr; ++ u32 dmatdlr; ++ u32 dmardlr; ++ u32 idr; ++ u32 version; ++ u32 dr; /* Currently oper as 32 bits, ++ though only low 16 bits matters */ ++ u32 rev[35]; ++ u32 rx_sample_dly; ++ u32 ccfgr; ++ u32 opcr; ++ u32 timcr; ++ u32 bbar0; ++ u32 bbar1; ++}; ++ ++#define dw_readl(dw, name) \ ++__raw_readl(&(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_writel(dw, name, val) \ ++__raw_writel((val), &(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_readw(dw, name) \ ++__raw_readw(&(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_writew(dw, name, val) \ ++__raw_writew((val), &(((struct fh_spi_reg *)dw->regs)->name)) ++ ++struct _fh_spi_dma_transfer { ++ struct dma_chan *chan; ++ struct dma_slave_config cfg; ++ struct scatterlist sgl[MAX_SG_LEN]; ++ u32 sgl_data_size[MAX_SG_LEN]; ++ u32 actual_sgl_size; ++ struct dma_async_tx_descriptor *desc; ++}; ++ ++struct fh_spi { ++ void * __iomem regs; /* vaddr of the control registers */ ++ u32 id; ++ u32 paddr; ++ u32 slave_port; ++ u32 irq; /* irq no */ ++ u32 fifo_len; /* depth of the FIFO buffer */ ++ u32 cpol; ++ u32 cpha; ++ u32 isr_flag; ++ /*clk*/ ++ u32 apb_clock_in; ++ u32 max_freq; /* max bus freq supported */ ++ u32 div; ++ /*use id u32 bus_num;*//*which bus*/ ++ u32 num_cs; /* supported slave numbers */ ++ u32 data_width; ++ u32 frame_mode; ++ u32 transfer_mode; ++ u32 active_cs_pin; ++ /*copy from the user...*/ ++ u32 tx_len; ++ u32 rx_len; ++ void *rx_buff; ++ void *tx_buff; ++ u32 tx_dma_add; ++ u32 rx_dma_add; ++ u32 tx_hs_no; ++ u32 rx_hs_no; ++ u32 tx_dumy_buff[4]; ++ u32 rx_dumy_buff[4]; ++ u32 tx_dumy_dma_add; ++ u32 rx_dumy_dma_add; ++ struct fh_spi_cs cs_data[SPI_MASTER_CONTROLLER_MAX_SLAVE]; ++ u32 pump_data_mode; ++ struct _fh_spi_dma_transfer dma_rx; ++ struct _fh_spi_dma_transfer dma_tx; ++ u32 complete_times; ++ struct fh_spi_platform_data *board_info; ++}; ++ ++struct fh_spi_controller { ++ struct device *master_dev; ++ struct clk *clk; ++ spinlock_t lock; ++ struct list_head queue; ++ struct platform_device *p_dev; ++ struct work_struct work; ++ struct workqueue_struct *workqueue; ++ struct spi_message *active_message; ++ struct spi_transfer *active_transfer; ++ struct fh_spi dwc; ++ struct completion done; ++ /*add multi*/ ++ u32 active_wire_width; ++ u32 dir; ++ struct spi_device *active_spi_dev; ++}; ++ ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Global variables section - Exported ++ * add declaration of global variables that will be exported here ++ * e.g. ++ * int8_t foo; ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++ ++static u32 Spi_Enable(struct fh_spi *dw, spi_enable_e enable); ++static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity); ++static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase); ++static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format); ++static u32 Spi_SetBaudrate(struct fh_spi *dw, spi_baudrate_e baudrate); ++static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq); ++static u32 Spi_ReadStatus(struct fh_spi *dw); ++static u32 Spi_EnableSlaveen(struct fh_spi *dw, spi_slave_e port); ++static u32 Spi_DisableSlaveen(struct fh_spi *dw, spi_slave_e port); ++static u32 Spi_EnableIrq(struct fh_spi *dw, u32 irq); ++static u32 Spi_SetTxlevlel(struct fh_spi *dw, u32 level); ++static u32 Spi_ReadTxfifolevel(struct fh_spi *dw); ++static u32 Spi_ReadRxfifolevel(struct fh_spi *dw); ++static u32 Spi_WriteData(struct fh_spi *dw, u32 data); ++static u32 Spi_ReadData(struct fh_spi *dw); ++static u32 Spi_Isrstatus(struct fh_spi *dw); ++static void Spi_SetDmaTxDataLevel(struct fh_spi *dw, u32 level); ++static void Spi_SetDmaRxDataLevel(struct fh_spi *dw, u32 level); ++static void Spi_SetDmaControlEnable(struct fh_spi *dw, ++spi_dma_control_mode_e enable_pos); ++static bool fh_spi_dma_chan_filter(struct dma_chan *chan, void *param); ++static int fh_spi_setup(struct spi_device *spi); ++static u32 Spi_SetRxdelay(struct fh_spi *dw, u8 data); ++static u32 Spi_RawIsrstatus(struct fh_spi *dw); ++static int rx_only_fix_data_width(struct fh_spi_controller *fh_spi, u32 size); ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++ ++/* function body */ ++ ++static u32 Spi_Enable(struct fh_spi *dw, spi_enable_e enable) ++{ ++ dw_writel(dw, ssienr, enable); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_ContinueReadNum(struct fh_spi *dw, u32 num) ++{ ++ dw_writel(dw, ctrl1, (num-1)); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity) ++{ ++ u32 data; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_POLARITY_RANGE; ++ data |= polarity; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase) ++{ ++ u32 data; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_PHASE_RANGE; ++ data |= phase; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_FRAME_FORMAT_RANGE; ++ data |= format; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_TRANSFER_MODE_RANGE; ++ data |= mode; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetBaudrate(struct fh_spi *dw, spi_baudrate_e baudrate) ++{ ++ dw_writel(dw, baudr, baudrate); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, imr); ++ data &= ~irq; ++ dw_writel(dw, imr, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_EnableIrq(struct fh_spi *dw, u32 irq) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, imr); ++ data |= irq; ++ dw_writel(dw, imr, data); ++ return CONFIG_OK; ++ ++} ++ ++static u32 Spi_SetTxlevlel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, txfltr, level); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_ReadTxfifolevel(struct fh_spi *dw) ++{ ++ return dw_readl(dw, txflr); ++} ++ ++static u32 Spi_ReadRxfifolevel(struct fh_spi *dw) ++{ ++ return (u32) dw_readl(dw, rxflr); ++} ++ ++static u32 Spi_ReadStatus(struct fh_spi *dw) ++{ ++ return (u32) dw_readl(dw, sr); ++} ++ ++static u32 Spi_EnableSlaveen(struct fh_spi *dw, spi_slave_e port) ++{ ++ u32 data = 0; ++ ++ gpio_direction_output(dw->active_cs_pin, 0); ++ data = dw_readl(dw, ser); ++ data |= port; ++ dw_writel(dw, ser, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_DisableSlaveen(struct fh_spi *dw, spi_slave_e port) ++{ ++ u32 data = 0; ++ gpio_direction_output(dw->active_cs_pin, 1); ++ data = dw_readl(dw, ser); ++ data &= ~port; ++ dw_writel(dw, ser, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_WriteData(struct fh_spi *dw, u32 data) ++{ ++ dw_writel(dw, dr, data); ++ return WRITE_ONLY_OK; ++} ++ ++static u32 Spi_ReadData(struct fh_spi *dw) ++{ ++ return dw_readl(dw, dr); ++} ++ ++static void Spi_Clearallerror(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, icr); ++ data = 0; ++} ++ ++static u32 Spi_Isrstatus(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, isr); ++ return data; ++} ++ ++static u32 Spi_RawIsrstatus(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, risr); ++ return data; ++} ++ ++static void Spi_SetDmaTxDataLevel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, dmatdlr, level); ++} ++ ++static void Spi_SetDmaRxDataLevel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, dmardlr, level); ++} ++ ++static void Spi_SetDmaControlEnable(struct fh_spi *dw, ++spi_dma_control_mode_e enable_pos) ++{ ++ u32 data; ++ data = dw_readl(dw, dmacr); ++ data |= enable_pos; ++ dw_writel(dw, dmacr, data); ++} ++ ++static void Spi_SetDmaControlDisable(struct fh_spi *dw, ++spi_dma_control_mode_e enable_pos) ++{ ++ u32 data; ++ data = dw_readl(dw, dmacr); ++ data &= ~enable_pos; ++ dw_writel(dw, dmacr, data); ++} ++ ++static u32 Spi_SetRxdelay(struct fh_spi *dw, u8 data) ++{ ++ dw_writel(dw, rx_sample_dly, data); ++ return CONFIG_OK; ++} ++ ++static inline u32 tx_max_tx_only(struct fh_spi_controller *fh_spi) ++{ ++ u32 hw_tx_level; ++ hw_tx_level = Spi_ReadTxfifolevel(&fh_spi->dwc); ++ hw_tx_level = fh_spi->dwc.fifo_len - hw_tx_level; ++ ++ return min(hw_tx_level, fh_spi->dwc.tx_len); ++} ++ ++static inline u32 tx_max(struct fh_spi_controller *fh_spi) ++{ ++ ++ u32 hw_tx_level, hw_rx_level; ++ u32 temp_tx_lev; ++ temp_tx_lev = Spi_ReadTxfifolevel(&fh_spi->dwc); ++ hw_rx_level = temp_tx_lev + Spi_ReadRxfifolevel(&fh_spi->dwc); ++ if (hw_rx_level >= fh_spi->dwc.fifo_len) ++ return 0; ++ /* add shift data... maybe should add apb bus delay */ ++ hw_rx_level++; ++ ++ hw_tx_level = temp_tx_lev; ++ hw_tx_level = fh_spi->dwc.fifo_len - hw_tx_level; ++ hw_rx_level = fh_spi->dwc.fifo_len - hw_rx_level; ++ /* min(hw_tx_level, fh_spi->dwc.tx_len); */ ++ return min(min(hw_tx_level, fh_spi->dwc.tx_len), hw_rx_level); ++} ++ ++/* Return the max entries we should read out of rx fifo */ ++static inline u32 rx_max(struct fh_spi_controller *fh_spi) ++{ ++ u32 hw_rx_level; ++ hw_rx_level = Spi_ReadRxfifolevel(&fh_spi->dwc); ++ return hw_rx_level; ++} ++ ++/*add spic new code here below..*/ ++static void reg_bit_process(u32 *data, u32 value, u32 mask) { ++(*data) &= ~mask; ++(*data) |= value; ++} ++ ++ ++static int Spi_SetApbReadWireMode(struct fh_spi *dw, spi_read_wire_mode_e mode) ++{ ++ ++ u32 data = dw_readl(dw, ccfgr); ++ switch (mode){ ++ case STANDARD_READ: ++ reg_bit_process(&data, 0 << 8, 7 << 8); ++ reg_bit_process(&data, 0 << 2, 3 << 2); ++ reg_bit_process(&data, 0 << 0, 3 << 0); ++ reg_bit_process(&data, 0 << 4, 7 << 4); ++ break; ++ ++ case DUAL_OUTPUT: ++ reg_bit_process(&data, 0 << 8, 7 << 8); ++ reg_bit_process(&data, 3 << 2, 3 << 2); ++ reg_bit_process(&data, 1 << 0, 3 << 0); ++ reg_bit_process(&data, 0 << 4, 7 << 4); ++ break; ++ ++ case QUAD_OUTPUT: ++ reg_bit_process(&data, 0 << 8, 7 << 8); ++ reg_bit_process(&data, 3 << 2, 3 << 2); ++ reg_bit_process(&data, 2 << 0, 3 << 0); ++ reg_bit_process(&data, 0 << 4, 7 << 4); ++ break; ++ default: ++ printk("wrong mode now....\n"); ++ } ++ data |= 1<<13; ++ dw_writel(dw, ccfgr, data); ++ return CONFIG_OK; ++} ++ ++static int Spi_SetXip(struct fh_spi *dw, spi_xip_config_e value) ++{ ++ ++ ++ u32 data = dw_readl(dw, ccfgr); ++ u32 data1 = dw_readl(dw, opcr); ++ ++ if (value == XIP_ENABLE) { ++ reg_bit_process(&data, XIP_ENABLE << 11, 1 << 11); ++ reg_bit_process(&data1, 0x20 << 20, 0xff << 20); ++ } else if (value == XIP_DISABLE) { ++ reg_bit_process(&data, XIP_DISABLE << 11, 1 << 11); ++ reg_bit_process(&data1, 0xff << 20, 0xff << 20); ++ } ++ dw_writel(dw, ccfgr, data); ++ dw_writel(dw, opcr, data1); ++ ++ return 0; ++} ++ ++static int Spi_SetDPI(struct fh_spi *dw, spi_dpi_config_e value) ++{ ++ ++ u32 data = dw_readl(dw, opcr); ++ reg_bit_process(&data, value << 16, 1 << 16); ++ dw_writel(dw, opcr, data); ++ return 0; ++} ++ ++SINT32 Spi_SetSwap(struct fh_spi *dw, unsigned int value) ++{ ++ u32 data; ++ ++ Spi_Enable(dw, SPI_DISABLE); ++ data = dw_readl(dw, ccfgr); ++ data &= ~(1<<12); ++ data |= (value<<12); ++ dw_writel(dw, ccfgr, data); ++ Spi_Enable(dw, SPI_ENABLE); ++ return 0; ++} ++ ++SINT32 Spi_SetWidth(struct fh_spi *dw, unsigned int value) ++{ ++ u32 data; ++ ++ Spi_Enable(dw, SPI_DISABLE); ++ data = dw_readl(dw, ctrl0); ++ data &= ~(0x0f<<0); ++ data |= ((value-1)<<0); ++ dw_writel(dw, ctrl0, data); ++ Spi_Enable(dw, SPI_ENABLE); ++ return 0; ++} ++ ++static int Spi_SetQPI(struct fh_spi *dw, spi_qpi_config_e value) ++{ ++ ++ u32 data = dw_readl(dw, opcr); ++ ++ reg_bit_process(&data, value << 17, 1 << 17); ++ dw_writel(dw, opcr, data); ++ ++ return 0; ++} ++ ++static int Spi_TimingConfigure(struct fh_spi *dw, u32 value) ++{ ++ dw_writel(dw, timcr, value); ++ return 0; ++} ++ ++void fh_spic_check_idle(struct fh_spi *dw){ ++ u32 status; ++ status = Spi_ReadStatus(dw); ++ /*ahb rx fifo not empty..*/ ++ BUG_ON((status & 1<<10) != 0); ++ /*ahb tx fifo empty..*/ ++ BUG_ON((status & 1<<9) != 1<<9); ++ /*apb rx fifo*/ ++ BUG_ON((status & 1<<3) != 0); ++ /*apb tx fifo*/ ++ BUG_ON((status & 1<<2) != 1<<2); ++ /*shift not busy..*/ ++ BUG_ON((status & 1) != 0); ++} ++ ++ ++int spic_wire_init(struct spi_master * p_master){ ++ ++ struct fh_spi_controller *fh_spi; ++ fh_spi = spi_master_get_devdata(p_master); ++ Spi_SetXip(&fh_spi->dwc, XIP_DISABLE); ++ Spi_SetDPI(&fh_spi->dwc, DPI_DISABLE); ++ Spi_SetQPI(&fh_spi->dwc, QPI_DISABLE); ++ Spi_TimingConfigure(&fh_spi->dwc, 0x0); ++ Spi_SetApbReadWireMode(&fh_spi->dwc,STANDARD_READ); ++ return 0; ++ ++} ++ ++void spi_bus_change_1_wire(struct spi_master *p_master) ++{ ++ struct fh_spi_controller *fh_spi; ++ fh_spi = spi_master_get_devdata(p_master); ++ fh_spi->active_wire_width = ONE_WIRE_SUPPORT; ++ fh_spi->dir = SPI_DATA_DIR_DUOLEX; ++ fh_spic_check_idle(&fh_spi->dwc); ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetApbReadWireMode(&fh_spi->dwc, STANDARD_READ); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ ++} ++ ++ ++void spi_bus_change_2_wire(struct spi_master *p_master,unsigned int dir) ++{ ++ ++ struct fh_spi_controller *fh_spi; ++ fh_spi = spi_master_get_devdata(p_master); ++ fh_spi->active_wire_width = DUAL_WIRE_SUPPORT; ++ fh_spi->dir = dir; ++ fh_spic_check_idle(&fh_spi->dwc); ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetApbReadWireMode(&fh_spi->dwc, DUAL_OUTPUT); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++} ++ ++void spi_bus_change_4_wire(struct spi_master *p_master,unsigned int dir) ++{ ++ struct fh_spi_controller *fh_spi; ++ fh_spi = spi_master_get_devdata(p_master); ++ fh_spi->active_wire_width = QUAD_WIRE_SUPPORT; ++ fh_spi->dir = dir; ++ fh_spic_check_idle(&fh_spi->dwc); ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetApbReadWireMode(&fh_spi->dwc, QUAD_OUTPUT); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++} ++ ++ ++static void spi_wait_tx_only_done(struct fh_spi_controller *fh_spi){ ++ u32 status; ++ do { ++ status = Spi_ReadStatus(&fh_spi->dwc); ++ } while ((status & 0x01) || (!(status & 0x04))); ++} ++ ++static int fh_spi_init_hw(struct fh_spi_controller *fh_spi, ++struct fh_spi_platform_data *board_info,struct spi_master *p_master) ++{ ++ int status, i; ++ struct _spi_advanced_info *p_adv_info = NULL; ++ fh_spi->dwc.id = board_info->bus_no; ++ fh_spi->dwc.fifo_len = board_info->fifo_len; ++ fh_spi->dwc.num_cs = board_info->slave_max_num; ++ for (i = 0; i < fh_spi->dwc.num_cs; i++) { ++ fh_spi->dwc.cs_data[i].GPIO_Pin = ++ board_info->cs_data[i].GPIO_Pin; ++ fh_spi->dwc.cs_data[i].name = board_info->cs_data[i].name; ++ } ++ ++ fh_spi->dwc.rx_hs_no = board_info->rx_handshake_num; ++ fh_spi->dwc.tx_hs_no = board_info->tx_handshake_num; ++ memset(&fh_spi->dwc.dma_rx, 0, sizeof(struct _fh_spi_dma_transfer)); ++ memset(&fh_spi->dwc.dma_tx, 0, sizeof(struct _fh_spi_dma_transfer)); ++ fh_spi->dwc.complete_times = 0; ++ fh_spi->dwc.pump_data_mode = PUMP_DATA_POLL_MODE; ++ /*bind the platform data here....*/ ++ fh_spi->dwc.board_info = board_info; ++ ++ fh_spi->dwc.isr_flag = SPI_IRQ_TXEIM | SPI_IRQ_TXOIM | SPI_IRQ_RXUIM ++ | SPI_IRQ_RXOIM; ++ fh_spi->dwc.frame_mode = SPI_MOTOROLA_MODE; ++ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE; ++ ++ do { ++ status = Spi_ReadStatus(&fh_spi->dwc); ++ } while (status & 0x01); ++ ++ /*add multi wire support..*/ ++ if(board_info->ctl_wire_support & MULTI_WIRE_SUPPORT){ ++ /*get master adv info and bind the driver on it...*/ ++ p_adv_info = spi_master_get_advanced_data(p_master); ++ p_adv_info->ctl_wire_support = board_info->ctl_wire_support; ++ p_adv_info->multi_wire_func_init = spic_wire_init; ++ p_adv_info->change_to_1_wire = spi_bus_change_1_wire; ++ p_adv_info->change_to_2_wire = spi_bus_change_2_wire; ++ p_adv_info->change_to_4_wire = spi_bus_change_4_wire; ++ } ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ if(board_info->ctl_wire_support & MULTI_WIRE_SUPPORT) { ++ if (p_adv_info) ++ p_adv_info->multi_wire_func_init(p_master); ++ } ++ Spi_SetFrameFormat(&fh_spi->dwc, fh_spi->dwc.frame_mode); ++ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode); ++ Spi_DisableIrq(&fh_spi->dwc, SPI_IRQ_ALL); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ return 0; ++} ++ ++static irqreturn_t fh_spi_irq(int irq, void *dev_id) ++{ ++ u8* txbuf; ++ struct fh_spi_controller *fh_spi; ++ u32 isr_status; ++ u32 rx_fifo_capability, tx_fifo_capability; ++ u16 data; ++ unsigned size; ++ fh_spi = (struct fh_spi_controller *) dev_id; ++ data = 0x00; ++ txbuf = (u8*) fh_spi->dwc.tx_buff; ++ isr_status = Spi_Isrstatus(&fh_spi->dwc); ++ size = fh_spi->active_transfer->len; ++ if (isr_status & (SPI_IRQ_TXOIM | SPI_IRQ_RXUIM | SPI_IRQ_RXOIM)) { ++ Spi_Clearallerror(&fh_spi->dwc); ++ dev_err(&fh_spi->p_dev->dev, "spi isr status:%x\n", isr_status); ++ WARN_ON(1); ++ } ++ ++ Spi_DisableIrq(&fh_spi->dwc, fh_spi->dwc.isr_flag); ++ ++ if (fh_spi->dwc.transfer_mode == SPI_TX_RX_MODE) { ++ ++ tx_fifo_capability = tx_max(fh_spi); ++ rx_fifo_capability = rx_max(fh_spi); ++ fh_spi->dwc.rx_len += rx_fifo_capability; ++ while (rx_fifo_capability) { ++ data = Spi_ReadData(&fh_spi->dwc); ++ if (fh_spi->dwc.rx_buff != NULL) ++ *(u8 *)fh_spi->dwc.rx_buff++ = (u8) data; ++ ++ rx_fifo_capability--; ++ } ++ ++ if (fh_spi->dwc.rx_len == size) { ++ complete(&(fh_spi->done)); ++ return IRQ_HANDLED; ++ } ++ ++ fh_spi->dwc.tx_len -= tx_fifo_capability; ++ while (tx_fifo_capability) { ++ data = 0x0; ++ if (fh_spi->dwc.tx_buff != NULL) ++ data = *(u8*) fh_spi->dwc.tx_buff++; ++ Spi_WriteData(&fh_spi->dwc, data); ++ tx_fifo_capability--; ++ } ++ Spi_EnableIrq(&fh_spi->dwc, fh_spi->dwc.isr_flag); ++ ++ } else if (fh_spi->dwc.transfer_mode == SPI_ONLY_TX_MODE) { ++ tx_fifo_capability = tx_max(fh_spi); ++ ++ fh_spi->dwc.tx_len -= tx_fifo_capability; ++ while (tx_fifo_capability) { ++ Spi_WriteData(&fh_spi->dwc, *txbuf++); ++ fh_spi->dwc.tx_buff++; ++ tx_fifo_capability--; ++ } ++ if (fh_spi->dwc.tx_len == 0) { ++ complete(&(fh_spi->done)); ++ return IRQ_HANDLED; ++ } ++ /*reopen tx isr...*/ ++ Spi_EnableIrq(&fh_spi->dwc, fh_spi->dwc.isr_flag); ++ } ++ return IRQ_HANDLED; ++ ++} ++ ++static int fh_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ++{ ++ u8 bits_per_word; ++ u32 hz; ++ u32 div; ++ struct fh_spi_controller *fh_spi = spi_master_get_devdata(spi->master); ++ ++ bits_per_word = spi->bits_per_word; ++ if (t && t->bits_per_word) ++ bits_per_word = t->bits_per_word; ++ ++ /* ++ * Calculate speed: ++ * - by default, use maximum speed from ssp clk ++ * - if device overrides it, use it ++ * - if transfer specifies other speed, use transfer's one ++ */ ++ /*hz = 1000 * ss->speed_khz / ss->divider;*/ ++ hz = fh_spi->dwc.max_freq; ++ if (spi->max_speed_hz) ++ hz = min(hz, spi->max_speed_hz); ++ if (t && t->speed_hz) ++ hz = min(hz, t->speed_hz); ++ ++ div = fh_spi->dwc.apb_clock_in / hz; ++ fh_spi->dwc.div = div; ++ ++ if (hz == 0) ++ { ++ dev_err(&spi->dev, "Cannot continue with zero clock\n"); ++ WARN_ON(1); ++ return -EINVAL; ++ } ++ ++ if (bits_per_word != 8) ++ { ++ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", ++ __func__, bits_per_word); ++ return -EINVAL; ++ } ++ ++ if (spi->mode & SPI_CPOL) ++ fh_spi->dwc.cpol = SPI_POLARITY_HIGH; ++ else ++ fh_spi->dwc.cpol = SPI_POLARITY_LOW; ++ ++ if (spi->mode & SPI_CPHA) ++ fh_spi->dwc.cpha = SPI_PHASE_TX_FIRST; ++ else ++ fh_spi->dwc.cpha = SPI_PHASE_RX_FIRST; ++ ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetPolarity(&fh_spi->dwc, fh_spi->dwc.cpol); ++ Spi_SetPhase(&fh_spi->dwc, fh_spi->dwc.cpha); ++ Spi_SetBaudrate(&fh_spi->dwc, fh_spi->dwc.div); ++ Spi_SetRxdelay(&fh_spi->dwc, 1); ++ Spi_DisableIrq(&fh_spi->dwc, SPI_IRQ_ALL); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ fh_spi_setup(spi); ++ return 0; ++} ++ ++void fix_multi_xfer_mode(struct fh_spi_controller *fh_spi) { ++ struct spi_device *p_spi_dev; ++ ++ p_spi_dev = fh_spi->active_spi_dev; ++ if(p_spi_dev->dev_open_multi_wire_flag & MULTI_WIRE_SUPPORT) { ++ if((fh_spi->active_wire_width & ++ (DUAL_WIRE_SUPPORT | QUAD_WIRE_SUPPORT)) ++ && (fh_spi->dir == SPI_DATA_DIR_OUT)) { ++ fh_spi->dwc.transfer_mode = SPI_ONLY_TX_MODE; ++ } ++ else if((fh_spi->active_wire_width & ++ (DUAL_WIRE_SUPPORT | QUAD_WIRE_SUPPORT)) && ++ (fh_spi->dir == SPI_DATA_DIR_IN)) { ++ fh_spi->dwc.transfer_mode = SPI_ONLY_RX_MODE; ++ } ++ /*do not parse one wire..*/ ++ } ++} ++ ++static void spi_ctl_fix_pump_data_mode(struct fh_spi_controller *fh_spi) { ++ if ((fh_spi->dwc.rx_buff == NULL) && (fh_spi->dwc.tx_buff != NULL)) ++ fh_spi->dwc.transfer_mode = SPI_ONLY_TX_MODE; ++ else if ((fh_spi->dwc.rx_buff != NULL) && (fh_spi->dwc.tx_buff == NULL)) ++ fh_spi->dwc.transfer_mode = SPI_ONLY_RX_MODE; ++ else ++ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE; ++} ++static int isr_pump_data(struct fh_spi_controller *fh_spi) ++{ ++ struct spi_device *p_spi_dev; ++ p_spi_dev = fh_spi->active_spi_dev; ++ fh_spi->dwc.isr_flag &= ~(SPI_IRQ_TXEIM | SPI_IRQ_RXFIM); ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ spi_ctl_fix_pump_data_mode(fh_spi); ++ fh_spi->dwc.isr_flag |= SPI_IRQ_TXEIM; ++ Spi_SetTxlevlel(&fh_spi->dwc, fh_spi->dwc.fifo_len - 1); ++ Spi_EnableIrq(&fh_spi->dwc, fh_spi->dwc.isr_flag); ++ /*add spic multi wire parse*/ ++ fix_multi_xfer_mode(fh_spi); ++ if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE) ++ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE; ++ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ wait_for_completion(&fh_spi->done); ++ /*add wait spi idle..*/ ++ spi_wait_tx_only_done(fh_spi); ++ ++ return 0; ++} ++ ++static bool fh_spi_dma_chan_filter(struct dma_chan *chan, void *param) ++{ ++ int dma_channel = *(int *) param; ++ bool ret = false; ++ ++ if (chan->chan_id == dma_channel) ++ ret = true; ++ return ret; ++} ++ ++static void fh_spi_tx_rx_dma_done_rx(void *arg) ++{ ++ ++ struct fh_spi_controller *fh_spi = (struct fh_spi_controller *) arg; ++ /*printk("%s\n",__func__);*/ ++ fh_spi->dwc.complete_times++; ++ if (fh_spi->dwc.complete_times == 2) { ++ fh_spi->dwc.complete_times = 0; ++ complete(&(fh_spi->done)); ++ } ++} ++ ++static void fh_spi_tx_rx_dma_done_tx(void *arg) ++{ ++ ++ struct fh_spi_controller *fh_spi = (struct fh_spi_controller *) arg; ++ /*printk("%s\n",__func__);*/ ++ fh_spi->dwc.complete_times++; ++ if (fh_spi->dwc.complete_times == 2) { ++ fh_spi->dwc.complete_times = 0; ++ complete(&(fh_spi->done)); ++ } ++} ++ ++static void fh_spi_tx_only_dma_done(void *arg) ++{ ++ struct fh_spi_controller *fh_spi = (struct fh_spi_controller *) arg; ++ complete(&(fh_spi->done)); ++} ++ ++static void fh_spi_rx_only_dma_done(void *arg) ++{ ++ struct fh_spi_controller *fh_spi = (struct fh_spi_controller *) arg; ++ /*printk("%s\n",__func__);*/ ++ complete(&(fh_spi->done)); ++ ++} ++ ++static int dma_set_tx_para(struct fh_spi_controller *fh_spi, ++void (*call_back)(void *arg)) ++{ ++ ++ struct fh_dma_extra ext_para; ++ struct dma_slave_config *tx_config; ++ struct spi_transfer *t; ++ struct dma_chan *txchan; ++ struct scatterlist *p_sca_list; ++ unsigned int sg_size = 0; ++ int i, xfer_len, one_sg_data_len; ++ unsigned char *temp_buf; ++ int one_time_size; ++ t = fh_spi->active_transfer; ++ memset(&fh_spi->dwc.dma_tx.cfg, 0, sizeof(struct dma_slave_config)); ++ memset(&ext_para, 0, sizeof(struct fh_dma_extra)); ++ txchan = fh_spi->dwc.dma_tx.chan; ++ tx_config = &fh_spi->dwc.dma_tx.cfg; ++ if(fh_spi->dwc.board_info->data_reg_offset != 0 ) ++ tx_config->dst_addr = fh_spi->dwc.paddr + ++ fh_spi->dwc.board_info->data_reg_offset; ++ else ++ tx_config->dst_addr = fh_spi->dwc.paddr + SPI_DATA_REG_OFFSET; ++ ++ /* set the spi data tx reg */ ++ tx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ tx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ tx_config->slave_id = fh_spi->dwc.tx_hs_no; ++ tx_config->src_maxburst = 8; ++ tx_config->dst_maxburst = 8; ++ tx_config->direction = DMA_MEM_TO_DEV; ++ tx_config->device_fc = FALSE; ++ xfer_len = fh_spi->dwc.tx_len; ++ temp_buf = (unsigned char*)t->tx_buf; ++ one_time_size = SG_ONE_TIME_MAX_SIZE; ++ if (xfer_len >= one_time_size) ++ sg_size = xfer_len / one_time_size; ++ ++ if (xfer_len % one_time_size) ++ sg_size++; ++ if(sg_size > MAX_SG_LEN) { ++ printk("%s_%d :: too large sg size:0x%x\n", ++ __func__,__LINE__,sg_size); ++ return -1; ++ } ++ ++ if (fh_spi->dwc.board_info->dma_master_sel_enable == ++ SPI_DMA_MASTER_SEL_ENABLE) { ++ ext_para.master_flag = MASTER_SEL_ENABLE; ++ ext_para.dst_master = ++ fh_spi->dwc.board_info->dma_master_ctl_sel; ++ ext_para.src_master = ++ fh_spi->dwc.board_info->dma_master_mem_sel; ++ } ++ ++ p_sca_list = &fh_spi->dwc.dma_tx.sgl[0]; ++ for(i=0;i<sg_size;i++,p_sca_list++){ ++ one_sg_data_len = min(xfer_len,one_time_size); ++ xfer_len -= one_sg_data_len; ++ ++ if (t->tx_buf == NULL) ++ { ++ ext_para.sinc = FH_DMA_SLAVE_FIX; ++ p_sca_list->dma_address = fh_spi->dwc.tx_dumy_dma_add; ++ } else { ++ ext_para.sinc = FH_DMA_SLAVE_INC; ++ p_sca_list->dma_address = dma_map_single( ++ txchan->dev->device.parent, ++ (void *) temp_buf, one_sg_data_len, ++ DMA_TO_DEVICE); ++ fh_spi->dwc.dma_tx.sgl_data_size[i] = one_sg_data_len; ++ temp_buf += one_sg_data_len; ++ ++ } ++ p_sca_list->length = one_sg_data_len; ++ } ++ ++ ext_para.dinc = FH_DMA_SLAVE_FIX; ++ dmaengine_slave_config(txchan, tx_config); ++ ++ fh_spi->dwc.dma_tx.desc = txchan->device->device_prep_slave_sg(txchan, ++ &fh_spi->dwc.dma_tx.sgl[0], sg_size, DMA_MEM_TO_DEV, ++ DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP, ++ &ext_para); ++ fh_spi->dwc.dma_tx.actual_sgl_size = sg_size; ++ fh_spi->dwc.dma_tx.desc->callback = call_back; ++ fh_spi->dwc.dma_tx.desc->callback_param = fh_spi; ++ return 0; ++} ++ ++static int dma_set_rx_para(struct fh_spi_controller *fh_spi, ++void (*call_back)(void *arg), unsigned int rx_para_size, unsigned int data_width) ++{ ++ struct fh_dma_extra ext_para; ++ struct dma_slave_config *rx_config; ++ struct spi_transfer *t; ++ struct dma_chan *rxchan; ++ struct scatterlist *p_sca_list; ++ unsigned int sg_size = 0; ++ int i, xfer_len, one_sg_data_len; ++ unsigned char *temp_buf; ++ unsigned int one_time_size; ++ t = fh_spi->active_transfer; ++ rxchan = fh_spi->dwc.dma_rx.chan; ++ memset(&fh_spi->dwc.dma_rx.cfg, 0, sizeof(struct dma_slave_config)); ++ memset(&ext_para, 0, sizeof(struct fh_dma_extra)); ++ rx_config = &fh_spi->dwc.dma_rx.cfg; ++ if(fh_spi->dwc.board_info->data_reg_offset != 0 ) ++ rx_config->src_addr = ++ fh_spi->dwc.paddr + fh_spi->dwc.board_info->data_reg_offset; ++ else ++ rx_config->src_addr = fh_spi->dwc.paddr + SPI_DATA_REG_OFFSET; ++ ++ if (data_width == 8) ++ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ else if (data_width == 16) ++ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ else ++ dev_err(&fh_spi->p_dev->dev, ++ "error data width...%d\n", data_width); ++ ++ /*rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;*/ ++ rx_config->slave_id = fh_spi->dwc.rx_hs_no; ++ rx_config->src_maxburst = 8; ++ rx_config->dst_maxburst = 8; ++ rx_config->device_fc = FALSE; ++ rx_config->direction = DMA_DEV_TO_MEM; ++ xfer_len = rx_para_size; ++ temp_buf = (unsigned char *)t->rx_buf; ++ ++ if (fh_spi->dwc.board_info->dma_protctl_enable == ++ SPI_DMA_PROTCTL_ENABLE) { ++ ext_para.protctl_flag = PROTCTL_ENABLE; ++ ext_para.protctl_data = ++ fh_spi->dwc.board_info->dma_protctl_data; ++ } ++ ++ if (fh_spi->dwc.board_info->dma_master_sel_enable == ++ SPI_DMA_MASTER_SEL_ENABLE) { ++ ext_para.master_flag = MASTER_SEL_ENABLE; ++ ext_para.src_master = ++ fh_spi->dwc.board_info->dma_master_ctl_sel; ++ ext_para.dst_master = ++ fh_spi->dwc.board_info->dma_master_mem_sel; ++ } ++ ++ if (fh_spi->dwc.board_info->data_increase_support == INC_SUPPORT) { ++ if (t->rx_buf != NULL) { ++ if (((unsigned int)t->rx_buf % 4) || (xfer_len % 4)) { ++ dev_err(&fh_spi->p_dev->dev, ++ "rx buf:%x should 4B allign, size:%x should 4B allign\n", ++ (unsigned int)t->rx_buf, xfer_len); ++ BUG_ON(((unsigned int)t->rx_buf % 4) || (xfer_len % 4)); ++ } ++ } ++ ++ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ one_time_size = min((u32)SG_ONE_TIME_MAX_SIZE, ++ fh_spi->dwc.board_info->data_field_size); ++ } else { ++ /*if set 1B,do not need mem allign and size allign, ++ but mem access will use single mode and have low optimize*/ ++ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ one_time_size = SG_ONE_TIME_MAX_SIZE; ++ } ++ ++ if (xfer_len >= one_time_size) ++ sg_size = xfer_len / one_time_size; ++ ++ if (xfer_len % one_time_size) ++ sg_size++; ++ ++ if (sg_size > MAX_SG_LEN) { ++ printk("%s_%d :: too large sg size:0x%x\n", ++ __func__, __LINE__, sg_size); ++ return -1; ++ } ++ p_sca_list = &fh_spi->dwc.dma_rx.sgl[0]; ++ for (i = 0; i < sg_size; i++, p_sca_list++) ++ { ++ one_sg_data_len = min((u32)xfer_len, one_time_size); ++ xfer_len -= one_sg_data_len; ++ if (t->rx_buf == NULL) { ++ ext_para.dinc = FH_DMA_SLAVE_FIX; ++ p_sca_list->dma_address = fh_spi->dwc.rx_dumy_dma_add; ++ } else { ++ ext_para.dinc = FH_DMA_SLAVE_INC; ++ p_sca_list->dma_address = dma_map_single( ++ rxchan->dev->device.parent, ++ (void *)temp_buf, one_sg_data_len, ++ DMA_FROM_DEVICE); ++ fh_spi->dwc.dma_rx.sgl_data_size[i] = one_sg_data_len; ++ temp_buf += one_sg_data_len; ++ } ++ p_sca_list->length = one_sg_data_len; ++ } ++ ++ if (fh_spi->dwc.board_info->data_increase_support == INC_SUPPORT) ++ ext_para.sinc = FH_DMA_SLAVE_INC; ++ else ++ ext_para.sinc = FH_DMA_SLAVE_FIX; ++ ++ dmaengine_slave_config(rxchan, rx_config); ++ fh_spi->dwc.dma_rx.desc = rxchan->device->device_prep_slave_sg(rxchan, ++ &fh_spi->dwc.dma_rx.sgl[0], sg_size, DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP, ++ &ext_para); ++ fh_spi->dwc.dma_rx.actual_sgl_size = sg_size; ++ fh_spi->dwc.dma_rx.desc->callback = call_back; ++ fh_spi->dwc.dma_rx.desc->callback_param = fh_spi; ++ return 0; ++} ++ ++void unmap_dma_tx_sg(struct fh_spi_controller *fh_spi) ++{ ++ struct dma_chan *txchan; ++ struct scatterlist *p_sca_list; ++ int i; ++ ++ txchan = fh_spi->dwc.dma_tx.chan; ++ p_sca_list = &fh_spi->dwc.dma_tx.sgl[0]; ++ for (i = 0; i < fh_spi->dwc.dma_tx.actual_sgl_size; i++, p_sca_list++) ++ { ++ dma_unmap_single(txchan->dev->device.parent, ++ p_sca_list->dma_address, ++ fh_spi->dwc.dma_tx.sgl_data_size[i], DMA_MEM_TO_DEV); ++ } ++} ++ ++void unmap_dma_rx_sg(struct fh_spi_controller *fh_spi) ++{ ++ struct dma_chan *rxchan; ++ struct scatterlist *p_sca_list; ++ int i; ++ ++ rxchan = fh_spi->dwc.dma_rx.chan; ++ p_sca_list = &fh_spi->dwc.dma_rx.sgl[0]; ++ for (i = 0; i < fh_spi->dwc.dma_rx.actual_sgl_size; i++, p_sca_list++) ++ { ++ dma_unmap_single(rxchan->dev->device.parent, ++ p_sca_list->dma_address, ++ fh_spi->dwc.dma_rx.sgl_data_size[i], DMA_FROM_DEVICE); ++ } ++} ++ ++ ++static int dma_pump_tx_rx_data(struct fh_spi_controller *fh_spi) ++{ ++ ++ struct spi_transfer *t; ++ struct dma_chan *rxchan; ++ struct dma_chan *txchan; ++ int ret; ++ t = fh_spi->active_transfer; ++ txchan = fh_spi->dwc.dma_tx.chan; ++ rxchan = fh_spi->dwc.dma_rx.chan; ++ init_completion(&fh_spi->done); ++ ret = dma_set_tx_para(fh_spi, fh_spi_tx_rx_dma_done_tx); ++ if (ret != 0) ++ return ret; ++ ++ ret = dma_set_rx_para(fh_spi, fh_spi_tx_rx_dma_done_rx, ++ fh_spi->dwc.tx_len , 8); ++ if (ret != 0) { ++ unmap_dma_tx_sg(fh_spi); ++ return ret; ++ } ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetDmaRxDataLevel(&fh_spi->dwc, 7); ++ Spi_SetDmaTxDataLevel(&fh_spi->dwc, fh_spi->dwc.fifo_len - 8); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ fh_spi->dwc.dma_rx.desc->tx_submit(fh_spi->dwc.dma_rx.desc); ++ fh_spi->dwc.dma_tx.desc->tx_submit(fh_spi->dwc.dma_tx.desc); ++ Spi_SetDmaControlEnable(&fh_spi->dwc, SPI_DMA_RX_POS); ++ Spi_SetDmaControlEnable(&fh_spi->dwc, SPI_DMA_TX_POS); ++ wait_for_completion(&fh_spi->done); ++ if (t->tx_buf != NULL) ++ unmap_dma_tx_sg(fh_spi); ++ ++ if (t->rx_buf != NULL) ++ unmap_dma_rx_sg(fh_spi); ++ ++ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_RX_POS); ++ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_TX_POS); ++ return 0; ++} ++ ++static int dma_pump_tx_only_data(struct fh_spi_controller *fh_spi) ++{ ++ struct spi_transfer *t; ++ struct dma_chan *rxchan; ++ struct dma_chan *txchan; ++ int ret; ++ t = fh_spi->active_transfer; ++ txchan = fh_spi->dwc.dma_tx.chan; ++ rxchan = fh_spi->dwc.dma_rx.chan; ++ init_completion(&fh_spi->done); ++ ++ ret = dma_set_tx_para(fh_spi, fh_spi_tx_only_dma_done); ++ if (ret != 0) ++ return ret; ++ ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetDmaTxDataLevel(&fh_spi->dwc, fh_spi->dwc.fifo_len - 8); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ fh_spi->dwc.dma_tx.desc->tx_submit(fh_spi->dwc.dma_tx.desc); ++ Spi_SetDmaControlEnable(&fh_spi->dwc, SPI_DMA_TX_POS); ++ wait_for_completion(&fh_spi->done); ++ /*wait spi tx fifo done..*/ ++ spi_wait_tx_only_done(fh_spi); ++ if (t->tx_buf != NULL) ++ unmap_dma_tx_sg(fh_spi); ++ ++ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_TX_POS); ++ return 0; ++} ++ ++ ++static int dma_pump_rx_only_data(struct fh_spi_controller *fh_spi) ++{ ++ struct spi_transfer *t; ++ struct dma_chan *rxchan; ++ struct dma_chan *txchan; ++ int ret; ++ unsigned int temp_size; ++ unsigned int data_width; ++ ++ u32 raw_isr; ++ t = fh_spi->active_transfer; ++ txchan = fh_spi->dwc.dma_tx.chan; ++ rxchan = fh_spi->dwc.dma_rx.chan; ++ init_completion(&fh_spi->done); ++ temp_size = min(fh_spi->dwc.tx_len, (u32)SPI_RX_ONLY_ONE_TIME_SIZE); ++ data_width = rx_only_fix_data_width(fh_spi, temp_size); ++ ++ if (data_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 1); ++ Spi_SetWidth(&fh_spi->dwc, 16); ++ } ++ ++ ret = dma_set_rx_para(fh_spi, fh_spi_rx_only_dma_done, ++ temp_size, data_width); ++ if (ret != 0) { ++ if (data_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 0); ++ Spi_SetWidth(&fh_spi->dwc, 8); ++ } ++ return ret; ++ } ++ ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetDmaRxDataLevel(&fh_spi->dwc, 7); ++ Spi_ContinueReadNum(&fh_spi->dwc, temp_size / (data_width / 8)); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ fh_spi->dwc.dma_rx.desc->tx_submit(fh_spi->dwc.dma_rx.desc); ++ Spi_SetDmaControlEnable(&fh_spi->dwc, SPI_DMA_RX_POS); ++ Spi_WriteData(&fh_spi->dwc, 0xffffffff); ++ if (!(wait_for_completion_timeout(&fh_spi->done, 20*HZ))) { ++ raw_isr = Spi_RawIsrstatus(&fh_spi->dwc); ++ printk("%s %d time out..spi raw status is %x\n", ++ __func__, __LINE__, raw_isr); ++ if (t->rx_buf != NULL) ++ unmap_dma_rx_sg(fh_spi); ++ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_RX_POS); ++ if (data_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 0); ++ Spi_SetWidth(&fh_spi->dwc, 8); ++ } ++ return -1; ++ } ++ if (t->rx_buf != NULL) ++ unmap_dma_rx_sg(fh_spi); ++ ++ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_RX_POS); ++ /*here need to cal the data has been transfered ... ++ if we need to start a new transfer ++ then maybe i could recall the rx only func :)*/ ++ fh_spi->dwc.rx_len += temp_size; ++ fh_spi->dwc.tx_len -= temp_size; ++ fh_spi->active_transfer->rx_buf += temp_size; ++ if (data_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 0); ++ Spi_SetWidth(&fh_spi->dwc, 8); ++ } ++ return 0; ++} ++ ++static int dma_pump_data(struct fh_spi_controller *fh_spi) ++{ ++ spi_ctl_fix_pump_data_mode(fh_spi); ++ fix_multi_xfer_mode(fh_spi); ++ if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE) { ++ if (fh_spi->dwc.board_info->spidma_xfer_mode != RX_ONLY_MODE) ++ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE; ++ } ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ if (fh_spi->dwc.transfer_mode == SPI_ONLY_TX_MODE) ++ dma_pump_tx_only_data(fh_spi); ++ else if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE) { ++ do { ++ dma_pump_rx_only_data(fh_spi); ++ } while (fh_spi->dwc.tx_len != 0); ++ } else ++ dma_pump_tx_rx_data(fh_spi); ++ return 0; ++} ++ ++ ++static int poll_rx_only_with_regwidth(struct fh_spi_controller *fh_spi, ++u8 *rxbuf, u32 size, u32 reg_width) ++{ ++ register u32 rx_fifo_capability; ++ u32 otp_xfer_size; ++ u8 *rxbuf_8; ++ u16 *rxbuf_16; ++ ++ rxbuf_8 = (u8 *)rxbuf; ++ rxbuf_16 = (u16 *)rxbuf; ++ if (reg_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 1); ++ Spi_SetWidth(&fh_spi->dwc, 16); ++ } ++ /* refix size div reg_width */ ++ size = size / (reg_width / 8); ++start: ++ /* or rx fifo error.. */ ++ if (size == 0) { ++ if (reg_width == 16) { ++ Spi_SetSwap(&fh_spi->dwc, 0); ++ Spi_SetWidth(&fh_spi->dwc, 8); ++ } ++ return 0; ++ } ++ ++ otp_xfer_size = min(fh_spi->dwc.fifo_len, size); ++ size -= otp_xfer_size; ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_ContinueReadNum(&fh_spi->dwc, otp_xfer_size); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ Spi_WriteData(&fh_spi->dwc, 0xffffffff); ++ do { ++ rx_fifo_capability = rx_max(fh_spi); ++ otp_xfer_size -= rx_fifo_capability; ++ while (rx_fifo_capability) { ++ if (reg_width == 16) ++ *rxbuf_16++ = (u16)Spi_ReadData(&fh_spi->dwc); ++ else ++ *rxbuf_8++ = (u8)Spi_ReadData(&fh_spi->dwc); ++ rx_fifo_capability--; ++ } ++ } while (otp_xfer_size); ++ goto start; ++} ++ ++ ++static int rx_only_fix_data_width(struct fh_spi_controller *fh_spi, u32 size) ++{ ++ u32 data_width = 0; ++ ++ if (((int)fh_spi->dwc.rx_buff % 2) || (size % 2) || ++ (fh_spi->dwc.board_info->swap_support != SWAP_SUPPORT)) ++ data_width = 8; ++ else ++ data_width = 16; ++ return data_width; ++} ++ ++static int poll_pump_rx_only_data(struct fh_spi_controller *fh_spi) ++{ ++ u32 size; ++ u32 data_width = 0; ++ int ret; ++ ++ size = fh_spi->dwc.tx_len; ++ data_width = rx_only_fix_data_width(fh_spi, size); ++ ret = poll_rx_only_with_regwidth(fh_spi, ++ fh_spi->dwc.rx_buff, size, data_width); ++ return ret; ++} ++ ++ ++static int poll_pump_tx_rx_data(struct fh_spi_controller *fh_spi) ++{ ++ register u32 rx_fifo_capability, tx_fifo_capability; ++ u8 *txbuf; ++ u8 *rxbuf; ++ u16 data; ++ u32 size; ++ rxbuf = (u8 *)fh_spi->dwc.rx_buff; ++ txbuf = (u8 *)fh_spi->dwc.tx_buff; ++ size = fh_spi->active_transfer->len; ++ ++ goto first; ++start: ++ rx_fifo_capability = rx_max(fh_spi); ++ fh_spi->dwc.rx_len += rx_fifo_capability; ++ if (rxbuf != NULL) { ++ fh_spi->dwc.rx_buff += rx_fifo_capability; ++ while (rx_fifo_capability) { ++ *rxbuf++ = Spi_ReadData(&fh_spi->dwc); ++ rx_fifo_capability--; ++ } ++ ++ } else { ++ while (rx_fifo_capability) { ++ data = Spi_ReadData(&fh_spi->dwc); ++ rx_fifo_capability--; ++ } ++ } ++ if (fh_spi->dwc.rx_len == size) ++ return 0; ++first: ++ tx_fifo_capability = tx_max(fh_spi); ++ fh_spi->dwc.tx_len -= tx_fifo_capability; ++ if (txbuf != NULL) { ++ fh_spi->dwc.tx_buff += tx_fifo_capability; ++ while (tx_fifo_capability) { ++ Spi_WriteData(&fh_spi->dwc, *txbuf++); ++ tx_fifo_capability--; ++ } ++ ++ } else { ++ while (tx_fifo_capability) { ++ Spi_WriteData(&fh_spi->dwc, 0xff); ++ tx_fifo_capability--; ++ } ++ } ++ ++ goto start; ++} ++ ++static int poll_pump_tx_only_data(struct fh_spi_controller *fh_spi) ++{ ++ register u32 tx_fifo_capability; ++ u8 *txbuf; ++ txbuf = (u8 *) fh_spi->dwc.tx_buff; ++ /*tx_max_tx_only*/ ++ while (fh_spi->dwc.tx_len) { ++ tx_fifo_capability = tx_max_tx_only(fh_spi); ++ fh_spi->dwc.tx_len -= tx_fifo_capability; ++ while (tx_fifo_capability) { ++ Spi_WriteData(&fh_spi->dwc, *txbuf++); ++ fh_spi->dwc.tx_buff++; ++ tx_fifo_capability--; ++ } ++ } ++ /*wait idle and tx fifo empty..*/ ++ spi_wait_tx_only_done(fh_spi); ++ return 0; ++} ++ ++static int poll_pump_data(struct fh_spi_controller *fh_spi) ++{ ++ spi_ctl_fix_pump_data_mode(fh_spi); ++ /*if multi open ,recheck mode..*/ ++ fix_multi_xfer_mode(fh_spi); ++ Spi_Enable(&fh_spi->dwc, SPI_DISABLE); ++ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode); ++ Spi_Enable(&fh_spi->dwc, SPI_ENABLE); ++ if (fh_spi->dwc.transfer_mode == SPI_ONLY_TX_MODE) ++ poll_pump_tx_only_data(fh_spi); ++ else if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE) ++ poll_pump_rx_only_data(fh_spi); ++ else ++ poll_pump_tx_rx_data(fh_spi); ++ return 0; ++} ++ ++void fix_fh_spi_xfer_wire_mode(struct spi_device *spi_dev, ++struct spi_transfer *t) ++{ ++ struct spi_master *spi_master; ++ struct _spi_advanced_info *p_info; ++ spi_master = spi_dev->master; ++ p_info = &spi_master->ctl_multi_wire_info; ++ BUG_ON(spi_dev->dev_open_multi_wire_flag > ++ spi_master->ctl_multi_wire_info.ctl_wire_support); ++ if (t->xfer_wire_mode == ONE_WIRE_SUPPORT) ++ p_info->change_to_1_wire(spi_master); ++ else if (t->xfer_wire_mode == DUAL_WIRE_SUPPORT) ++ p_info->change_to_2_wire(spi_master, t->xfer_dir); ++ else if (t->xfer_wire_mode == QUAD_WIRE_SUPPORT) ++ p_info->change_to_4_wire(spi_master, t->xfer_dir); ++} ++ ++ ++static int fh_spi_handle_message(struct fh_spi_controller *fh_spi, ++struct spi_message *m) ++{ ++ bool first, last; ++ struct spi_transfer *t, *tmp_t; ++ int status = 0; ++ int cs_change; ++ struct spi_device *spi_dev; ++ struct spi_master *spi_master; ++ cs_change = 1; ++ m->actual_length = 0; ++ fh_spi->active_message = m; ++ /*get spi slave from the message bind on it.*/ ++ spi_dev = m->spi; ++ spi_master = spi_dev->master; ++ /*bind the active spi dev to the controller..*/ ++ fh_spi->active_spi_dev = spi_dev; ++ list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) ++ { ++ first = (&t->transfer_list == m->transfers.next); ++ last = (&t->transfer_list == m->transfers.prev); ++ if (first || t->speed_hz || t->bits_per_word) ++ fh_spi_setup_transfer(m->spi, t); ++ ++ if (cs_change) ++ Spi_EnableSlaveen(&fh_spi->dwc, fh_spi->dwc.slave_port); ++ cs_change = t->cs_change; ++ fh_spi->active_transfer = t; ++ fh_spi->dwc.tx_len = t->len; ++ fh_spi->dwc.rx_len = 0; ++ fh_spi->dwc.tx_buff = (void *) t->tx_buf; ++ fh_spi->dwc.rx_buff = t->rx_buf; ++ ++ if (fh_spi->dwc.board_info->dma_transfer_enable ++ == SPI_TRANSFER_USE_DMA) { ++ if (fh_spi->dwc.tx_len < DMA_TRANS_GATE_LEVEL) ++ fh_spi->dwc.pump_data_mode = PUMP_DATA_POLL_MODE; ++ else ++ fh_spi->dwc.pump_data_mode = PUMP_DATA_DMA_MODE; ++ } else { ++ fh_spi->dwc.pump_data_mode = PUMP_DATA_POLL_MODE; ++ } ++ ++ if (fh_spi->dwc.pump_data_mode == PUMP_DATA_DMA_MODE) { ++ if (fh_spi->dwc.board_info->data_increase_support == INC_SUPPORT) { ++ if (t->rx_buf != NULL) { ++ if (((unsigned int)t->rx_buf % 4) || (t->len % 4)) { ++ fh_spi->dwc.pump_data_mode = PUMP_DATA_POLL_MODE; ++ } ++ } ++ } ++ } ++ ++ if (spi_dev->dev_open_multi_wire_flag & MULTI_WIRE_SUPPORT) ++ fix_fh_spi_xfer_wire_mode(spi_dev, t); ++ ++ switch (fh_spi->dwc.pump_data_mode) { ++ case PUMP_DATA_DMA_MODE: ++ status = dma_pump_data(fh_spi); ++ /*if the dma pump data error , ++ aoto jump to the isr mode ..*/ ++ if (status == 0) { ++ break; ++ } else { ++ WARN_ON(1); ++ dev_err(&fh_spi->p_dev->dev, ++ "spi dma pump data error\n"); ++ fh_spi->dwc.pump_data_mode ++ = PUMP_DATA_POLL_MODE; ++ } ++ ++ case PUMP_DATA_ISR_MODE: ++ status = isr_pump_data(fh_spi); ++ break; ++ ++ case PUMP_DATA_POLL_MODE: ++ status = poll_pump_data(fh_spi); ++ break; ++ default: ++ status = -1; ++ WARN_ON(1); ++ dev_err(&fh_spi->p_dev->dev, ++ "spi pump data mode error..\n"); ++ } ++ ++ if (!cs_change && last) { ++ Spi_DisableSlaveen(&fh_spi->dwc, ++ fh_spi->dwc.slave_port); ++ } ++/* ++ if (t->delay_usecs) ++ udelay(t->delay_usecs); ++*/ ++ m->actual_length += t->len; ++ if (status) ++ break; ++ ++ } ++ ++ return status; ++ ++} ++ ++static void fh_spi_handle(struct work_struct *w) ++{ ++ struct fh_spi_controller ++ *fh_spi = container_of(w, struct fh_spi_controller, work); ++ unsigned long flags; ++ struct spi_message *m; ++ spin_lock_irqsave(&fh_spi->lock, flags); ++ while (!list_empty(&fh_spi->queue)) { ++ m = list_entry(fh_spi->queue.next, struct spi_message, queue); ++ list_del_init(&m->queue); ++ spin_unlock_irqrestore(&fh_spi->lock, flags); ++ m->status = fh_spi_handle_message(fh_spi, m); ++ if (m->complete) ++ m->complete(m->context); ++ ++ spin_lock_irqsave(&fh_spi->lock, flags); ++ } ++ spin_unlock_irqrestore(&fh_spi->lock, flags); ++ ++} ++ ++static int fh_spi_transfer(struct spi_device *spi, struct spi_message *m) ++{ ++ struct fh_spi_controller *fh_spi = spi_master_get_devdata(spi->master); ++ unsigned long flags; ++ ++ m->status = -EINPROGRESS; ++ spin_lock_irqsave(&fh_spi->lock, flags); ++ list_add_tail(&m->queue, &fh_spi->queue); ++ spin_unlock_irqrestore(&fh_spi->lock, flags); ++ queue_work(fh_spi->workqueue, &fh_spi->work); ++ ++ return 0; ++ ++} ++ ++static int fh_spi_setup(struct spi_device *spi) ++{ ++ /* spi_setup() does basic checks, ++ * stmp_spi_setup_transfer() does more later ++ */ ++ struct fh_spi_controller *fh_spi = spi_master_get_devdata(spi->master); ++ ++ fh_spi->dwc.active_cs_pin = ++ fh_spi->dwc.cs_data[spi->chip_select].GPIO_Pin; ++ ++ if (spi->chip_select >= fh_spi->dwc.num_cs) { ++ dev_err(&spi->dev, "%s, unsupported chip select no=%d\n", ++ __func__, spi->chip_select); ++ return -EINVAL; ++ } ++ fh_spi->dwc.slave_port = 1 << spi->chip_select; ++ ++ if (spi->bits_per_word != 8) { ++ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", ++ __func__, spi->bits_per_word); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++/*free the controller malloc data for the spi_dev*/ ++static void fh_spi_cleanup(struct spi_device *spi) ++{ ++ ++} ++ ++static int __devinit fh_spi_probe(struct platform_device *dev) ++{ ++ int err = 0; ++ struct spi_master *master; ++ struct fh_spi_controller *fh_spi; ++ struct resource *r, *ioarea; ++ int ret, i, j; ++ dma_cap_mask_t mask; ++ int filter_no; ++ /*board info below*/ ++ struct fh_spi_platform_data *spi_platform_info; ++ ++ spi_platform_info = ++ (struct fh_spi_platform_data *) dev->dev.platform_data; ++ if (spi_platform_info == NULL) { ++ ++ err = -ENODEV; ++ goto out0; ++ } ++ ++ master = spi_alloc_master(&dev->dev, sizeof(struct fh_spi_controller)); ++ if (master == NULL) { ++ err = -ENOMEM; ++ dev_err(&dev->dev, "%s, master malloc failed.\n", __func__); ++ goto out0; ++ } ++ ++ /*get the spi private data*/ ++ fh_spi = spi_master_get_devdata(master); ++ if (!fh_spi) { ++ dev_err(&dev->dev, "%s, master dev data is null.\n", __func__); ++ err = -ENOMEM; ++ /*free the spi master data*/ ++ goto out_put_master; ++ } ++ /*controller's master dev is platform dev~~*/ ++ fh_spi->master_dev = &dev->dev; ++ /*bind the platform dev*/ ++ fh_spi->p_dev = dev; ++ /*set the platform dev private data*/ ++ platform_set_drvdata(dev, master); ++ ++ fh_spi->dwc.irq = platform_get_irq(dev, 0); ++ if (fh_spi->dwc.irq < 0) { ++ dev_err(&dev->dev, "%s, spi irq no error.\n", __func__); ++ err = fh_spi->dwc.irq; ++ goto out_set_plat_drvdata_null; ++ } ++ ++ err = request_irq(fh_spi->dwc.irq, fh_spi_irq, 0, dev_name(&dev->dev), ++ fh_spi); ++ if (err) { ++ dev_dbg(&dev->dev, "request_irq failed, %d\n", err); ++ goto out_set_plat_drvdata_null; ++ } ++ ++ /* Get resources(memory, IRQ) associated with the device */ ++ r = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ err = -ENODEV; ++ /*release the irq..*/ ++ goto out_free_irq; ++ } ++ ++ fh_spi->dwc.paddr = r->start; ++ ioarea = request_mem_region(r->start, resource_size(r), dev->name); ++ if (!ioarea) { ++ dev_err(&dev->dev, "spi region already claimed\n"); ++ err = -EBUSY; ++ goto out_free_irq; ++ } ++ ++ fh_spi->dwc.regs = ioremap(r->start, resource_size(r)); ++ if (!fh_spi->dwc.regs) { ++ dev_err(&dev->dev, "spi region already mapped\n"); ++ err = -EINVAL; ++ /*free mem region*/ ++ goto out_relase_mem_region; ++ } ++ ++ INIT_WORK(&fh_spi->work, fh_spi_handle); ++ init_completion(&fh_spi->done); ++ INIT_LIST_HEAD(&fh_spi->queue); ++ spin_lock_init(&fh_spi->lock); ++ ++ fh_spi->workqueue = create_singlethread_workqueue(dev_name(&dev->dev)); ++ if (!fh_spi->workqueue) { ++ err = -ENXIO; ++ /*release mem remap*/ ++ goto out_iounmap; ++ } ++ /*spi common interface*/ ++ master->transfer = fh_spi_transfer; ++ master->setup = fh_spi_setup; ++ master->cleanup = fh_spi_cleanup; ++ ++ /* the spi->mode bits understood by this driver: */ ++ master->mode_bits = SPI_CPOL | SPI_CPHA; ++ master->bus_num = dev->id; ++ spi_platform_info->bus_no = dev->id; ++ master->num_chipselect = spi_platform_info->slave_max_num; ++ /*parse the controller board info~~~ ++ clk enable in the func ++ */ ++ ret = fh_spi_init_hw(fh_spi, spi_platform_info, master); ++ if (ret) { ++ err = ret; ++ goto out_destroy_queue; ++ } ++ fh_spi->clk = clk_get(&fh_spi->p_dev->dev, spi_platform_info->clk_name); ++ ++ if (IS_ERR(fh_spi->clk)) { ++ dev_err(&fh_spi->p_dev->dev, "cannot find the spi%d clk.\n", ++ fh_spi->dwc.id); ++ err = PTR_ERR(fh_spi->clk); ++ goto out_destroy_queue; ++ } ++ ++ clk_enable(fh_spi->clk); ++ fh_spi->dwc.apb_clock_in = clk_get_rate(fh_spi->clk); ++ if (spi_platform_info->apb_clock_in > fh_spi->dwc.apb_clock_in) { ++ clk_set_rate(fh_spi->clk, spi_platform_info->apb_clock_in); ++ fh_spi->dwc.apb_clock_in = spi_platform_info->apb_clock_in; ++ } ++ if (spi_platform_info->max_speed_support != 0) ++ fh_spi->dwc.max_freq = spi_platform_info->max_speed_support; ++ else ++ fh_spi->dwc.max_freq = fh_spi->dwc.apb_clock_in / 2; ++ for (i = 0; i < fh_spi->dwc.num_cs; i++) { ++ ret = gpio_request(fh_spi->dwc.cs_data[i].GPIO_Pin, ++ fh_spi->dwc.cs_data[i].name); ++ if (ret) { ++ dev_err(&dev->dev, ++ "spi failed to request the gpio:%d\n", ++ fh_spi->dwc.cs_data[i].GPIO_Pin); ++ /*release the gpio already request..*/ ++ if (i != 0) { ++ for (j = 0; j < i; j++) ++ gpio_free(fh_spi->dwc.cs_data[j].GPIO_Pin); ++ } ++ err = ret; ++ /*clk disable*/ ++ goto out_clk_disable; ++ } ++ /*set the dir*/ ++ gpio_direction_output(fh_spi->dwc.cs_data[i].GPIO_Pin, ++ GPIOF_OUT_INIT_HIGH); ++ } ++ /*fix:need use the platform dma channel.. not 0 and 1....*/ ++ if (fh_spi->dwc.board_info->dma_transfer_enable == ++ SPI_TRANSFER_USE_DMA) { ++ filter_no = fh_spi->dwc.board_info->tx_dma_channel; ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ fh_spi->dwc.dma_tx.chan = dma_request_channel(mask, ++ fh_spi_dma_chan_filter, &filter_no); ++ ++ if (!fh_spi->dwc.dma_tx.chan) { ++ dev_err(&fh_spi->p_dev->dev, ++ "spi%d request dma channel error....\n", ++ fh_spi->dwc.id); ++ fh_spi->dwc.board_info->dma_transfer_enable = 0; ++ goto step_register_master; ++ } ++ filter_no = fh_spi->dwc.board_info->rx_dma_channel; ++ fh_spi->dwc.dma_rx.chan = dma_request_channel(mask, ++ fh_spi_dma_chan_filter, &filter_no); ++ if (!fh_spi->dwc.dma_rx.chan) { ++ dev_err(&fh_spi->p_dev->dev, ++ "spi%d request dma channel error....\n", ++ fh_spi->dwc.id); ++ dma_release_channel(fh_spi->dwc.dma_tx.chan); ++ fh_spi->dwc.board_info->dma_transfer_enable = 0; ++ goto step_register_master; ++ } ++ ++ fh_spi->dwc.tx_dumy_dma_add = dma_map_single( ++ fh_spi->dwc.dma_tx.chan->dev->device.parent, ++ (void *) fh_spi->dwc.tx_dumy_buff, ++ sizeof(fh_spi->dwc.tx_dumy_buff), ++ DMA_TO_DEVICE); ++ ++ fh_spi->dwc.rx_dumy_dma_add = dma_map_single( ++ fh_spi->dwc.dma_rx.chan->dev->device.parent, ++ (void *) fh_spi->dwc.rx_dumy_buff, ++ sizeof(fh_spi->dwc.rx_dumy_buff), ++ DMA_TO_DEVICE); ++ } ++ ++step_register_master: ++ err = spi_register_master(master); ++ if (err) { ++ dev_dbg(&dev->dev, "cannot register spi master, %d\n", err); ++ goto out_gpio_tree; ++ } ++ ++ return 0; ++ ++out_gpio_tree: ++ for (i = 0; i < fh_spi->dwc.num_cs; i++) ++ gpio_free(fh_spi->dwc.cs_data[i].GPIO_Pin); ++out_clk_disable: ++ clk_disable(fh_spi->clk); ++out_destroy_queue: ++ destroy_workqueue(fh_spi->workqueue); ++out_iounmap: ++ iounmap(fh_spi->dwc.regs); ++out_relase_mem_region: ++ release_mem_region(r->start, resource_size(r)); ++out_free_irq: ++ free_irq(fh_spi->dwc.irq, fh_spi); ++out_set_plat_drvdata_null: ++ memset(fh_spi, 0, sizeof(struct fh_spi_controller)); ++ platform_set_drvdata(dev, NULL); ++out_put_master: ++ spi_master_put(master); ++out0: ++ return err; ++ ++} ++ ++ ++static int __devexit fh_spi_remove(struct platform_device *dev) ++{ ++ struct resource *r; ++ struct spi_master *master; ++ struct fh_spi_controller *fh_spi; ++ int i; ++ master = platform_get_drvdata(dev); ++ if (master == NULL) ++ goto out0; ++ ++ fh_spi = spi_master_get_devdata(master); ++ spi_unregister_master(master); ++ /*gpio free*/ ++ for (i = 0; i < fh_spi->dwc.num_cs; i++) ++ gpio_free(fh_spi->dwc.cs_data[i].GPIO_Pin); ++ /*clk disable*/ ++ clk_disable(fh_spi->clk); ++ /*dma free*/ ++ if (fh_spi->dwc.board_info->dma_transfer_enable == ++ SPI_TRANSFER_USE_DMA) { ++ if (fh_spi->dwc.dma_rx.chan) { ++ dma_release_channel(fh_spi->dwc.dma_rx.chan); ++ fh_spi->dwc.dma_rx.chan->private = NULL; ++ } ++ if (fh_spi->dwc.dma_tx.chan) { ++ dma_release_channel(fh_spi->dwc.dma_tx.chan); ++ fh_spi->dwc.dma_tx.chan->private = NULL; ++ } ++ } ++ /*queue free*/ ++ destroy_workqueue(fh_spi->workqueue); ++ r = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ /*io map free*/ ++ iounmap(fh_spi->dwc.regs); ++ /*mem region free*/ ++ release_mem_region(r->start, resource_size(r)); ++ /*irq free*/ ++ free_irq(fh_spi->dwc.irq, fh_spi); ++ /*clear the spi master dev data*/ ++ memset(fh_spi, 0, sizeof(struct fh_spi_controller)); ++ /*put master*/ ++ platform_set_drvdata(dev, NULL); ++ spi_master_put(master); ++ ++out0: ++ return 0; ++ ++} ++ ++static struct platform_driver fh_spi_driver = { ++ .probe = fh_spi_probe, ++ .remove = __devexit_p(fh_spi_remove), ++ .driver = { ++ .name = "fh_spi", ++ .owner = THIS_MODULE, ++ }, ++ .suspend = NULL, ++ .resume = NULL, ++}; ++ ++static int __init fh_spi_init(void) ++{ ++ return platform_driver_register(&fh_spi_driver); ++} ++ ++static void __exit fh_spi_exit(void) ++{ ++ platform_driver_unregister(&fh_spi_driver); ++} ++ ++module_init(fh_spi_init); ++module_exit(fh_spi_exit); ++MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>"); ++MODULE_DESCRIPTION("DUOBAO SPI driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/spi/fh_spi_slave.c b/drivers/spi/fh_spi_slave.c +new file mode 100644 +index 00000000..f3e864a4 +--- /dev/null ++++ b/drivers/spi/fh_spi_slave.c +@@ -0,0 +1,979 @@ ++/* ++ * fh_slave_spi.c ++ * ++ * Created on: Sep 19, 2016 ++ * Author: duobao ++ */ ++ ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/spi/spi.h> ++#include <linux/scatterlist.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/bug.h> ++#include <linux/completion.h> ++#include <linux/gpio.h> ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <mach/fh_dmac.h> ++#include <linux/fs.h> ++#include <linux/ioctl.h> ++#include <asm/io.h> ++#include <asm/uaccess.h> ++#include <mach/io.h> ++#include <linux/kfifo.h> ++#include <mach/spi.h> ++ ++#define lift_shift_bit_num(bit_num) (1<<bit_num) ++//read spi irq, only useful if you set which is masked ++#define SPI_IRQ_TXEIS (lift_shift_bit_num(0)) ++#define SPI_IRQ_TXOIS (lift_shift_bit_num(1)) ++#define SPI_IRQ_RXUIS (lift_shift_bit_num(2)) ++#define SPI_IRQ_RXOIS (lift_shift_bit_num(3)) ++#define SPI_IRQ_RXFIS (lift_shift_bit_num(4)) ++#define SPI_IRQ_MSTIS (lift_shift_bit_num(5)) ++//spi status ++#define SPI_STATUS_BUSY (lift_shift_bit_num(0)) ++#define SPI_STATUS_TFNF (lift_shift_bit_num(1)) ++#define SPI_STATUS_TFE (lift_shift_bit_num(2)) ++#define SPI_STATUS_RFNE (lift_shift_bit_num(3)) ++#define SPI_STATUS_RFF (lift_shift_bit_num(4)) ++#define SPI_STATUS_TXE (lift_shift_bit_num(5)) ++#define SPI_STATUS_DCOL (lift_shift_bit_num(6)) ++#define CACHE_LINE_SIZE (32) ++#define PUMP_DATA_NONE_MODE (0x00) ++#define PUMP_DATA_DMA_MODE (0x11) ++#define PUMP_DATA_ISR_MODE (0x22) ++#define PUMP_DATA_POLL_MODE (0x33) ++#define SPI_DIV_TRANSFER_SIZE (256) ++#define SPI_DATA_REG_OFFSET (0x60) ++#define KFIFO_SIZE 2048 ++#define DUMY_DATA 0xff ++#define SPI_SLAVE_MAX_FIFO_SIZE 256 ++#define SLAVE_SET_PHASE 1 ++#define SLAVE_SET_POLARITY SLAVE_SET_PHASE + 1 ++#define SLAVE_INIT_RX_FIFO SLAVE_SET_POLARITY + 1 ++#define SLAVE_INIT_TX_FIFO SLAVE_INIT_RX_FIFO + 1 ++#define SLAVE_GET_ERROR_STATUS SLAVE_INIT_TX_FIFO + 1 ++ ++//#define FH_SPI_SLAVE_DEBUG ++#define MAX_SPI_SLAVES 8 ++/**************************************************************************** ++ * ADT section ++ * add definition of user defined Data Type that only be used in this file here ++ ***************************************************************************/ ++enum { ++ CONFIG_OK = 0, CONFIG_PARA_ERROR = lift_shift_bit_num(0), ++ //only for the set slave en/disable ++ CONFIG_BUSY = lift_shift_bit_num(1), ++ //only for write_read mode ++ WRITE_READ_OK = 0, ++ WRITE_READ_ERROR = lift_shift_bit_num(2), ++ WRITE_READ_TIME_OUT = lift_shift_bit_num(3), ++ //only for write only mode ++ WRITE_ONLY_OK = 0, ++ WRITE_ONLY_ERROR = lift_shift_bit_num(4), ++ WRITE_ONLY_TIME_OUT = lift_shift_bit_num(5), ++ //only for read only mode ++ READ_ONLY_OK = 0, ++ READ_ONLY_ERROR = lift_shift_bit_num(6), ++ READ_ONLY_TIME_OUT = lift_shift_bit_num(7), ++ //eeprom mode ++ EEPROM_OK = 0, ++ EEPROM_ERROR = lift_shift_bit_num(8), ++ EEPROM_TIME_OUT = lift_shift_bit_num(9), ++ //if read/write/eeprom error,the error below could give you more info by reading the 'Spi_ReadTransferError' function ++ MULTI_MASTER_ERROR = lift_shift_bit_num(10), ++ TX_OVERFLOW_ERROR = lift_shift_bit_num(11), ++ RX_OVERFLOW_ERROR = lift_shift_bit_num(12), ++}; ++ ++//enable spi ++typedef enum enum_spi_enable { ++ SPI_DISABLE = 0, ++ SPI_ENABLE = (lift_shift_bit_num(0)), ++} spi_enable_e; ++ ++//polarity ++typedef enum enum_spi_polarity { ++ SPI_POLARITY_LOW = 0, ++ SPI_POLARITY_HIGH = (lift_shift_bit_num(7)), ++ //bit pos ++ SPI_POLARITY_RANGE = (lift_shift_bit_num(7)), ++} spi_polarity_e; ++ ++//phase ++typedef enum enum_spi_phase { ++ SPI_PHASE_RX_FIRST = 0, ++ SPI_PHASE_TX_FIRST = (lift_shift_bit_num(6)), ++ //bit pos ++ SPI_PHASE_RANGE = (lift_shift_bit_num(6)), ++} spi_phase_e; ++ ++//frame format ++typedef enum enum_spi_format { ++ SPI_MOTOROLA_MODE = 0x00, ++ SPI_TI_MODE = 0x10, ++ SPI_MICROWIRE_MODE = 0x20, ++ //bit pos ++ SPI_FRAME_FORMAT_RANGE = 0x30, ++} spi_format_e; ++ ++//data size ++typedef enum enum_spi_data_size { ++ SPI_DATA_SIZE_4BIT = 0x03, ++ SPI_DATA_SIZE_5BIT = 0x04, ++ SPI_DATA_SIZE_6BIT = 0x05, ++ SPI_DATA_SIZE_7BIT = 0x06, ++ SPI_DATA_SIZE_8BIT = 0x07, ++ SPI_DATA_SIZE_9BIT = 0x08, ++ SPI_DATA_SIZE_10BIT = 0x09, ++ SPI_DATA_SIZE_16BIT = 0x0f, ++ //bit pos ++ SPI_DATA_SIZE_RANGE = 0x0f, ++} spi_data_size_e; ++ ++//transfer mode ++typedef enum enum_spi_transfer_mode { ++ SPI_TX_RX_MODE = 0x000, ++ SPI_ONLY_TX_MODE = 0x100, ++ SPI_ONLY_RX_MODE = 0x200, ++ SPI_EEPROM_MODE = 0x300, ++ //bit pos ++ SPI_TRANSFER_MODE_RANGE = 0x300, ++} spi_transfer_mode_e; ++ ++//spi baudrate ++typedef enum enum_spi_baudrate { ++ SPI_SCLKIN = 50000000, ++ SPI_SCLKOUT_27000000 = (SPI_SCLKIN / 27000000), //27M ++ SPI_SCLKOUT_13500000 = (SPI_SCLKIN / 13500000), //13.5M ++ SPI_SCLKOUT_6750000 = (SPI_SCLKIN / 6750000), //6.75M ++ SPI_SCLKOUT_4500000 = (SPI_SCLKIN / 4500000), //4.5M ++ SPI_SCLKOUT_3375000 = (SPI_SCLKIN / 3375000), //3.375M ++ SPI_SCLKOUT_2700000 = (SPI_SCLKIN / 2700000), //2.7M ++ SPI_SCLKOUT_1500000 = (SPI_SCLKIN / 1500000), //1.5M ++ SPI_SCLKOUT_500000 = (SPI_SCLKIN / 500000), //0.1M ++ SPI_SCLKOUT_100000 = (SPI_SCLKIN / 100000), //0.1M ++} spi_baudrate_e; ++ ++//spi_irq ++typedef enum enum_spi_irq { ++ SPI_IRQ_TXEIM = (lift_shift_bit_num(0)), ++ SPI_IRQ_TXOIM = (lift_shift_bit_num(1)), ++ SPI_IRQ_RXUIM = (lift_shift_bit_num(2)), ++ SPI_IRQ_RXOIM = (lift_shift_bit_num(3)), ++ SPI_IRQ_RXFIM = (lift_shift_bit_num(4)), ++ SPI_IRQ_MSTIM = (lift_shift_bit_num(5)), ++ SPI_IRQ_ALL = 0x3f, ++} spi_irq_e; ++ ++//spi_slave_port ++typedef enum enum_spi_slave { ++ SPI_SLAVE_PORT0 = (lift_shift_bit_num(0)), ++ SPI_SLAVE_PORT1 = (lift_shift_bit_num(1)), ++} spi_slave_e; ++ ++//dma control ++typedef enum enum_spi_dma_control_mode { ++ SPI_DMA_RX_POS = (lift_shift_bit_num(0)), ++ SPI_DMA_TX_POS = (lift_shift_bit_num(1)), ++ //bit pos ++ SPI_DMA_CONTROL_RANGE = 0x03, ++} spi_dma_control_mode_e; ++ ++//frame format ++typedef enum enum_spi_slave_mode { ++ SPI_SLAVE_EN = 0x00, ++ SPI_SLAVE_DIS = 1 << 10, ++ //bit pos ++ SPI_SLAVE_MODE_RANGE = 1 << 10, ++} spi_slave_mode_e; ++ ++#ifdef FH_SPI_SLAVE_DEBUG ++#define SPI_SLAVE_PRINT_DBG(fmt, args...) \ ++ printk("[FH_SPI_S_DEBUG]: "); \ ++ printk(fmt, ## args) ++#else ++#define SPI_SLAVE_PRINT_DBG(fmt, args...) do { } while (0) ++#endif ++ ++struct fh_spi_reg { ++ u32 ctrl0; ++ u32 ctrl1; ++ u32 ssienr; ++ u32 mwcr; ++ u32 ser; ++ u32 baudr; ++ u32 txfltr; ++ u32 rxfltr; ++ u32 txflr; ++ u32 rxflr; ++ u32 sr; ++ u32 imr; ++ u32 isr; ++ u32 risr; ++ u32 txoicr; ++ u32 rxoicr; ++ u32 rxuicr; ++ u32 msticr; ++ u32 icr; ++ u32 dmacr; ++ u32 dmatdlr; ++ u32 dmardlr; ++ u32 idr; ++ u32 version; ++ u32 dr; /* Currently oper as 32 bits, ++ though only low 16 bits matters */ ++}; ++ ++#define dw_readl(dw, name) \ ++ __raw_readl(&(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_writel(dw, name, val) \ ++ __raw_writel((val), &(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_readw(dw, name) \ ++ __raw_readw(&(((struct fh_spi_reg *)dw->regs)->name)) ++#define dw_writew(dw, name, val) \ ++ __raw_writew((val), &(((struct fh_spi_reg *)dw->regs)->name)) ++ ++struct _fh_spi_dma_transfer { ++ //bind to dma channel ++ struct dma_chan *chan; ++ struct dma_slave_config *cfg; ++ struct scatterlist sgl; ++ struct dma_async_tx_descriptor *desc; ++}; ++ ++struct fh_spi { ++ void * __iomem regs; /* vaddr of the control registers */ ++ u32 id; ++ u32 paddr; ++ u32 slave_port; ++ u32 irq; /* irq no */ ++ u32 fifo_len; /* depth of the FIFO buffer */ ++ u32 cpol; ++ u32 cpha; ++ u32 isr_flag; ++ //clk ++ u32 apb_clock_in; ++ u32 max_freq; /* max bus freq supported */ ++ u32 div; ++ /*use id u32 bus_num;*//*which bus*/ ++ u32 num_cs; /* supported slave numbers */ ++ u32 data_width; ++ u32 frame_mode; ++ u32 transfer_mode; ++ u32 active_cs_pin; ++ //copy from the user... ++ u32 tx_len; ++ u32 rx_len; ++ void *rx_buff; ++ void *tx_buff; ++ u32 tx_dma_add; ++ u32 rx_dma_add; ++ u32 tx_hs_no; //tx handshaking number ++ u32 rx_hs_no; //rx handshaking number ++ u32 *tx_dumy_buff; ++ u32 *rx_dumy_buff; ++ struct fh_spi_cs cs_data[SPI_MASTER_CONTROLLER_MAX_SLAVE]; ++ u32 pump_data_mode; ++ struct _fh_spi_dma_transfer dma_rx; ++ struct _fh_spi_dma_transfer dma_tx; ++ u32 complete_times; ++ struct fh_spi_platform_data *board_info; ++}; ++ ++//this file private ++struct fh_spi_slave_controller { ++ struct clk *clk; ++ spinlock_t lock; ++ //message queue ++ struct platform_device *p_dev; ++ struct fh_spi dwc; ++ struct completion tx_done; ++ ++ u32 cur_rx_len; ++ u32 cur_tx_len; ++ ++ //dev interface ++ int major; ++ struct class *psClass; ++ struct device *psDev; ++ ++ //kfifo interface ++ struct kfifo kfifo_in; ++ struct kfifo kfifo_out; ++}; ++ ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++ ++/***************************************************************************** ++ * Global variables section - Exported ++ * add declaration of global variables that will be exported here ++ * e.g. ++ * int8_t foo; ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ ++ * static fun; ++ *****************************************************************************/ ++ ++static int fh_spi_slave_init_hw(struct fh_spi_slave_controller *fh_spi_slave, ++ struct fh_spi_platform_data *board_info); ++static u32 Spi_RawIsrstatus(struct fh_spi *dw); ++ ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++static struct fh_spi_slave_controller *priv_array[MAX_SPI_SLAVES] = { NULL, ++NULL, NULL, NULL, NULL, NULL, NULL, NULL }; ++ ++/* function body */ ++ ++static u32 Spi_Enable(struct fh_spi *dw, spi_enable_e enable) ++{ ++ dw_writel(dw, ssienr, enable); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity) ++{ ++ u32 data; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_POLARITY_RANGE; ++ data |= polarity; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase) ++{ ++ u32 data; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_PHASE_RANGE; ++ data |= phase; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_FRAME_FORMAT_RANGE; ++ data |= format; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_TRANSFER_MODE_RANGE; ++ data |= mode; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, imr); ++ data &= ~irq; ++ dw_writel(dw, imr, data); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_EnableIrq(struct fh_spi *dw, u32 irq) ++{ ++ u32 data = 0; ++ ++ data = dw_readl(dw, imr); ++ data |= irq; ++ dw_writel(dw, imr, data); ++ return CONFIG_OK; ++ ++} ++ ++static u32 Spi_SetTxlevlel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, txfltr, level); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_SetRxlevlel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, rxfltr, level); ++ return CONFIG_OK; ++} ++ ++static u32 Spi_ReadTxfifolevel(struct fh_spi *dw) ++{ ++ return dw_readl(dw, txflr); ++} ++ ++static u32 Spi_ReadRxfifolevel(struct fh_spi *dw) ++{ ++ return (u32) dw_readl(dw, rxflr); ++} ++ ++static u32 Spi_ReadStatus(struct fh_spi *dw) ++{ ++ return (uint8_t) dw_readl(dw, sr); ++} ++ ++static u32 Spi_SetSlaveMode(struct fh_spi *dw, spi_slave_mode_e format) ++{ ++ ++ u32 data = 0; ++ data = dw_readl(dw, ctrl0); ++ data &= ~(u32) SPI_SLAVE_MODE_RANGE; ++ data |= format; ++ dw_writel(dw, ctrl0, data); ++ return CONFIG_OK; ++ ++} ++ ++static u32 Spi_WriteData(struct fh_spi *dw, u16 data) ++{ ++ dw_writew(dw, dr, data); ++ return WRITE_ONLY_OK; ++} ++ ++static u16 Spi_ReadData(struct fh_spi *dw) ++{ ++ return dw_readw(dw, dr); ++} ++ ++#if(0) ++static void Spi_Clearallerror(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, icr); ++ data = 0; ++} ++#endif ++ ++static u32 Spi_Isrstatus(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, isr); ++ return data; ++} ++ ++static u32 Spi_RawIsrstatus(struct fh_spi *dw) ++{ ++ u32 data = dw_readl(dw, risr); ++ return data; ++} ++ ++#if(0) ++static void Spi_SetDmaTxDataLevel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, dmatdlr, level); ++} ++ ++static void Spi_SetDmaRxDataLevel(struct fh_spi *dw, u32 level) ++{ ++ dw_writel(dw, dmardlr, level); ++} ++ ++static void Spi_SetDmaControlEnable(struct fh_spi *dw, ++ spi_dma_control_mode_e enable_pos) ++{ ++ ++ u32 data; ++ ++ data = dw_readl(dw, dmacr); ++ data |= enable_pos; ++ dw_writel(dw, dmacr, data); ++} ++#endif ++ ++static int spi_slave_open(struct inode *inode, struct file *filp) ++{ ++ int i, ret = 0; ++ struct fh_spi_slave_controller *fh_spi_slave; ++ SPI_SLAVE_PRINT_DBG("%s\n", __func__); ++ //bind the pri to the spi slave control... ++ SPI_SLAVE_PRINT_DBG("inode id is %x..\n", inode->i_rdev); ++ for (i = 0; i < MAX_SPI_SLAVES; i++) { ++ SPI_SLAVE_PRINT_DBG("register id is %x..\n", ++ MKDEV(priv_array[i]->major, 0)); ++ if (priv_array[i] ++ && MKDEV(priv_array[i]->major, 0) ++ == inode->i_rdev) { ++ //SPI_SLAVE_PRINT_DBG(); ++ filp->private_data = priv_array[i]; ++ break; ++ } ++ } ++ if (i == MAX_SPI_SLAVES) ++ return -ENXIO; ++ //reset kfifo... ++ fh_spi_slave = priv_array[i]; ++ kfifo_reset(&fh_spi_slave->kfifo_in); ++ kfifo_reset(&fh_spi_slave->kfifo_out); ++ return ret; ++} ++ ++static ssize_t spi_slave_read(struct file *filp, char __user *buf, size_t count, ++ loff_t *f_pos) ++{ ++ int ret; ++ unsigned int copied; ++ struct fh_spi_slave_controller *fh_spi_slave; ++ fh_spi_slave = (struct fh_spi_slave_controller *) filp->private_data; ++ //write data to fifo_out ++ if (kfifo_is_empty(&fh_spi_slave->kfifo_out)) { ++ return -EFAULT; ++ } ++ ret = kfifo_to_user(&fh_spi_slave->kfifo_out, buf, count, &copied); ++ //start spi hw work... ++ if (ret == 0) { ++ fh_spi_slave->cur_rx_len = copied; ++ return copied; ++ } ++ //error.. ++ else { ++ ++ return ret; ++ } ++ ++ //hw isr pump fifo_out data.. ++ ++} ++ ++#if(0) ++static void wait_spi_idle(struct fh_spi_slave_controller *fh_spi_slave) { ++ int status; ++ do { ++ status = Spi_ReadStatus(&fh_spi_slave->dwc); ++ SPI_SLAVE_PRINT_DBG("status is %x\n",status); ++ }while (status & 0x01); ++} ++#endif ++ ++static void spi_slave_isr_tx_data(struct fh_spi_slave_controller *fh_spi_slave) ++{ ++ //fh_spi_slave->dwc.isr_flag = SPI_IRQ_TXEIM; ++ //Spi_SetTxlevlel(&fh_spi_slave->dwc, fh_spi_slave->dwc.fifo_len / 2); ++ Spi_SetTxlevlel(&fh_spi_slave->dwc, fh_spi_slave->dwc.fifo_len - 5); ++ SPI_SLAVE_PRINT_DBG("open spi slave isr tx..\n"); ++ Spi_EnableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM); ++ //wait_for_completion(&fh_spi_slave->tx_done); ++} ++ ++static ssize_t spi_slave_write(struct file *filp, const char __user *buf, ++ size_t count, loff_t *f_pos) ++{ ++ int ret; ++ unsigned int copied; ++ struct fh_spi_slave_controller *fh_spi_slave; ++ fh_spi_slave = (struct fh_spi_slave_controller *) filp->private_data; ++ if (kfifo_is_full(&fh_spi_slave->kfifo_in)) { ++ //spin_unlock_irqrestore(&fh_spi_slave->lock, flags); ++ return -EFAULT; ++ } ++ ret = kfifo_from_user(&fh_spi_slave->kfifo_in, buf, count, &copied); ++ //start spi hw work... ++ if (ret == 0) { ++ //start spi hw work... ++ //here we could start a back work to process the hw write data.... ++ fh_spi_slave->cur_tx_len = copied; ++ spi_slave_isr_tx_data(fh_spi_slave); ++ return copied; ++ } ++ //error.. ++ else { ++ return ret; ++ } ++ ++ ++ ++} ++ ++long spi_slave_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int err = -ENOIOCTLCMD; ++ ++ switch (cmd) { ++ case SLAVE_SET_PHASE: ++ break; ++ case SLAVE_SET_POLARITY: ++ break; ++ case SLAVE_INIT_RX_FIFO: ++ break; ++ ++ case SLAVE_INIT_TX_FIFO: ++ break; ++ ++ case SLAVE_GET_ERROR_STATUS: ++ break; ++ ++ default: ++ break; ++ } ++ ++ return err; ++} ++ ++static int spi_slave_release(struct inode *inode, struct file *filp) ++{ ++ ++ int ret = 0; ++ return ret; ++} ++ ++static struct file_operations spi_slave_fops = { ++ .open = spi_slave_open, ++ .read = spi_slave_read, ++ .write = spi_slave_write, ++ .unlocked_ioctl = spi_slave_ioctl, ++ .release = spi_slave_release, ++}; ++ ++static inline u32 tx_max(struct fh_spi_slave_controller *fh_spi_slave) ++{ ++ u32 hw_tx_level; ++ hw_tx_level = Spi_ReadTxfifolevel(&fh_spi_slave->dwc); ++ hw_tx_level = fh_spi_slave->dwc.fifo_len - hw_tx_level; ++ hw_tx_level /= 2; ++ return hw_tx_level; //min(hw_tx_level, fh_spi_slave->dwc.tx_len); ++} ++ ++/* Return the max entries we should read out of rx fifo */ ++static inline u32 rx_max(struct fh_spi_slave_controller *fh_spi_slave) ++{ ++ u32 hw_rx_level; ++ ++ hw_rx_level = Spi_ReadRxfifolevel(&fh_spi_slave->dwc); ++ return hw_rx_level; ++} ++ ++static void spi_slave_process_tx_isr( ++ struct fh_spi_slave_controller *fh_spi_slave) ++{ ++ ++ u8 tx_buff[SPI_SLAVE_MAX_FIFO_SIZE] = { 0 }; ++ int kfifo_tx_size, hw_tx_size, trans_size; ++ u16 data; ++ int i; ++ int temp; ++ //Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM); ++ //Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_RXFIM); ++ ++ kfifo_tx_size = kfifo_len(&fh_spi_slave->kfifo_in); ++ //kfifo_tx_size = fh_spi_slave->cur_tx_len; ++ hw_tx_size = tx_max(fh_spi_slave); ++ //read MIN(hw tx fifo avail size , tx kfifo size) ++ trans_size = min(kfifo_tx_size, hw_tx_size); ++ temp = kfifo_out(&fh_spi_slave->kfifo_in, tx_buff, trans_size); ++ //transfer data to hw.. and reduce the actual trans data size.. ++ SPI_SLAVE_PRINT_DBG("kfifo size :%d, hw size:%d..\n",kfifo_tx_size,hw_tx_size); ++ SPI_SLAVE_PRINT_DBG("tx isr size is %d..\n",trans_size); ++ //printk("**0d%d\n",trans_size); ++ for (i = 0; i < trans_size; i++) { ++ data = tx_buff[i]; ++ //SPI_SLAVE_PRINT_DBG("tx data is %x\n",data); ++ Spi_WriteData(&fh_spi_slave->dwc, data); ++ } ++ //SPI_SLAVE_PRINT_DBG("\n"); ++ fh_spi_slave->cur_tx_len -= trans_size; ++ if (fh_spi_slave->cur_tx_len == 0) { ++ Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM); ++ //complete(&(fh_spi_slave->tx_done)); ++ } else { ++ //Spi_EnableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM); ++ } ++ ++} ++ ++static void spi_slave_process_rx_isr( ++ struct fh_spi_slave_controller *fh_spi_slave) ++{ ++ ++ int hw_rx_size; ++ int i; ++ u16 data; ++ int status; ++ //here we try to get more data when the the clk is too high... ++ //do { ++ hw_rx_size = rx_max(fh_spi_slave); ++ SPI_SLAVE_PRINT_DBG("rx get size is 0x%d\n",hw_rx_size); ++ for (i = 0; i < hw_rx_size; i++) { ++ data = Spi_ReadData(&fh_spi_slave->dwc); ++ //rx_buff[i] = (u8) data; ++ kfifo_in(&fh_spi_slave->kfifo_out, &data, 1); ++ } ++ status = Spi_ReadStatus(&fh_spi_slave->dwc); ++ //} while (status & (1 << 3)); ++ ++} ++ ++static irqreturn_t fh_spi_slave_irq(int irq, void *dev_id) ++{ ++ struct fh_spi_slave_controller *fh_spi_slave; ++ u32 isr_status; ++ u32 raw_status; ++ ++ fh_spi_slave = (struct fh_spi_slave_controller *) dev_id; ++ isr_status = Spi_Isrstatus(&fh_spi_slave->dwc); ++ raw_status = Spi_RawIsrstatus(&fh_spi_slave->dwc); ++ //printk("raw irq status is 0x%x..\n",raw_status); ++ SPI_SLAVE_PRINT_DBG("irq status is 0x%x..\n",isr_status); ++ if(raw_status & (1<<3)){ ++ printk("[FH_SPI_S_ERROR]: rx overflow....\n"); ++ } ++ if (isr_status & SPI_IRQ_TXEIM) { ++ spi_slave_process_tx_isr(fh_spi_slave); ++ } ++ if (isr_status & SPI_IRQ_RXFIM) { ++ spi_slave_process_rx_isr(fh_spi_slave); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int __devinit fh_spi_slave_probe(struct platform_device *dev) ++{ ++ int err = 0; ++ struct resource *r,*ioarea; ++ int ret; ++ char spi_slave_name[32] = {0}; ++ char spi_slave_class_name[32] = {0}; ++ int major_id; ++ struct fh_spi_slave_controller *fh_spi_slave; ++ struct fh_spi_platform_data * spi_platform_info; ++ spi_platform_info = (struct fh_spi_platform_data *)dev->dev.platform_data; ++ if(spi_platform_info == NULL){ ++ err = -ENODEV; ++ dev_err(&dev->dev, "%s, spi slave platform data null.\n", ++ __func__); ++ BUG(); ++ ++ } ++ fh_spi_slave =kzalloc(sizeof(struct fh_spi_slave_controller), GFP_KERNEL); ++ if (!fh_spi_slave) { ++ dev_err(&dev->dev, "malloc spi slave control mem not enough\n"); ++ BUG(); ++ } ++ fh_spi_slave->dwc.irq = platform_get_irq(dev, 0); ++ if (fh_spi_slave->dwc.irq < 0) { ++ dev_err(&dev->dev, "%s, spi slave irq no error.\n", ++ __func__); ++ err = fh_spi_slave->dwc.irq; ++ BUG(); ++ } ++ err = request_irq(fh_spi_slave->dwc.irq , fh_spi_slave_irq, 0, ++ dev_name(&dev->dev), fh_spi_slave); ++ if (err) { ++ dev_dbg(&dev->dev, "request_irq failed, %d\n", err);BUG(); ++ } ++ r = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ dev_err(&dev->dev, "%s, spi slave ioresource error. \n", ++ __func__); ++ err = -ENODEV; ++ BUG(); ++ } ++ fh_spi_slave->dwc.paddr = r->start; ++ ioarea = request_mem_region(r->start, ++ resource_size(r), dev->name);if(!ioarea) { ++ dev_err(&dev->dev, "spi slave region already claimed\n"); ++ err = -EBUSY; ++ BUG(); ++ ++ } ++ fh_spi_slave->dwc.regs = ioremap(r->start, resource_size(r)); ++ if (!fh_spi_slave->dwc.regs) { ++ dev_err(&dev->dev, "spi slave region already mapped\n"); ++ err = -EINVAL; ++ BUG(); ++ } ++ spi_platform_info->bus_no = dev->id; ++ priv_array[dev->id] = fh_spi_slave; ++ init_completion(&fh_spi_slave->tx_done); ++ spin_lock_init( ++ &fh_spi_slave->lock); ++ ++ fh_spi_slave->clk = clk_get(NULL, spi_platform_info->clk_name); ++ if (IS_ERR(fh_spi_slave->clk)) { ++ dev_err(&fh_spi_slave->p_dev->dev, "cannot find the spi%d clk.\n", ++ fh_spi_slave->dwc.id); ++ err = PTR_ERR(fh_spi_slave->clk); ++ BUG(); ++ } ++ clk_enable(fh_spi_slave->clk); ++ clk_set_rate(fh_spi_slave->clk,spi_platform_info->apb_clock_in); ++ ++ ret = fh_spi_slave_init_hw(fh_spi_slave,spi_platform_info); ++ if(ret) { ++ err = ret; ++ BUG(); ++ } ++ init_completion(&fh_spi_slave->tx_done); ++ sprintf(spi_slave_name, "fh_spi_slave_%d", dev->id); ++ sprintf(spi_slave_class_name, "fh_spi_slave_class_%d", dev->id); ++ major_id = register_chrdev(0, spi_slave_name, &spi_slave_fops); ++ if (major_id <= 0) { ++ err = -EIO; ++ dev_err(&fh_spi_slave->p_dev->dev, "cannot register spi slave_%d char dev..\n", ++ fh_spi_slave->dwc.id); ++ BUG(); ++ } else { ++ fh_spi_slave->major = major_id; ++ } ++ ++ fh_spi_slave->psClass = class_create(THIS_MODULE, spi_slave_class_name);if (IS_ERR(fh_spi_slave->psClass)) { ++ err = -EIO; ++ dev_err(&fh_spi_slave->p_dev->dev, "%s: Unable to create class\n", __FILE__); ++ BUG(); ++ } ++ ++ fh_spi_slave->psDev = device_create(fh_spi_slave->psClass, NULL, MKDEV(major_id, 0), ++ fh_spi_slave, spi_slave_name); ++ if (IS_ERR(fh_spi_slave->psDev)) { ++ err = -EIO; ++ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to create device\n", __FILE__); ++ BUG(); ++ } ++ ++ if(kfifo_alloc( ++ &fh_spi_slave->kfifo_in, KFIFO_SIZE, GFP_KERNEL)){ ++ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to alloc kfifo..\n", __FILE__); ++ BUG(); ++ } ++ ++ if(kfifo_alloc(&fh_spi_slave->kfifo_out, KFIFO_SIZE, GFP_KERNEL)) { ++ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to alloc kfifo..\n", __FILE__); ++ BUG(); ++ } ++ ++ #if(0) ++ ++ //1 :empty 0:not empty ++ //1 :full 0:not full ++ int empty,full,avail; ++ char test_buf_out[20] = {0}; ++ ++ empty = kfifo_is_empty(&fh_spi_slave->kfifo_in); ++ full = kfifo_is_full(&fh_spi_slave->kfifo_in); ++ avail = kfifo_avail(&fh_spi_slave->kfifo_in); ++ printk("empty: %x, full: %x, avail: %x\n",empty,full,avail); ++ printk(KERN_INFO "queue len: %u\n", kfifo_len(&fh_spi_slave->kfifo_in)); ++ kfifo_in(&fh_spi_slave->kfifo_in, "hello", 5); ++ printk(KERN_INFO "queue len: %u\n", kfifo_len(&fh_spi_slave->kfifo_in)); ++ ++ empty = kfifo_is_empty(&fh_spi_slave->kfifo_in); ++ full = kfifo_is_full(&fh_spi_slave->kfifo_in); ++ avail = kfifo_avail(&fh_spi_slave->kfifo_in); ++ printk("empty: %x, full: %x, avail: %x\n",empty,full,avail); ++ ++ /* put values into the fifo */ ++ for (i = 0; i !=5; i++) ++ kfifo_put(&fh_spi_slave->kfifo_in, &i); ++ ++ i = kfifo_out(&fh_spi_slave->kfifo_in, test_buf_out, 5); ++ printk("data len is %d\n",i); ++ printk(KERN_INFO "buf: %.*s\n", i, test_buf_out); ++ ++ printk(KERN_INFO "queue len: %u\n", kfifo_len(&fh_spi_slave->kfifo_in)); ++ i = kfifo_out(&fh_spi_slave->kfifo_in, test_buf_out, 10); ++ printk("data len is %d\n",i); ++ printk(KERN_INFO "buf: %.*s\n", i, test_buf_out); ++ #endif ++ ++ return err; ++} ++ ++static int __devexit fh_spi_slave_remove(struct platform_device *dev) ++{ ++ return 0; ++} ++ ++static int fh_spi_slave_init_hw(struct fh_spi_slave_controller *fh_spi_slave, ++ struct fh_spi_platform_data *board_info) ++{ ++ int status; ++ fh_spi_slave->dwc.id = board_info->bus_no; ++ fh_spi_slave->dwc.fifo_len = board_info->fifo_len; ++ fh_spi_slave->dwc.rx_hs_no = board_info->rx_handshake_num; ++ fh_spi_slave->dwc.tx_hs_no = board_info->tx_handshake_num; ++ memset(&fh_spi_slave->dwc.dma_rx, 0, sizeof(struct _fh_spi_dma_transfer)); ++ memset(&fh_spi_slave->dwc.dma_tx, 0, sizeof(struct _fh_spi_dma_transfer)); ++ fh_spi_slave->dwc.pump_data_mode = PUMP_DATA_ISR_MODE; ++ //bind the platform data here.... ++ fh_spi_slave->dwc.board_info = board_info; ++ ++ fh_spi_slave->dwc.isr_flag = SPI_IRQ_RXFIM; ++ fh_spi_slave->dwc.frame_mode = SPI_MOTOROLA_MODE; ++ fh_spi_slave->dwc.transfer_mode = SPI_TX_RX_MODE; ++ fh_spi_slave->dwc.cpol = SPI_POLARITY_HIGH; ++ fh_spi_slave->dwc.cpha = SPI_PHASE_RX_FIRST; ++ do { ++ status = Spi_ReadStatus(&fh_spi_slave->dwc); ++ } while (status & 0x01); ++ //add spi disable ++ Spi_Enable(&fh_spi_slave->dwc, SPI_DISABLE); ++ //add spi frame mode & transfer mode ++ Spi_SetFrameFormat(&fh_spi_slave->dwc, fh_spi_slave->dwc.frame_mode); ++ Spi_SetTransferMode(&fh_spi_slave->dwc, fh_spi_slave->dwc.transfer_mode); ++ Spi_SetPolarity(&fh_spi_slave->dwc, fh_spi_slave->dwc.cpol); ++ Spi_SetPhase(&fh_spi_slave->dwc, fh_spi_slave->dwc.cpha); ++ //Spi_SetRxlevlel(&fh_spi_slave->dwc, fh_spi_slave->dwc.fifo_len / 2); ++ Spi_SetRxlevlel(&fh_spi_slave->dwc, 0); ++ Spi_SetSlaveMode(&fh_spi_slave->dwc, SPI_SLAVE_EN); ++ //add spi disable all isr ++ Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_ALL); ++ Spi_EnableIrq(&fh_spi_slave->dwc, fh_spi_slave->dwc.isr_flag); ++ //add spi enable ++ Spi_Enable(&fh_spi_slave->dwc, SPI_ENABLE); ++ ++ return 0; ++ ++} ++ ++static struct platform_driver fh_spi_slave_driver = { ++ .probe = fh_spi_slave_probe, ++ .remove = __devexit_p(fh_spi_slave_remove), ++ .driver = { ++ .name = "fh_spi_slave", ++ .owner = THIS_MODULE, ++ }, ++ .suspend =NULL, ++ .resume = NULL, ++}; ++ ++static int __init fh_spi_slave_init(void) ++{ ++ return platform_driver_register(&fh_spi_slave_driver); ++} ++ ++static void __exit fh_spi_slave_exit(void) ++{ ++ platform_driver_unregister(&fh_spi_slave_driver); ++} ++ ++module_init(fh_spi_slave_init); ++module_exit(fh_spi_slave_exit); ++MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>"); ++MODULE_DESCRIPTION("DUOBAO SPI SLAVE driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 2e13a14b..b423fe92 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -318,7 +318,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) + } + + spi->master = master; +- spi->dev.parent = dev; ++ spi->dev.parent = &master->dev; + spi->dev.bus = &spi_bus_type; + spi->dev.release = spidev_release; + device_initialize(&spi->dev); +diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig +index b3692e6e..925c7cff 100644 +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -1635,4 +1635,32 @@ config SERIAL_XILINX_PS_UART_CONSOLE + help + Enable a Xilinx PS UART port to be the system console. + ++config SERIAL_FH ++ tristate "FH UART support" ++ select SERIAL_CORE ++ help ++ This driver supports the FH UART port. ++ ++config SERIAL_FH_CONSOLE ++ bool "FH UART console support" ++ depends on SERIAL_FH=y ++ select SERIAL_CORE_CONSOLE ++ help ++ Enable a FH UART port to be the system console. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + endmenu +diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile +index cb2628fe..4cae882c 100644 +--- a/drivers/tty/serial/Makefile ++++ b/drivers/tty/serial/Makefile +@@ -96,3 +96,7 @@ obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o + obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o + obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o + obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o ++obj-$(CONFIG_SERIAL_FH) += fh_serial.o ++ ++ ++ +diff --git a/drivers/tty/serial/fh_serial.c b/drivers/tty/serial/fh_serial.c +new file mode 100644 +index 00000000..a1d4bdc4 +--- /dev/null ++++ b/drivers/tty/serial/fh_serial.c +@@ -0,0 +1,1617 @@ ++#if defined(CONFIG_SERIAL_FH_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++#define SUPPORT_SYSRQ ++#endif ++ ++#include <linux/module.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/init.h> ++#include <linux/sysrq.h> ++#include <linux/console.h> ++#include <linux/tty.h> ++#include <linux/tty_flip.h> ++#include <linux/serial_core.h> ++#include <linux/serial.h> ++#include <linux/delay.h> ++#include <linux/clk.h> ++#include <linux/cpufreq.h> ++#include <linux/moduleparam.h> ++#include <linux/ratelimit.h> ++#include <linux/serial_reg.h> ++#include <linux/nmi.h> ++#include <linux/mutex.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++#include <linux/interrupt.h> ++#include <linux/err.h> ++#include <linux/sched.h> ++#include <linux/timex.h> ++#include <asm/irq.h> ++#include <asm/mach/irq.h> ++#include "fh_serial.h" ++#include <linux/completion.h> ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <mach/pmu.h> ++#include <linux/scatterlist.h> ++#include <linux/syslog.h> ++#include <mach/fh_dmac_regs.h> ++#include <mach/chip.h> ++/********************************* ++ * ++ * fh private ++ * ++ *********************************/ ++#define REG_UART_RBR (0x0000) ++#define REG_UART_THR (0x0000) ++#define REG_UART_DLL (0x0000) ++#define REG_UART_DLH (0x0004) ++#define REG_UART_IER (0x0004) ++#define REG_UART_IIR (0x0008) ++#define REG_UART_FCR (0x0008) ++#define REG_UART_LCR (0x000c) ++#define REG_UART_MCR (0x0010) ++#define REG_UART_LSR (0x0014) ++#define REG_UART_MSR (0x0018) ++#define REG_UART_SCR (0x001c) ++#define REG_UART_FAR (0x0070) ++#define REG_UART_TFR (0x0074) ++#define REG_UART_RFW (0x0078) ++#define REG_UART_USR (0x007c) ++#define REG_UART_TFL (0x0080) ++#define REG_UART_RFL (0x0084) ++#define REG_UART_SRR (0x0088) ++#define REG_UART_SFE (0x0098) ++#define REG_UART_SRT (0x009c) ++#define REG_UART_STET (0x00a0) ++#define REG_UART_HTX (0x00a4) ++#define REG_UART_DMASA (0x00a8) ++#define REG_UART_CPR (0x00f4) ++#define REG_UART_UCV (0x00f8) ++#define REG_UART_CTR (0x00fc) ++ ++#define DBGLINE() printk(KERN_DEBUG \ ++ "file: %s\tfunc:%s\tline:%d\n",\ ++ __FILE__, __func__, __LINE__) ++#define FH_SERIAL_NAME "ttyS" ++#define FH_DRIVE_NAME "ttyS" ++#define FH_DEV_NAME "ttyS" ++ ++#define UART_DMA_TRANSFER_LEN (8) ++ ++#define UART_READ_RX_DW_FIFO_OK 0 ++#define UART_READ_RX_DW_FIFO_TIME_OUT 0xcc ++#define MAP_SIZE 0x80000 ++ ++#ifdef CONFIG_SERIAL_FH_CONSOLE ++static struct console fh_serial_console; ++#define FH_SERIAL_CONSOLE (&fh_serial_console) ++#else ++#define FH_SERIAL_CONSOLE NULL ++#endif ++ ++#define tx_enabled(port) ((port)->unused[0]) ++#define rx_enabled(port) ((port)->unused[1]) ++#define FH_TYPE (99) ++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) ++#define fh_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) ++ ++ ++#define fh_uart_readl(addr) \ ++ __raw_readl(addr) ++#define fh_uart_writel(addr, val) \ ++ __raw_writel((val), addr) ++ ++#define fh_uart_readw(addr) \ ++ __raw_readw(addr) ++#define fh_uart_writew(addr, val) \ ++ __raw_writew((val), addr) ++ ++/****************************************************************************** ++ * Function prototype section ++ * add prototypes for all functions called by this file,execepting those ++ * declared in header file ++ *****************************************************************************/ ++static void fh_uart_pm(struct uart_port *port, unsigned int level, ++ unsigned int old); ++static void fh_uart_stop_tx(struct uart_port *port); ++static void fh_uart_start_tx(struct uart_port *port); ++static void fh_uart_stop_rx(struct uart_port *port); ++static void fh_uart_start_rx(struct uart_port *port); ++static void fh_uart_enable_ms(struct uart_port *port); ++static unsigned int fh_uart_tx_empty(struct uart_port *port); ++static unsigned int fh_uart_get_mctrl(struct uart_port *port); ++static void fh_uart_set_mctrl(struct uart_port *port, unsigned int mctrl); ++static void fh_uart_break_ctl(struct uart_port *port, int break_state); ++static irqreturn_t fh_uart_rx_chars(int irq, void *dev_id); ++static irqreturn_t fh_uart_tx_chars(int irq, void *dev_id); ++static irqreturn_t fh_uart_isr(int irq, void *dev_id); ++static void fh_serial_shutdown(struct uart_port *port); ++static int fh_serial_startup(struct uart_port *port); ++static void fh_serial_set_termios(struct uart_port *port, ++ struct ktermios *termios, ++ struct ktermios *old); ++static const char *fh_serial_type(struct uart_port *port); ++static void fh_serial_release_port(struct uart_port *port); ++static int fh_serial_request_port(struct uart_port *port); ++static void fh_serial_config_port(struct uart_port *port, int flags); ++static int fh_uart_set_wake(struct uart_port *, unsigned int state); ++ ++struct fh_uart_port *to_fh_uart_port(struct uart_port *port); ++struct fh_uart_port *info_to_fh_uart_port(fh_uart_info *info); ++static bool fh_uart_dma_chan_filter(struct dma_chan *chan, void *param); ++static void fh_serial_dma_tx_char_done(void *arg); ++static void fh_serial_dma_rx_callback(void *arg); ++static void fh_serial_dma_rx_char(void *arg); ++static int uart_dma_set_rx_para(struct fh_uart_port *fh_uart_dma, int xfer_len, ++ void (*call_back)(void *arg)); ++static int uart_dma_set_tx_para(struct fh_uart_port *fh_uart_dma, int xfer_len, ++ void (*call_back)(void *arg)); ++static void fh_serial_dma_tx_char(struct fh_uart_port *uart_dma); ++/***************************************************************************** ++ * Global variables section - Local ++ * define global variables(will be refered only in this file) here, ++ * static keyword should be used to limit scope of local variable to this file ++ * e.g. ++ * static uint8_t ufoo; ++ *****************************************************************************/ ++static struct uart_ops fh_serial_ops = { ++ .pm = fh_uart_pm, ++ .tx_empty = fh_uart_tx_empty, ++ .get_mctrl = fh_uart_get_mctrl, ++ .set_mctrl = fh_uart_set_mctrl, ++ .stop_tx = fh_uart_stop_tx, ++ .start_tx = fh_uart_start_tx, ++ .stop_rx = fh_uart_stop_rx, ++ .enable_ms = fh_uart_enable_ms, ++ .break_ctl = fh_uart_break_ctl, ++ .startup = fh_serial_startup, ++ .shutdown = fh_serial_shutdown, ++ .set_termios = fh_serial_set_termios, ++ .type = fh_serial_type, ++ .release_port = fh_serial_release_port, ++ .request_port = fh_serial_request_port, ++ .config_port = fh_serial_config_port, ++ .set_wake = fh_uart_set_wake, ++ .verify_port = NULL, ++}; ++ ++static struct uart_driver fh_uart_drv = { ++ .owner = THIS_MODULE, ++ .driver_name = FH_DRIVE_NAME, ++ .nr = FH_UART_NUMBER, ++ .cons = FH_SERIAL_CONSOLE, ++ .dev_name = FH_DEV_NAME, ++ .major = 4, ++ .minor = 64, ++}; ++ ++#if (defined(CONFIG_ARCH_FH8810) || defined(CONFIG_ARCH_WUDANG)) ++#define UART_PORT0_ISR ISR_NUMBER1 ++#define UART_PORT1_ISR ISR_NUMBER0 ++#define UART_PORT0_BASE UART1_REG_BASE ++#define UART_PORT1_BASE UART0_REG_BASE ++#define UART_PORT0(x) VUART1(x) ++#define UART_PORT1(x) VUART0(x) ++#else ++#define UART_PORT0_ISR ISR_NUMBER0 ++#define UART_PORT0(x) VUART0(x) ++#define UART_PORT0_BASE UART0_REG_BASE ++#if FH_UART_NUMBER >= 2 ++#define UART_PORT1_ISR ISR_NUMBER1 ++#define UART_PORT1_BASE UART1_REG_BASE ++#define UART_PORT1(x) VUART1(x) ++#endif ++#if FH_UART_NUMBER >= 3 ++#define UART_PORT2_ISR ISR_NUMBER2 ++#define UART_PORT2_BASE UART2_REG_BASE ++#define UART_PORT2(x) VUART2(x) ++#endif ++#if FH_UART_NUMBER >= 4 ++#define UART_PORT3_ISR ISR_NUMBER3 ++#define UART_PORT3_BASE UART3_REG_BASE ++#define UART_PORT3(x) VUART3(x + 0x100) ++#endif ++#endif ++ ++static struct fh_uart_port fh_own_ports[FH_UART_NUMBER] = { ++ [0] = { ++ .port = { ++ .lock = __SPIN_LOCK_UNLOCKED(fh_own_ports[0].port.lock), ++ .iotype = UPIO_MEM, ++ .irq = UART_PORT0_ISR, ++ .uartclk = UART_CLOCK_FREQ, ++ .fifosize = UART0_FIFO_SIZE, ++ .ops = &fh_serial_ops, ++ .flags = UPF_BOOT_AUTOCONF, ++ .line = 0, ++ .mapbase = UART_PORT0_BASE, ++ .membase = (unsigned char __iomem *)UART_PORT0(UART_PORT0_BASE), ++ }, ++ .fh_info = { ++ .name = "FH UART0", ++ .irq_num = UART_PORT0_ISR, ++ .base_add = (unsigned char __iomem *)UART_PORT0(UART_PORT0_BASE), ++ .baudrate = BAUDRATE_115200, ++ .line_ctrl = Uart_line_8n2, ++ .fifo_ctrl = UART_INT_RXFIFO_DEPTH_QUARTER, ++ } ++ }, ++#if FH_UART_NUMBER >= 2 ++ [1] = { ++ .port = { ++ .lock = __SPIN_LOCK_UNLOCKED(fh_own_ports[1].port.lock), ++ .iotype = UPIO_MEM, ++ .irq = UART_PORT1_ISR, ++ .uartclk = UART_CLOCK_FREQ, ++ .fifosize = UART1_FIFO_SIZE, ++ .ops = &fh_serial_ops, ++ .flags = UPF_BOOT_AUTOCONF, ++ .line = 1, ++ .mapbase = UART_PORT1_BASE, ++ .membase = (unsigned char __iomem *)UART_PORT1(UART_PORT1_BASE), ++ ++ }, ++ .fh_info = { ++ .name = "FH UART1", ++ .irq_num = UART_PORT1_ISR, ++ .base_add = (unsigned char __iomem *)UART_PORT1(UART_PORT1_BASE), ++ .baudrate = BAUDRATE_115200, ++ .line_ctrl = Uart_line_8n2, ++ .fifo_ctrl = UART_DMA_RXFIFO_DEPTH_HALF, ++ .use_dma = 0, ++ }, ++ .uart_dma = { ++ .tx_hs_no = UART1_TX_HW_HANDSHAKE, ++ .rx_hs_no = UART1_RX_HW_HANDSHAKE, ++ .tx_dma_channel = UART1_DMA_TX_CHAN, ++ .rx_dma_channel = UART1_DMA_RX_CHAN, ++ .rx_xmit_len = UART_DMA_TRANSFER_LEN, ++ } ++ }, ++#endif ++#if FH_UART_NUMBER >= 3 ++ [2] = { ++ .port = { ++ .lock = __SPIN_LOCK_UNLOCKED(fh_own_ports[2].port.lock), ++ .iotype = UPIO_MEM, ++ .irq = UART_PORT2_ISR, ++ .uartclk = UART_CLOCK_FREQ, ++ .fifosize = UART2_FIFO_SIZE, ++ .ops = &fh_serial_ops, ++ .flags = UPF_BOOT_AUTOCONF, ++ .line = 2, ++ .mapbase = UART_PORT2_BASE, ++ .membase = (unsigned char __iomem *)UART_PORT2(UART_PORT2_BASE), ++ ++ }, ++ .fh_info = { ++ .name = "FH UART2", ++ .irq_num = UART_PORT2_ISR, ++ .base_add = (unsigned char __iomem *)UART_PORT2(UART_PORT2_BASE), ++ .baudrate = BAUDRATE_115200, ++ .line_ctrl = Uart_line_8n2, ++ .fifo_ctrl = UART_INT_RXFIFO_DEPTH_QUARTER, ++ } ++ }, ++#endif ++#if FH_UART_NUMBER >= 4 ++ [3] = { ++ .port = { ++ .lock = __SPIN_LOCK_UNLOCKED(fh_own_ports[3].port.lock), ++ .iotype = UPIO_MEM, ++ .irq = UART_PORT3_ISR, ++ .uartclk = UART_CLOCK_FREQ, ++ .fifosize = UART3_FIFO_SIZE, ++ .ops = &fh_serial_ops, ++ .flags = UPF_BOOT_AUTOCONF, ++ .line = 3, ++ .mapbase = UART_PORT3_BASE, ++ .membase = (unsigned char __iomem *)UART_PORT3(UART_PORT3_BASE), ++ ++ }, ++ .fh_info = { ++ .name = "FH UART3", ++ .irq_num = UART_PORT3_ISR, ++ .base_add = (unsigned char __iomem *)UART_PORT3(UART_PORT3_BASE), ++ .baudrate = BAUDRATE_115200, ++ .line_ctrl = Uart_line_8n2, ++ .fifo_ctrl = UART_INT_RXFIFO_DEPTH_QUARTER, ++ } ++ }, ++#endif ++}; ++ ++struct fh_uart_port *to_fh_uart_port(struct uart_port *port) ++{ ++ return container_of(port, struct fh_uart_port, port); ++ ++} ++ ++struct fh_uart_port *info_to_fh_uart_port(fh_uart_info *info) ++{ ++ return container_of(info, struct fh_uart_port, fh_info); ++ ++} ++ ++s32 Uart_Disable_Irq(fh_uart_info *desc, uart_irq_e interrupts) ++{ ++ u32 ret; ++ u32 base = (u32)desc->base_add; ++ ++ ret = fh_uart_readl(base + REG_UART_IER); ++ ret &= ~interrupts; ++ fh_uart_writel(base+REG_UART_IER, ret); ++ ++ return UART_CONFIG_OK; ++} ++ ++s32 Uart_Enable_Irq(fh_uart_info *desc, uart_irq_e interrupts) ++{ ++ u32 ret; ++ u32 base = (u32)desc->base_add; ++ ++ ret = fh_uart_readl(base); ++ ret |= interrupts; ++ fh_uart_writel(base + REG_UART_IER, ret); ++ ++ return UART_CONFIG_OK; ++ ++} ++ ++s32 Uart_Fifo_Config(fh_uart_info *desc) ++{ ++ u32 ret; ++ u32 base = (u32)desc->base_add; ++ ++ fh_uart_writel(base + REG_UART_FCR, desc->fifo_ctrl); ++ ret = fh_uart_readl(base + REG_UART_IIR); ++ ++ if (ret & UART_FIFO_IS_ENABLE) ++ return UART_CONFIG_FIFO_OK; ++ else ++ return UART_CONFIG_FIFO_ERROR; ++} ++ ++s32 Uart_Read_Control_Status(fh_uart_info *desc) ++{ ++ u32 base = (u32)desc->base_add; ++ return fh_uart_readl(base + REG_UART_USR); ++} ++ ++s32 Uart_Set_Line_Control(fh_uart_info *desc) ++{ ++ u32 ret; ++ u32 base = (u32)desc->base_add; ++ ++ ret = Uart_Read_Control_Status(desc); ++ if (ret & UART_STATUS_BUSY) ++ return UART_IS_BUSY; ++ ++ fh_uart_writel(base + REG_UART_LCR, desc->line_ctrl); ++ return UART_CONFIG_LINE_OK; ++} ++ ++s32 Uart_Read_Line_Status(fh_uart_info *desc) ++{ ++ u32 base = (u32)desc->base_add; ++ return fh_uart_readl(base + REG_UART_LSR); ++} ++ ++s32 Uart_Set_Clock_Divisor(fh_uart_info *desc) ++{ ++ u32 low, high, ret; ++ u32 base = (u32)desc->base_add; ++ ++ low = desc->baudrate & 0x00ff; ++ high = (desc->baudrate & 0xff00) >> 8; ++ ++ ret = Uart_Read_Control_Status(desc); ++ if (ret & UART_STATUS_BUSY) ++ return UART_IS_BUSY; ++ ++ ret = fh_uart_readl(base + REG_UART_LCR); ++ /* if DLAB not set */ ++ if (!(ret & UART_LCR_DLAB_POS)) { ++ ret |= UART_LCR_DLAB_POS; ++ fh_uart_writel(base + REG_UART_LCR, ret); ++ } ++ fh_uart_writel(base + REG_UART_DLL, low); ++ fh_uart_writel(base + REG_UART_DLH, high); ++ ++ /* clear DLAB */ ++ ret = ret & 0x7f; ++ fh_uart_writel(base + REG_UART_LCR, ret); ++ ++ return UART_CONFIG_DIVISOR_OK; ++} ++ ++s32 Uart_Read_iir(fh_uart_info *desc) ++{ ++ u32 base = (u32)desc->base_add; ++ return fh_uart_readl(base + REG_UART_IIR); ++} ++ ++static bool fh_uart_dma_chan_filter(struct dma_chan *chan, void *param) ++{ ++ int dma_channel = *(int *) param; ++ bool ret = false; ++ if (chan->chan_id == dma_channel) ++ ret = true; ++ return ret; ++} ++static void fh_serial_dma_tx_char_done(void *arg) ++{ ++ struct fh_uart_port *uart_dma = (struct fh_uart_port *)arg; ++ uart_dma->port.icount.tx += uart_dma->uart_dma.tx_count; ++ uart_dma->uart_dma.tx_done = 1; ++} ++static void fh_serial_dma_rx_char(void *arg) ++{ ++ struct fh_uart_port *uart_dma = (struct fh_uart_port *)arg; ++ struct uart_port *port = &uart_dma->port; ++ struct tty_struct *tty = uart_dma->port.state->port.tty; ++ unsigned int uerstat; ++ unsigned int flag; ++ unsigned int xmit_len; ++ unsigned int i; ++ xmit_len = uart_dma->uart_dma.rx_xmit_len; ++ uart_dma->port.icount.rx += xmit_len; ++ uerstat = Uart_Read_Line_Status(&uart_dma->fh_info); ++ flag = TTY_NORMAL; ++ if (unlikely(uerstat & UART_LINE_STATUS_RFE)) { ++ printk(KERN_INFO "rxerr: port rxs=0x%08x\n", uerstat); ++ if (uerstat & UART_LINE_STATUS_BI) { ++ port->icount.brk++; ++ if (uart_handle_break(port)) ++ goto dma_ignore_char; ++ } ++ } ++ if (uerstat & UART_LINE_STATUS_PE) ++ port->icount.parity++; ++ if (uerstat & UART_LINE_STATUS_BI) ++ port->icount.frame++; ++ if (uerstat & UART_LINE_STATUS_OE) ++ port->icount.overrun++; ++ uerstat &= port->read_status_mask; ++ if (uerstat & UART_LINE_STATUS_BI) ++ flag = TTY_BREAK; ++ else if (uerstat & UART_LINE_STATUS_PE) ++ flag = TTY_PARITY; ++ else if (uerstat & (UART_LINE_STATUS_FE | ++ UART_LINE_STATUS_OE)) ++ flag = TTY_FRAME; ++ for (i = uart_dma->uart_dma.rx_rd_ptr; \ ++ i < uart_dma->uart_dma.rx_rd_ptr + xmit_len; i++) { ++ if (!uart_handle_sysrq_char(&uart_dma->port, \ ++ uart_dma->uart_dma.rx_dumy_buff[i])) { ++ uart_insert_char(&uart_dma->port, uerstat, \ ++ UART_LINE_STATUS_OE,\ ++ uart_dma->uart_dma.rx_dumy_buff[i], flag); ++ } ++ } ++dma_ignore_char: ++ tty_flip_buffer_push(tty); ++} ++static int uart_dma_set_rx_para(struct fh_uart_port *fh_uart_dma, ++ int xfer_len, ++ void (*call_back)(void *arg)) ++{ ++ struct fh_dma_extra ext_para; ++ struct dma_slave_config *rx_config; ++ struct dma_chan *rxchan; ++ struct scatterlist *p_sca_list; ++ unsigned int sg_size = 1; ++ memset(&fh_uart_dma->uart_dma.dma_rx.cfg, ++ 0, ++ sizeof(struct dma_slave_config)); ++ memset(&ext_para, 0, sizeof(struct fh_dma_extra)); ++ p_sca_list = &fh_uart_dma->uart_dma.dma_rx.sgl[0]; ++ rxchan = fh_uart_dma->uart_dma.dma_rx.chan; ++ rx_config = &fh_uart_dma->uart_dma.dma_rx.cfg; ++ rx_config->src_addr = fh_uart_dma->uart_dma.paddr + REG_UART_RBR; ++ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ rx_config->slave_id = fh_uart_dma->uart_dma.rx_hs_no; ++ rx_config->src_maxburst = 8; ++ rx_config->dst_maxburst = 8; ++ rx_config->direction = DMA_DEV_TO_MEM; ++ rx_config->device_fc = 0; ++ ext_para.sinc = FH_DMA_SLAVE_FIX; ++ p_sca_list->dma_address = fh_uart_dma->uart_dma.rx_dma_add \ ++ + fh_uart_dma->uart_dma.rx_wr_ptr; ++ p_sca_list->length = min(xfer_len, 128); ++ ext_para.dinc = FH_DMA_SLAVE_INC; ++ dmaengine_slave_config(rxchan, rx_config); ++ fh_uart_dma->uart_dma.dma_rx.desc = ++ rxchan->device->device_prep_slave_sg(rxchan, ++ &fh_uart_dma->uart_dma.dma_rx.sgl[0], sg_size, DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP, ++ &ext_para); ++ fh_uart_dma->uart_dma.dma_rx.actual_sgl_size = sg_size; ++ fh_uart_dma->uart_dma.dma_rx.desc->callback = fh_serial_dma_rx_callback; ++ fh_uart_dma->uart_dma.dma_rx.desc->callback_param = fh_uart_dma; ++ return 0; ++} ++static void fh_serial_dma_rx_callback(void *arg) ++{ ++ struct fh_uart_port *port = (struct fh_uart_port *)arg; ++ port->uart_dma.rx_wr_ptr = ++ (port->uart_dma.rx_wr_ptr + port->uart_dma.rx_xmit_len) & (128 - 1); ++ fh_serial_dma_rx_char(port); ++ port->uart_dma.rx_rd_ptr = port->uart_dma.rx_wr_ptr; ++ uart_dma_set_rx_para(port, ++ port->uart_dma.rx_xmit_len, ++ fh_serial_dma_rx_callback); ++ port->uart_dma.dma_rx.desc->tx_submit(port->uart_dma.dma_rx.desc); ++} ++static int uart_dma_set_tx_para(struct fh_uart_port *fh_uart_dma, ++ int xfer_len, ++ void (*call_back)(void *arg)) ++{ ++ struct fh_dma_extra ext_para; ++ struct dma_slave_config *tx_config; ++ struct dma_chan *txchan; ++ struct scatterlist *p_sca_list; ++ unsigned int sg_size = 1; ++ memset(&fh_uart_dma->uart_dma.dma_tx.cfg, ++ 0, ++ sizeof(struct dma_slave_config)); ++ memset(&ext_para, 0, sizeof(struct fh_dma_extra)); ++ p_sca_list = &fh_uart_dma->uart_dma.dma_tx.sgl[0]; ++ txchan = fh_uart_dma->uart_dma.dma_tx.chan; ++ tx_config = &fh_uart_dma->uart_dma.dma_tx.cfg; ++ tx_config->dst_addr = fh_uart_dma->uart_dma.paddr + REG_UART_THR; ++ tx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ tx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; ++ tx_config->slave_id = fh_uart_dma->uart_dma.tx_hs_no; ++ tx_config->src_maxburst = 1; ++ tx_config->dst_maxburst = 1; ++ tx_config->direction = DMA_MEM_TO_DEV; ++ tx_config->device_fc = 0; ++ ext_para.sinc = FH_DMA_SLAVE_FIX; ++ p_sca_list->dma_address = fh_uart_dma->uart_dma.tx_dma_add; ++ p_sca_list->length = min(xfer_len, 128); ++ ext_para.dinc = FH_DMA_SLAVE_INC; ++ dmaengine_slave_config(txchan, tx_config); ++ fh_uart_dma->uart_dma.dma_tx.desc = ++ txchan->device->device_prep_slave_sg(txchan, ++ &fh_uart_dma->uart_dma.dma_tx.sgl[0], sg_size, DMA_MEM_TO_DEV, ++ DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_DEST_UNMAP, ++ &ext_para); ++ fh_uart_dma->uart_dma.dma_tx.actual_sgl_size = sg_size; ++ fh_uart_dma->uart_dma.dma_tx.desc->callback = fh_serial_dma_tx_char_done; ++ fh_uart_dma->uart_dma.dma_tx.desc->callback_param = fh_uart_dma; ++ return 0; ++} ++static void fh_serial_dma_tx_char(struct fh_uart_port *uart_dma) ++{ ++ unsigned int xfer_len; ++ struct circ_buf *xmit = &uart_dma->port.state->xmit; ++ if (uart_circ_empty(xmit) || uart_tx_stopped(&uart_dma->port)) { ++ uart_dma->uart_dma.tx_done = 1; ++ uart_dma->uart_dma.tx_done = 0; ++ return; ++ } ++ if (uart_dma->uart_dma.tx_done) { ++ xfer_len = ++ uart_circ_chars_pending(xmit); /* Check xfer length */ ++ if (xfer_len > 128) ++ xfer_len = 128; ++ if (xmit->tail < xmit->head) { ++ memcpy(uart_dma->uart_dma.tx_dumy_buff, ++ &xmit->buf[xmit->tail], ++ xfer_len); ++ } else { ++ int first = UART_XMIT_SIZE - xmit->tail; ++ int second = xmit->head; ++ memcpy(uart_dma->uart_dma.tx_dumy_buff, ++ &xmit->buf[xmit->tail], ++ first); ++ if (second) ++ memcpy(&uart_dma->uart_dma.tx_dumy_buff[first], ++ &xmit->buf[0], ++ second); ++ } ++ xmit->tail = (xmit->tail + xfer_len) & (UART_XMIT_SIZE - 1); ++ uart_dma->uart_dma.tx_count = xfer_len; ++ uart_dma_set_tx_para( ++ uart_dma, ++ xfer_len, ++ fh_serial_dma_tx_char_done); ++ uart_dma->uart_dma.dma_tx.desc->tx_submit(uart_dma->uart_dma.dma_tx.desc); ++ uart_dma->uart_dma.tx_done = 0; ++ } ++} ++void fh_uart_rx_dma_start(struct fh_uart_port *port) ++{ ++ uart_dma_set_rx_para(port, ++ port->uart_dma.rx_xmit_len, ++ fh_serial_dma_rx_callback); ++ port->uart_dma.dma_rx.desc->tx_submit(port->uart_dma.dma_rx.desc); ++} ++ ++s32 Uart_Init(fh_uart_info *desc) ++{ ++ ++ u32 base = (u32)desc->base_add; ++ struct fh_uart_port *port = info_to_fh_uart_port(desc); ++ u8 test_init_status = 0; ++ ++ /* reset fifo */ ++ fh_uart_writel(base + REG_UART_FCR, 6); ++ test_init_status |= Uart_Set_Clock_Divisor(desc); ++ test_init_status |= Uart_Set_Line_Control(desc); ++ test_init_status |= Uart_Fifo_Config(desc); ++ if (test_init_status != 0) ++ return test_init_status; ++ ++ Uart_Disable_Irq(desc, UART_INT_ALL); ++ if (!port->fh_info.use_dma) ++ fh_uart_start_rx(&port->port); ++ else { ++ if (!port->uart_dma.HasInit) { ++ port->uart_dma.HasInit = 1; ++ fh_uart_rx_dma_start(port); ++ } ++ } ++ return 0; ++} ++ ++ ++ ++/********************************* ++ * ++ * ++ * FH CONSOLE ++ * ++ * ++ *********************************/ ++#ifdef CONFIG_SERIAL_FH_CONSOLE ++static struct uart_port *cons_uart; ++ ++static void ++fh_serial_console_putchar(struct uart_port *port, int ch) ++{ ++ u32 ret; ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ ++ do { ++ ret = (u8)Uart_Read_Control_Status(&myown_port->fh_info); ++ } ++ /* wait txfifo is full ++ * 0 means full. ++ * 1 means not full ++ */ ++ while (!(ret & UART_STATUS_TFNF)) ++ ; ++ ++ fh_uart_writel(myown_port->fh_info.base_add + REG_UART_THR, ch); ++} ++ ++static void ++fh_serial_console_write(struct console *co, const char *s, ++ unsigned int count) ++{ ++ struct fh_uart_port *myown_port = &fh_own_ports[co->index]; ++ uart_console_write(&myown_port->port, ++ s, ++ count, ++ fh_serial_console_putchar); ++} ++ ++ ++static int __init ++fh_serial_console_setup(struct console *co, ++ char *options) ++{ ++ struct uart_port *port; ++ int baud = 115200; ++ int bits = 8; ++ int parity = 'n'; ++ int flow = 'n'; ++ /* is this a valid port */ ++ if ((co->index == -1) || (co->index >= FH_UART_NUMBER)) ++ pr_err("ERROR: co->index invaild: %d\n", co->index); ++ ++ port = &fh_own_ports[co->index].port; ++ ++ /* is the port configured? */ ++ if (port->mapbase == 0x0) ++ pr_err("ERROR: port->mapbase == 0x0\n"); ++ ++ cons_uart = port; ++ /* ++ * Check whether an invalid uart number has been specified, and ++ * if so, search for the first available port that does have ++ * console support. ++ */ ++ if (options) ++ uart_parse_options(options, &baud, &parity, &bits, &flow); ++ uart_set_options(port, co, baud, parity, bits, flow); ++ ++ /* must true for setup ok, see printk.c line:1463 */ ++ return 1; ++} ++ ++ ++int fh_serial_initconsole(void) ++{ ++ fh_serial_console.data = &fh_uart_drv; ++ register_console(&fh_serial_console); ++ return 0; ++} ++console_initcall(fh_serial_initconsole); ++ ++static struct console fh_serial_console = { ++ .name = FH_SERIAL_NAME, ++ .device = uart_console_device, ++ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, ++ .index = -1, ++ .write = fh_serial_console_write, ++ .setup = fh_serial_console_setup, ++ .data = &fh_uart_drv, ++}; ++ ++#endif /* CONFIG_SERIAL_FH_CONSOLE */ ++ ++static void fh_uart_stop_tx(struct uart_port *port) ++{ ++ /* close tx isr */ ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ struct circ_buf *xmit = &myown_port->port.state->xmit; ++ u32 base = (u32)myown_port->fh_info.base_add; ++ if (!myown_port->fh_info.use_dma) ++ fh_uart_writel(base + REG_UART_IER, 0x01); ++ else{ ++ xmit->tail = ++ (xmit->tail + myown_port->uart_dma.tx_count) & (UART_XMIT_SIZE - 1); ++ myown_port->port.icount.tx += myown_port->uart_dma.tx_count; ++ myown_port->uart_dma.tx_count = 0; ++ myown_port->uart_dma.tx_done = 1; ++ } ++ tx_enabled(port) = 0; ++ fh_uart_writel(base + REG_UART_IER, 0x01); ++} ++ ++static void fh_uart_start_tx(struct uart_port *port) ++{ ++ /* open tx isr */ ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ ++ if (!myown_port->fh_info.use_dma) { ++ u32 base = (u32)myown_port->fh_info.base_add; ++ fh_uart_writel(base + REG_UART_IER, 0x03); ++ tx_enabled(port) = 1; ++ } else { ++ if (myown_port->uart_dma.tx_done) { ++ fh_serial_dma_tx_char(myown_port); ++ tx_enabled(port) = 1; ++ } ++ } ++} ++ ++static void fh_uart_stop_rx(struct uart_port *port) ++{ ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ rx_enabled(port) = 0; ++ Uart_Disable_Irq(&myown_port->fh_info, UART_INT_ERBFI_POS); ++} ++ ++static void fh_uart_start_rx(struct uart_port *port) ++{ ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ rx_enabled(port) = 1; ++ Uart_Enable_Irq(&myown_port->fh_info, UART_INT_ERBFI_POS); ++} ++ ++static void fh_uart_pm(struct uart_port *port, unsigned int level, ++ unsigned int old) ++{ ++ ++} ++ ++static int fh_uart_set_wake(struct uart_port *port, unsigned int state) ++{ ++ return 0; ++} ++ ++ ++static void fh_uart_enable_ms(struct uart_port *port) ++{ ++ ++} ++ ++ ++static unsigned int fh_uart_tx_empty(struct uart_port *port) ++{ ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ /* ++ * 1 means empty ++ * 0:means no empty ++ */ ++ int ret = 1; ++ int ret_status; ++ ++ ret_status = (u8)Uart_Read_Control_Status(&myown_port->fh_info); ++ if (ret_status & UART_STATUS_TFE) ++ ret = 1; ++ else ++ ret = 0; ++ return ret; ++} ++ ++ ++static unsigned int fh_uart_get_mctrl(struct uart_port *port) ++{ ++ return 0; ++} ++ ++ ++static void fh_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ ++} ++ ++static void fh_uart_break_ctl(struct uart_port *port, int break_state) ++{ ++ ++} ++ ++static irqreturn_t ++fh_uart_rx_chars(int irq, void *dev_id) ++{ ++ struct fh_uart_port *myown_port = dev_id; ++ struct uart_port *port = &myown_port->port; ++ struct tty_struct *tty = port->state->port.tty; ++ unsigned int ch = 0; ++ unsigned int flag; ++ unsigned int uerstat; ++ int max_count = 64; ++ int ret_status; ++ ++ while (max_count-- > 0) { ++ /* check if rx fifo is empty */ ++ ret_status = (u8)Uart_Read_Control_Status(&myown_port->fh_info); ++ if (!(ret_status & UART_STATUS_RFNE)) ++ break; ++ /* read error in the rx process */ ++ uerstat = Uart_Read_Line_Status(&myown_port->fh_info); ++ /* read data in the rxfifo */ ++ if (uerstat & UART_LINE_STATUS_DR) ++ ch = fh_uart_readl(myown_port->fh_info.base_add + REG_UART_RBR); ++ /* insert the character into the buffer */ ++ flag = TTY_NORMAL; ++ port->icount.rx++; ++ /* if at least one error in rx process */ ++ if (unlikely(uerstat & UART_LINE_STATUS_RFE)) { ++ pr_err("rxerr: port ch=0x%02x, rxs=0x%08x\n", ++ ch, uerstat); ++ /* check for break */ ++ if (uerstat & UART_LINE_STATUS_BI) { ++ port->icount.brk++; ++ if (uart_handle_break(port)) ++ goto ignore_char; ++ } ++ ++ if (uerstat & UART_LINE_STATUS_BI) ++ port->icount.frame++; ++ if (uerstat & UART_LINE_STATUS_OE) ++ port->icount.overrun++; ++ ++ uerstat &= port->read_status_mask; ++ ++ if (uerstat & UART_LINE_STATUS_BI) ++ flag = TTY_BREAK; ++ else if (uerstat & UART_LINE_STATUS_PE) ++ flag = TTY_PARITY; ++ else if (uerstat & (UART_LINE_STATUS_FE | ++ UART_LINE_STATUS_OE)) ++ flag = TTY_FRAME; ++ } ++ ++ if (uart_handle_sysrq_char(port, ch)) ++ goto ignore_char; ++ ++ uart_insert_char(port, uerstat, UART_LINE_STATUS_OE, ++ ch, flag); ++ ++ ignore_char: ++ continue; ++ } ++ tty_flip_buffer_push(tty); ++ return IRQ_HANDLED; ++} ++ ++ ++ ++static irqreturn_t ++fh_uart_tx_chars(int irq, void *dev_id) ++{ ++ struct fh_uart_port* myown_port = dev_id; ++ struct uart_port *port = &myown_port->port; ++ struct circ_buf *xmit = &port->state->xmit; ++ int count = 256; ++ int ret_status; ++ ++ /* if there isn't anything more to transmit, or the uart is now ++ * stopped, disable the uart and exit ++ */ ++ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { ++ fh_uart_stop_tx(port); ++ goto out; ++ } ++ /* try and drain the buffer... */ ++ while (!uart_circ_empty(xmit) && count-- > 0) { ++ ++ /* ++ * check the tx fifo full? ++ * full then break ++ */ ++ ret_status = (u8)Uart_Read_Control_Status(&myown_port->fh_info); ++ if(!(ret_status & UART_STATUS_TFNF)) ++ break; ++ /* write data to the hw fifo */ ++ fh_uart_writel(myown_port->fh_info.base_add + REG_UART_THR, \ ++ xmit->buf[xmit->tail]); ++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ++ port->icount.tx++; ++ } ++ ++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ uart_write_wakeup(port); ++ ++ if (uart_circ_empty(xmit)) ++ fh_uart_stop_tx(port); ++out: ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t ++fh_uart_isr(int irq, void *dev_id) ++{ ++ irqreturn_t ret_isr; ++ struct fh_uart_port* myown_port = dev_id; ++ int ret_iir; ++ ++ /* check if the tx empty isr */ ++ ret_iir = Uart_Read_iir(&myown_port->fh_info); ++ if (ret_iir == 0x06) ++ pr_err("uart overrun\n"); ++ ++ if ((ret_iir & 0x04)||(ret_iir & 0x0c)) ++ ret_isr = fh_uart_rx_chars(irq,dev_id); ++ ++ if (ret_iir & 0x02) ++ ret_isr = fh_uart_tx_chars(irq,dev_id); ++ else ++ ret_isr = IRQ_HANDLED; ++ ++ return ret_isr; ++} ++ ++static void fh_serial_shutdown(struct uart_port *port) ++{ ++ struct fh_uart_port* myown_port = to_fh_uart_port(port); ++ ++ Uart_Disable_Irq(&myown_port->fh_info,UART_INT_ALL); ++ fh_uart_writel( myown_port->fh_info.base_add + REG_UART_FCR, 6); ++ free_irq(myown_port->fh_info.irq_num, myown_port); ++ tx_enabled(port) = 0; ++ rx_enabled(port) = 0; ++} ++ ++static int fh_serial_startup(struct uart_port *port) ++{ ++ struct fh_uart_port* myown_port = to_fh_uart_port(port); ++ int ret; ++ int status; ++ ++ do { ++ status = Uart_Read_Line_Status(&myown_port->fh_info); ++ ++ } while ((status & BOTH_EMPTY) != BOTH_EMPTY); ++ ++ Uart_Init(&myown_port->fh_info); ++ if ((ret = request_irq(myown_port->fh_info.irq_num, ++ fh_uart_isr, ++ 0, ++ FH_DEV_NAME, ++ (void*)myown_port))) { ++ pr_err("cannot get irq %d\n", myown_port->fh_info.irq_num); ++ return ret; ++ } ++ ++ enable_irq_wake(myown_port->fh_info.irq_num); ++ ++ return 0; ++} ++ ++static void fh_serial_set_termios(struct uart_port *port, ++ struct ktermios *termios, ++ struct ktermios *old) ++{ ++ struct fh_uart_port* myown_port = to_fh_uart_port(port); ++ ++ unsigned long flags; ++ unsigned int baud, quot; ++ unsigned int line_data = 0,status; ++ ++ do { ++ status = Uart_Read_Line_Status(&myown_port->fh_info); ++ ++ } while ((status & BOTH_EMPTY) != BOTH_EMPTY); ++ ++ switch (termios->c_cflag & CSIZE) { ++ case CS5: ++ line_data |= UART_LCR_WLEN5; ++ break; ++ case CS6: ++ line_data |= UART_LCR_WLEN6; ++ break; ++ case CS7: ++ line_data |= UART_LCR_WLEN7; ++ break; ++ case CS8: ++ line_data |= UART_LCR_WLEN8; ++ break; ++ default: ++ line_data |= UART_LCR_WLEN8; ++ break; ++ } ++ /* stop bits */ ++ if (termios->c_cflag & CSTOPB) ++ line_data |= UART_LCR_STOP; ++ ++ if (termios->c_cflag & PARENB) { ++ line_data |= UART_LCR_PARITY; ++ ++ if (!(termios->c_cflag & PARODD)) ++ line_data |= UART_LCR_EPAR; ++ } ++ /* ++ * baud cal. ++ * baud is the uart will be out. ++ * the quot is the div ++ */ ++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); ++ quot = uart_get_divisor(port, baud); ++ ++ do{ ++ status = Uart_Read_Line_Status(&myown_port->fh_info); ++ } while ((status & BOTH_EMPTY) != BOTH_EMPTY); ++ ++ uart_update_timeout(port, termios->c_cflag, baud); ++ spin_lock_irqsave(&myown_port->port.lock, flags); ++ ++ myown_port->port.read_status_mask = ++ UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; ++ if (termios->c_iflag & INPCK) ++ myown_port->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; ++ if (termios->c_iflag & (BRKINT | PARMRK)) ++ myown_port->port.read_status_mask |= UART_LSR_BI; ++ ++ /* ++ * Characters to ignore ++ */ ++ myown_port->port.ignore_status_mask = 0; ++ if (termios->c_iflag & IGNPAR) ++ myown_port->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; ++ if (termios->c_iflag & IGNBRK) { ++ myown_port->port.ignore_status_mask |= UART_LSR_BI; ++ /* ++ * If we're ignoring parity and break indicators, ++ * ignore overruns too (for real raw support). ++ */ ++ if (termios->c_iflag & IGNPAR) ++ myown_port->port.ignore_status_mask |= UART_LSR_OE; ++ } ++ ++ /* ++ * ignore all characters if CREAD is not set ++ */ ++ if ((termios->c_cflag & CREAD) == 0) ++ myown_port->port.ignore_status_mask |= UART_LSR_DR; ++ ++ ++ myown_port->fh_info.line_ctrl = (uart_line_e)line_data; ++ myown_port->fh_info.baudrate = quot; ++ myown_port->fh_info.fifo_ctrl = UART_INT_RXFIFO_DEPTH_QUARTER; ++ Uart_Init(&myown_port->fh_info); ++ spin_unlock_irqrestore(&myown_port->port.lock, flags); ++} ++ ++ ++ ++static const char *fh_serial_type(struct uart_port *port) ++{ ++ return FH_SERIAL_NAME; ++} ++ ++static void fh_serial_release_port(struct uart_port *port) ++{ ++ release_mem_region(port->mapbase, MAP_SIZE); ++} ++ ++static int fh_serial_request_port(struct uart_port *port) ++{ ++ struct fh_uart_port* myown_port = to_fh_uart_port(port); ++ const char* name = myown_port->fh_info.name; ++ return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY; ++} ++ ++ ++static void fh_serial_config_port(struct uart_port *port, int flags) ++{ ++ if (flags & UART_CONFIG_TYPE) { ++ fh_serial_request_port(port); ++ port->type = FH_TYPE; ++ } ++} ++ ++static int fh_serial_init_port(struct fh_uart_port *myown_port, ++ ++ struct platform_device *platdev) ++{ ++ struct uart_port *port = &myown_port->port; ++ struct resource *res; ++ ++ if (platdev == NULL) ++ return -ENODEV; ++ ++ ++ myown_port->fh_info.dev = platdev; ++ /* setup info for port */ ++ port->dev = &platdev->dev; ++ ++ /* sort our the physical and virtual addresses for each UART */ ++ res = platform_get_resource(platdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ printk(KERN_ERR "failed to find memory resource for uart\n"); ++ return -EINVAL; ++ } ++ ++ myown_port->uart_dma.paddr = res->start; ++ myown_port->fh_info.baudrate = BAUDRATE_115200; ++ if (myown_port->fh_info.use_dma) ++ myown_port->fh_info.fifo_ctrl = 0x8f; ++ else ++ myown_port->fh_info.fifo_ctrl = UART_INT_RXFIFO_DEPTH_QUARTER; ++ myown_port->fh_info.line_ctrl = Uart_line_8n2; ++ ++ Uart_Init(&myown_port->fh_info); ++ return 0; ++} ++ ++static inline int fh_serial_cpufreq_register(struct fh_uart_port* myown_port) ++{ ++ return 0; ++} ++ ++static ssize_t fh_serial_show_clksrc(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "* %s\n", FH_SERIAL_NAME); ++} ++ ++static DEVICE_ATTR(clock_source, S_IRUGO, fh_serial_show_clksrc, NULL); ++ ++#ifdef CONFIG_PM ++static int fh_serial_suspend(struct platform_device *pdev, ++ pm_message_t state) ++{ ++ struct uart_port *port = platform_get_drvdata(pdev); ++ ++ uart_suspend_port(&fh_uart_drv, port); ++ ++ return 0; ++} ++ ++static int fh_serial_resume(struct platform_device *pdev) ++{ ++ struct uart_port *port = platform_get_drvdata(pdev); ++ int may_wakeup; ++ ++ may_wakeup = device_may_wakeup(&pdev->dev); ++ ++ uart_resume_port(&fh_uart_drv, port); ++ device_set_wakeup_enable(&pdev->dev, may_wakeup); ++ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_MAGIC_SYSRQ ++static unsigned int SysrqParseHex(char *buff) ++{ ++ unsigned int data; ++ ++ data = (unsigned int)simple_strtoul(buff, NULL, 16); ++ return data; ++} ++ ++static int SysrqGetSingle(void) ++{ ++ struct fh_uart_port* myown_port; ++ unsigned int ch; ++ ++ myown_port = &fh_own_ports[0]; ++ while (1) { ++ if ((fh_uart_readl(myown_port->fh_info.base_add + REG_UART_LSR) & 0x01) == 0x01) { ++ ch = fh_uart_readl(myown_port->fh_info.base_add + REG_UART_RBR) & 0xff; ++ return ch; ++ } ++ } ++} ++ ++static int SysrqGetValue(void) ++{ ++ unsigned char internal_buffer[11] = {0}; ++ unsigned char loop = 0; ++ unsigned char data; ++ unsigned int value; ++ struct fh_uart_port *myown_port; ++ ++ myown_port = &fh_own_ports[0]; ++ while (1) { ++ if ((fh_uart_readl(myown_port->fh_info.base_add + REG_UART_LSR) & 0x01) == 0x01) { ++ data = fh_uart_readl(myown_port->fh_info.base_add + REG_UART_RBR) & 0xff; ++ /*Get Next Param*/ ++ if (data == ' ' || data == '\r' || data == '\n') { ++ internal_buffer[loop] = '\0'; ++ value = SysrqParseHex(internal_buffer); ++ return value; ++ } else { ++ internal_buffer[loop] = data; ++ loop++; ++ if (loop >= sizeof(internal_buffer)) { ++ printk(KERN_INFO "Address or length Error!\n"); ++ return 0; ++ } ++ } ++ } ++ } ++} ++ ++static int SysrqGetDirection(void) ++{ ++ unsigned int ch; ++ ++ ch = SysrqGetSingle(); ++ if (ch == 'w' || ch == 'W') ++ return 1; ++ else if (ch == 'r' || ch == 'R') ++ return 0; ++ else ++ return -1; ++} ++ ++static int SysrqGetMode(void) ++{ ++ unsigned int ch; ++ ++ ch = SysrqGetSingle(); ++ if (ch == 'v' || ch == 'V') ++ return 1; ++ else if (ch == 'p' || ch == 'P') ++ return 0; ++ else ++ return -1; ++} ++ ++static void sysrq_handle_fh_mem(int key) ++{ ++ unsigned int ch; ++ unsigned int mode; ++ unsigned int direction; ++ unsigned int vir_address; ++ unsigned int phy_address; ++ unsigned int len; ++ unsigned int start = 0; ++ ++ direction = SysrqGetDirection(); ++ if (direction == 1) { ++ printk(KERN_INFO "Write Mode(p or v)\n"); ++ mode = SysrqGetMode(); ++ if (mode == 0) { ++ printk(KERN_INFO \ ++ "Physical Address Write:\n"); ++ phy_address = SysrqGetValue(); ++ len = SysrqGetValue(); ++ printk(KERN_INFO \ ++ "Start Physical Address : 0x%x\n", phy_address); ++ printk(KERN_INFO "Write Data : 0x%x\n", len); ++ vir_address = __phys_to_virt(phy_address); ++ writel(len, vir_address); ++ printk(KERN_INFO \ ++ "Address:0x%x at 0x%x\n", vir_address, len); ++ } else if (mode == 1) { ++ printk(KERN_INFO \ ++ "Virtual Address Write:\n"); ++ vir_address = SysrqGetValue(); ++ len = SysrqGetValue(); ++ writel(len, vir_address); ++ printk(KERN_INFO \ ++ "Address:0x%x at 0x%x\n", vir_address, len); ++ } else { ++ printk(KERN_INFO "Select Wrong Mode!\n"); ++ return; ++ } ++ } else if (direction == 0) { ++ printk(KERN_INFO "Read Mode(p or v)\n"); ++ mode = SysrqGetMode(); ++ if (mode == 0) { ++ printk(KERN_INFO \ ++ "Physical Address Read:\n"); ++ phy_address = SysrqGetValue(); ++ len = SysrqGetValue(); ++ printk(KERN_INFO \ ++ "Start Physical Address : 0x%x\n", phy_address); ++ printk(KERN_INFO \ ++ "Read Length : 0x%x\n", len); ++ vir_address = __phys_to_virt(phy_address); ++ for (; start < len; start++) { ++ if (start % 8 == 0) ++ printk(KERN_INFO "\n%02x:", ++ (vir_address + start * 4) & 0xff); ++ ch = readl((vir_address + start * 4)); ++ printk("%08x ", ch); ++ } ++ } else if (mode == 1) { ++ printk(KERN_INFO \ ++ "Virtual Address Read:\n"); ++ vir_address = SysrqGetValue(); ++ len = SysrqGetValue(); ++ printk(KERN_INFO \ ++ "Read Length : 0x%x\n", len); ++ for (; start < len; start++) { ++ if (start % 8 == 0) ++ printk(KERN_INFO "\n%02x:", ++ (vir_address + start * 4) & 0xff); ++ ch = readl((vir_address + start * 4)); ++ printk("%08x ", ch); ++ } ++ } else { ++ printk(KERN_INFO "Select Wrong Mode!\n"); ++ return; ++ } ++ } else { ++ printk(KERN_INFO "Select Wrong Direction!\n"); ++ return; ++ } ++ ++} ++ ++static void fh_show_syslog(char *log_buf, int len) ++{ ++ for (; len; len--) { ++ if (*log_buf == 0x0a) { ++ fh_serial_console_putchar(&fh_own_ports[0].port, '\r'); ++ fh_serial_console_putchar(&fh_own_ports[0].port, '\n'); ++ log_buf++; ++ } ++ fh_serial_console_putchar(&fh_own_ports[0].port, *log_buf); ++ log_buf++; ++ } ++} ++ ++ ++static void sysrq_handle_fh_dmesg(int key) ++{ ++ int len; ++ char *log_buf = NULL; ++ ++ /* Just Dummy */ ++ len = 16 * 1024; ++ len = do_syslog(SYSLOG_ACTION_SIZE_UNREAD, \ ++ log_buf, len, SYSLOG_FROM_CALL); ++ log_buf = kmalloc(len, GFP_KERNEL); ++ if (log_buf == NULL) { ++ pr_info("Get Syslog Buffer failed!\n"); ++ return; ++ } ++ memset((void *)log_buf, 0x0, len); ++ do_syslog(SYSLOG_ACTION_READ, log_buf, len, SYSLOG_FROM_CALL); ++ fh_show_syslog(log_buf, len); ++ kfree(log_buf); ++} ++ ++ ++static struct sysrq_key_op sysrq_fh_debug_mem_op = { ++ .handler = sysrq_handle_fh_mem, ++ .help_msg = "Fullhan Debug Dump Mem(G)", ++ .action_msg = "Fullhan Dump Mem(w or r)", ++ .enable_mask = SYSRQ_ENABLE_DUMP, ++}; ++ ++static struct sysrq_key_op sysrq_fh_dmesg_op = { ++ .handler = sysrq_handle_fh_dmesg, ++ .help_msg = "Fullhan DMSG(x)", ++ .action_msg = "Fullhan DMSG", ++ .enable_mask = SYSRQ_ENABLE_DUMP, ++}; ++ ++ ++#endif ++ ++int fh_serial_probe(struct platform_device *dev) ++{ ++ int ret = 0; ++ struct fh_uart_port *myown_port; ++ int filter_no; ++ dma_cap_mask_t mask; ++ struct clk *uart_clk; ++ char clk_name[16]; ++ ++ if (dev->id > (sizeof(fh_own_ports)/sizeof(struct fh_uart_port))) ++ goto probe_err; ++ ++ sprintf(clk_name, "uart%d_clk", dev->id); ++ uart_clk = clk_get(NULL, clk_name); ++ if (IS_ERR(uart_clk)) ++ return PTR_ERR(uart_clk); ++ ret = clk_enable(uart_clk); ++ if (ret) ++ goto probe_err; ++ ++ myown_port = &fh_own_ports[dev->id]; ++ if (myown_port->fh_info.use_dma) { ++ filter_no = myown_port->uart_dma.tx_dma_channel; ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ myown_port->uart_dma.dma_tx.chan = dma_request_channel(mask, ++ fh_uart_dma_chan_filter, &filter_no); ++ if (!myown_port->uart_dma.dma_tx.chan) ++ goto probe_err; ++ filter_no = myown_port->uart_dma.rx_dma_channel; ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ myown_port->uart_dma.dma_rx.chan = dma_request_channel(mask, ++ fh_uart_dma_chan_filter, &filter_no); ++ if (!myown_port->uart_dma.dma_rx.chan) { ++ dma_release_channel(myown_port->uart_dma.dma_tx.chan); ++ myown_port->fh_info.use_dma = 0; ++ goto probe_err; ++ } ++ myown_port->uart_dma.tx_dma_add = dma_map_single( ++ myown_port->uart_dma.dma_tx.chan->dev->device.parent, ++ (void *) myown_port->uart_dma.tx_dumy_buff, ++ sizeof(myown_port->uart_dma.tx_dumy_buff), ++ DMA_TO_DEVICE); ++ myown_port->uart_dma.rx_dma_add = dma_map_single( ++ myown_port->uart_dma.dma_rx.chan->dev->device.parent, ++ (void *) myown_port->uart_dma.rx_dumy_buff, ++ sizeof(myown_port->uart_dma.rx_dumy_buff), ++ DMA_TO_DEVICE); ++ myown_port->uart_dma.HasInit = 0; ++ myown_port->uart_dma.tx_done = 1; ++ myown_port->uart_dma.tx_count = 0; ++ myown_port->uart_dma.rx_wr_ptr = 0; ++ myown_port->uart_dma.rx_rd_ptr = 0; ++ } ++ ++ ret = fh_serial_init_port(myown_port, dev); ++ if (ret < 0) ++ goto probe_err; ++ ++ ret = uart_add_one_port(&fh_uart_drv, &myown_port->port); ++ if (ret != 0) ++ printk(KERN_ERR "%s: failed to add one port.\n", __func__); ++ ++ platform_set_drvdata(dev, &myown_port->port); ++ ret = device_create_file(&dev->dev, &dev_attr_clock_source); ++ ++ if (ret < 0) ++ printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); ++ ++ ret = fh_serial_cpufreq_register(myown_port); ++ if (ret < 0) ++ dev_err(&dev->dev, "failed to add cpufreq notifier\n"); ++#ifdef CONFIG_MAGIC_SYSRQ ++ register_sysrq_key('g', &sysrq_fh_debug_mem_op); ++ register_sysrq_key('x', &sysrq_fh_dmesg_op); ++#endif ++ printk(KERN_DEBUG "fh serial probe done\n"); ++ return 0; ++ ++ probe_err: ++ printk(KERN_ERR "%s: fh serial probe error.\n", __func__); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(fh_serial_probe); ++ ++static inline void fh_serial_cpufreq_deregister(struct fh_uart_port* myown_port) ++{ ++ ++} ++ ++ ++int __devexit fh_serial_remove(struct platform_device *dev) ++{ ++ struct uart_port *port = fh_dev_to_port(&dev->dev); ++ struct fh_uart_port *myown_port = to_fh_uart_port(port); ++ struct device *dev_rx = ++ myown_port->uart_dma.dma_tx.chan->dev->device.parent; ++ struct device *dev_tx = ++ myown_port->uart_dma.dma_rx.chan->dev->device.parent; ++ ++ if (port) { ++ if (myown_port->fh_info.use_dma) { ++ dma_release_channel(myown_port->uart_dma.dma_tx.chan); ++ dma_release_channel(myown_port->uart_dma.dma_rx.chan); ++ dma_unmap_single(dev_tx, ++ (dma_addr_t)myown_port->uart_dma.tx_dumy_buff, ++ sizeof(myown_port->uart_dma.tx_dumy_buff), ++ DMA_TO_DEVICE); ++ dma_unmap_single(dev_rx, ++ (dma_addr_t)myown_port->uart_dma.rx_dumy_buff, ++ sizeof(myown_port->uart_dma.rx_dumy_buff), ++ DMA_TO_DEVICE); ++ } ++ fh_serial_cpufreq_deregister(myown_port); ++ device_remove_file(&dev->dev, &dev_attr_clock_source); ++ uart_remove_one_port(&fh_uart_drv, port); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fh_serial_remove); ++ ++int fh_serial_init(struct platform_driver *drv) ++{ ++ return platform_driver_register(drv); ++} ++EXPORT_SYMBOL_GPL(fh_serial_init); ++ ++static int __init fh_serial_modinit(void) ++{ ++ int ret; ++ ret = uart_register_driver(&fh_uart_drv); ++ if (ret < 0) { ++ printk(KERN_ERR "failed to register UART driver\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static void __exit fh_serial_modexit(void) ++{ ++ uart_unregister_driver(&fh_uart_drv); ++} ++ ++ ++static int _fh_serial_probe(struct platform_device *dev) ++{ ++ return fh_serial_probe(dev); ++} ++ ++static struct platform_driver fh_serial_driver = { ++ .probe = _fh_serial_probe, ++ .remove = __devexit_p(fh_serial_remove), ++#ifdef CONFIG_PM ++ .suspend = fh_serial_suspend, ++ .resume = fh_serial_resume, ++#endif ++ .driver = { ++ .name = FH_SERIAL_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init _fh_serial_init(void) ++{ ++ return fh_serial_init(&fh_serial_driver); ++} ++ ++static void __exit _fh_serial_exit(void) ++{ ++ platform_driver_unregister(&fh_serial_driver); ++} ++ ++module_init(_fh_serial_init); ++module_exit(_fh_serial_exit); ++ ++module_init(fh_serial_modinit); ++module_exit(fh_serial_modexit); +diff --git a/drivers/tty/serial/fh_serial.h b/drivers/tty/serial/fh_serial.h +new file mode 100644 +index 00000000..888c8000 +--- /dev/null ++++ b/drivers/tty/serial/fh_serial.h +@@ -0,0 +1,200 @@ ++/* ++ * fh_serial.h ++ * ++ * Created on: Jul 29, 2014 ++ * Author: duobao ++ */ ++#ifndef FH_SERIAL_H_ ++#define FH_SERIAL_H_ ++/**************************************************************************** ++ * #include section ++ * add #include here if any ++ ***************************************************************************/ ++#include <linux/dmaengine.h> ++#include <linux/scatterlist.h> ++#include <linux/completion.h> ++/**************************************************************************** ++ * #define section ++ * add constant #define here if any ++ ***************************************************************************/ ++ ++#define lift_shift_bit_num(bit_num) (1<<bit_num) ++#define ISR_NUMBER0 (UART0_IRQ) ++#define ISR_NUMBER1 (UART1_IRQ) ++#define ISR_NUMBER2 (UART2_IRQ) ++#define ISR_NUMBER3 (UART3_IRQ) ++#define UART0_PORT 0 ++#define UART1_PORT 1 ++#define UART2_PORT 2 ++#define UART3_PORT 3 ++#define UART_MAX_NUM 4 ++#define UART_DATA_ARRIVED 1 ++#define UART_LCR_DLAB_POS (lift_shift_bit_num(7)) ++ ++#define UART0_FIFO_SIZE 64 ++#define UART1_FIFO_SIZE 64 ++#define UART2_FIFO_SIZE 64 ++#define UART3_FIFO_SIZE 64 ++/**************************************************************************** ++* ADT section ++* add Abstract Data Type definition here ++***************************************************************************/ ++//error status ++enum { ++ UART_CONFIG_OK = 0, ++ UART_CONFIG_FIFO_OK = 0, ++ UART_CONFIG_LINE_OK = 0, ++ UART_CONFIG_DIVISOR_OK = 0, ++ UART_WRITE_DATA_OK = 0, ++ UART_READ_DATA_OK = 0, ++ UART_CLEAR_ERROR_OK = 0, ++ UART_RESET_RX_POOL_OK = 0, ++ UART_CLEAR_RX_DATA_READY_OK = 0, ++ UART_INIT_OK = 0, ++ UART_CONFIG_PARA_ERROR = lift_shift_bit_num(0), ++ UART_CONFIG_FIFO_ERROR = lift_shift_bit_num(1), ++ UART_IS_BUSY = lift_shift_bit_num(2), ++ UART_DW_FIFO_OVERFLOW = lift_shift_bit_num(3), //dw rxfifo overflow ,maybe rxisr is closed or main clock is too low ++ UART_SW_FIFO_OVERFLOW = lift_shift_bit_num(4), //soft rxfifo overflow , maybe main clk is too low ++ UART_PARITY_ERROR = lift_shift_bit_num(5), ++ UART_FRAME_ERROR = lift_shift_bit_num(6), ++ UART_BREAK_ERROR = lift_shift_bit_num(7), ++ UART_FIFO_EMPTY = lift_shift_bit_num(8), ++}; ++ ++//interrupt enable ++typedef enum enum_uart_irq { ++ UART_INT_PTIME_POS = (lift_shift_bit_num(7)), ++ UART_INT_EDSSI_POS = (lift_shift_bit_num(3)), ++ UART_INT_ELSI_POS = (lift_shift_bit_num(2)), ++ UART_INT_ETBEI_POS = (lift_shift_bit_num(1)), ++ UART_INT_ERBFI_POS = (lift_shift_bit_num(0)), ++ UART_INT_ALL = 0x0f, ++}uart_irq_e; ++ ++//interrupt id ++enum { ++ UART_INT_ID_MODEM = 0, ++ UART_INT_ID_NO_INT = 1, ++ UART_INT_ID_THR_EMPTY = 2, ++ UART_INT_ID_RECEIVE_DATA = 4, ++ UART_INT_ID_RECEIVE_LINE = 6, ++ UART_INT_ID_BUSY = 7, ++ UART_INT_ID_TIME_OUT = 12, ++ UART_FIFO_IS_ENABLE = 0xc0, ++}; ++ ++typedef enum enum_uart_line { ++ Uart_line_5n1 = 0x00, // 5 data bits, no parity, 1 stop bit ++ Uart_line_5n1_5 = 0x04, // 5 data bits, no parity, 1.5 stop bits ++ Uart_line_5e1 = 0x18, // 5 data bits, even parity, 1 stop bit ++ Uart_line_5e1_5 = 0x1c, // 5 data bits, even parity, 1.5 stop bits ++ Uart_line_5o1 = 0x08, // 5 data bits, odd parity, 1 stop bit ++ Uart_line_5o1_5 = 0x0c, // 5 data bits, odd parity, 1.5 stop bits ++ Uart_line_6n1 = 0x01, // 6 data bits, no parity, 1 stop bit ++ Uart_line_6n2 = 0x05, // 6 data bits, no parity, 2 stop bits ++ Uart_line_6e1 = 0x19, // 6 data bits, even parity, 1 stop bit ++ Uart_line_6e2 = 0x1d, // 6 data bits, even parity, 2 stop bits ++ Uart_line_6o1 = 0x09, // 6 data bits, odd parity, 1 stop bit ++ Uart_line_6o2 = 0x0d, // 6 data bits, odd parity, 2 stop bits ++ Uart_line_7n1 = 0x02, // 7 data bits, no parity, 1 stop bit ++ Uart_line_7n2 = 0x06, // 7 data bits, no parity, 2 stop bits ++ Uart_line_7e1 = 0x1a, // 7 data bits, even parity, 1 stop bit ++ Uart_line_7e2 = 0x1e, // 7 data bits, even parity, 2 stop bits ++ Uart_line_7o1 = 0x0a, // 7 data bits, odd parity, 1 stop bit ++ Uart_line_7o2 = 0x0e, // 7 data bits, odd parity, 2 stop bits ++ Uart_line_8n1 = 0x03, // 8 data bits, no parity, 1 stop bit ++ Uart_line_8n2 = 0x07, // 8 data bits, no parity, 2 stop bits ++ Uart_line_8e1 = 0x1b, // 8 data bits, even parity, 1 stop bit ++ Uart_line_8e2 = 0x1f, // 8 data bits, even parity, 2 stop bits ++ Uart_line_8o1 = 0x0b, // 8 data bits, odd parity, 1 stop bit ++ Uart_line_8o2 = 0x0f // 8 data bits, odd parity, 2 stop bits ++}uart_line_e; ++ ++//rx & tx fifo config ++typedef enum enum_uart_fifo { ++ UART_INT_RXFIFO_DEPTH_1 = 0x01, //fifo enable, rx 1 byte, set rx int ++ UART_INT_RXFIFO_DEPTH_QUARTER = 0x41, //fifo enable, rx 1/4 fifo, set rx int ++ UART_INT_RXFIFO_DEPTH_HALF =0x81, //fifo enable, rx 1/2 fifo, set rx int ++ UART_INT_RXFIFO_2LESS_THAN_FULL =0xc1, //fifo enable, rx 2 less than full, set rx int ++ UART_DMA_RXFIFO_DEPTH_HALF = 0x89, /* fifo enable, rx 1/2 fifo, set tx/rx dma */ ++}uart_fifo_e; ++ ++//line status ++enum { ++ UART_LINE_STATUS_RFE = (lift_shift_bit_num(7)), ++ UART_LINE_STATUS_TEMT = (lift_shift_bit_num(6)), ++ UART_LINE_STATUS_THRE = (lift_shift_bit_num(5)), ++ UART_LINE_STATUS_BI = (lift_shift_bit_num(4)), ++ UART_LINE_STATUS_FE = (lift_shift_bit_num(3)), ++ UART_LINE_STATUS_PE = (lift_shift_bit_num(2)), ++ UART_LINE_STATUS_OE = (lift_shift_bit_num(1)), ++ UART_LINE_STATUS_DR = (lift_shift_bit_num(0)), ++}; ++ ++//uart status ++enum { ++ UART_STATUS_RFF = (lift_shift_bit_num(4)), ++ UART_STATUS_RFNE = (lift_shift_bit_num(3)), ++ UART_STATUS_TFE = (lift_shift_bit_num(2)), ++ UART_STATUS_TFNF = (lift_shift_bit_num(1)), ++ UART_STATUS_BUSY = (lift_shift_bit_num(0)), ++ ++}; ++ ++#define UART_CLOCK_FREQ (16666667) //15MHZ ++typedef enum enum_uart_baudrate{ ++ BAUDRATE_9600 = (((UART_CLOCK_FREQ/9600)+8)/16), ++ BAUDRATE_19200 = (((UART_CLOCK_FREQ/19200)+8)/16), ++ BAUDRATE_38400 = (((UART_CLOCK_FREQ/38400)+8)/16), ++ BAUDRATE_57600 = (((UART_CLOCK_FREQ/57600)+8)/16), ++ BAUDRATE_115200 = (((UART_CLOCK_FREQ/115200)+8)/16), ++ BAUDRATE_194000 = (((UART_CLOCK_FREQ/194000)+8)/16), ++}uart_baudrate_e; ++ ++typedef struct _fh_uart_info { ++ const char * name; ++ unsigned int irq_num; ++ unsigned char __iomem *base_add; ++ uart_baudrate_e baudrate; ++ uart_line_e line_ctrl; ++ uart_fifo_e fifo_ctrl; ++ unsigned int use_dma; ++ struct platform_device *dev; ++ ++}fh_uart_info; ++ ++struct fh_uart_dma_transfer { ++ struct dma_chan *chan; ++ struct dma_slave_config cfg; ++ struct scatterlist sgl[128]; ++ unsigned int sgl_data_size[128]; ++ unsigned int actual_sgl_size; ++ struct dma_async_tx_descriptor *desc; ++}; ++struct fh_uart_dma { ++ u32 tx_dumy_buff[128]; ++ u8 rx_dumy_buff[128]; ++ u32 rx_wr_ptr; ++ u32 rx_rd_ptr; ++ u32 tx_dma_add; ++ u32 rx_dma_add; ++ u32 tx_hs_no; ++ u32 rx_hs_no; ++ u32 tx_dma_channel; ++ u32 rx_dma_channel; ++ u32 tx_count; ++ u32 tx_done; ++ u32 paddr; ++ u32 rx_xmit_len; ++ u32 HasInit; ++ struct fh_uart_dma_transfer dma_rx; ++ struct fh_uart_dma_transfer dma_tx; ++}; ++struct fh_uart_port { ++ fh_uart_info fh_info; ++ struct uart_port port; ++ struct fh_uart_dma uart_dma; ++}; ++ ++#endif /* FH_SERIAL_H_ */ +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 48f17813..f67a21c4 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -42,6 +42,7 @@ config USB_ARCH_HAS_OHCI + default y if ARCH_DAVINCI_DA8XX + default y if ARCH_CNS3XXX + default y if PLAT_SPEAR ++ default y if ARCH_FULLHAN + # PPC: + default y if STB03xxx + default y if PPC_MPC52xx +diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile +index 30ddf8dc..7e05b632 100644 +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -1,13 +1,16 @@ + # +-# Makefile for the kernel USB device drivers. ++#akefile for the kernel USB device drivers. + # + + # Object files in subdirectories + + obj-$(CONFIG_USB) += core/ + ++#obj-$(CONFIG_USB_DWC2) += dwc2/ ++ + obj-$(CONFIG_USB_MON) += mon/ + ++obj-$(CONFIG_USB_FH_OTG) += host/ + obj-$(CONFIG_PCI) += host/ + obj-$(CONFIG_USB_EHCI_HCD) += host/ + obj-$(CONFIG_USB_ISP116X_HCD) += host/ +@@ -23,7 +26,7 @@ obj-$(CONFIG_USB_HWA_HCD) += host/ + obj-$(CONFIG_USB_ISP1760_HCD) += host/ + obj-$(CONFIG_USB_IMX21_HCD) += host/ + obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ +- ++obj-$(CONFIG_USB_S3C_OTG_HOST) += host/ + obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ + + obj-$(CONFIG_USB_WUSB) += wusbcore/ +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index ace9f844..d0b57e01 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -393,7 +393,6 @@ rh_string(int id, struct usb_hcd const *hcd, u8 *data, unsigned len) + char const *s; + static char const langids[4] = {4, USB_DT_STRING, 0x09, 0x04}; + +- // language ids + switch (id) { + case 0: + /* Array of LANGID codes (0x0409 is MSFT-speak for "en-us") */ +@@ -562,7 +561,6 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) + case DeviceOutRequest | USB_REQ_SET_INTERFACE: + break; + case DeviceOutRequest | USB_REQ_SET_ADDRESS: +- // wValue == urb->dev->devaddr + dev_dbg (hcd->self.controller, "root hub device address %d\n", + wValue); + break; +@@ -572,7 +570,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) + /* ENDPOINT REQUESTS */ + + case EndpointRequest | USB_REQ_GET_STATUS: +- // ENDPOINT_HALT flag ++ + tbuf [0] = 0; + tbuf [1] = 0; + len = 2; +@@ -1582,8 +1580,10 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) + usb_unanchor_urb(urb); + + /* pass ownership to the completion handler */ ++ //printk("god...hand add is %x\n",(unsigned int)urb->complete); + urb->status = status; + urb->complete (urb); ++ + atomic_dec (&urb->use_count); + if (unlikely(atomic_read(&urb->reject))) + wake_up (&usb_kill_urb_queue); +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index a428aa08..769bc355 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2939,6 +2939,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, + /* FALL THROUGH */ + default: + if (r == 0) ++ printk("error is r = eproto\n"); + r = -EPROTO; + break; + } +diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile +index 4fe92b18..743db7f1 100644 +--- a/drivers/usb/gadget/Makefile ++++ b/drivers/usb/gadget/Makefile +@@ -3,7 +3,7 @@ + # + ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG + +-obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o ++#obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o + obj-$(CONFIG_USB_NET2280) += net2280.o + obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o + obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o +@@ -11,7 +11,6 @@ obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o + obj-$(CONFIG_USB_IMX) += imx_udc.o + obj-$(CONFIG_USB_GOKU) += goku_udc.o + obj-$(CONFIG_USB_OMAP) += omap_udc.o +-obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o + obj-$(CONFIG_USB_AT91) += at91_udc.o + obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o + obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o +@@ -21,8 +20,6 @@ obj-$(CONFIG_USB_M66592) += m66592-udc.o + obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o + obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o + obj-$(CONFIG_USB_CI13XXX_PCI) += ci13xxx_pci.o +-obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o +-obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o + obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o + obj-$(CONFIG_USB_EG20T) += pch_udc.o + obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o +diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c +index 93b999e4..6b6be1d9 100644 +--- a/drivers/usb/gadget/audio.c ++++ b/drivers/usb/gadget/audio.c +@@ -33,8 +33,9 @@ + #include "config.c" + #include "epautoconf.c" + +-#include "u_audio.c" ++/* #include "u_audio.c" */ + #include "f_audio.c" ++#include "audio_poll.c" + + /*-------------------------------------------------------------------------*/ + +diff --git a/drivers/usb/gadget/audio_poll.c b/drivers/usb/gadget/audio_poll.c +new file mode 100644 +index 00000000..c2506417 +--- /dev/null ++++ b/drivers/usb/gadget/audio_poll.c +@@ -0,0 +1,173 @@ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/fs.h> ++#include <linux/uaccess.h> ++#include <linux/wait.h> ++#include <linux/semaphore.h> ++#include <linux/device.h> ++#include <linux/cdev.h> ++#include <linux/sched.h> ++#include <linux/poll.h> ++ ++#include "f_uac.h" ++ ++ ++#define init_MUTEX(LOCKNAME) sema_init(LOCKNAME, 1) ++#define DEVICE_NAME "uac_audio" ++#define UAC_STREAM_OFF 0 ++#define UAC_STREAM_ON 1 ++#define UAC_IOC_SEND_AUDIO 0x499 ++#define UAC_IOC_GET_STREAM_STATUS 0x599 ++ ++ ++ ++static struct class *cdev_class; ++static struct cdev dev_c; ++static dev_t dev; ++ ++ ++static struct semaphore sem; ++static wait_queue_head_t outq; ++ ++static int gStreamFlag; ++static int gStreamStatus = UAC_STREAM_OFF; ++static int gStaFlag; ++ ++ ++/*#define UAC_DEV_USE_LOCK*/ ++static int lock(void) ++{ ++#ifdef UAC_DEV_USE_LOCK ++ return down_interruptible(&sem); ++#else ++ return 0; ++#endif ++} ++ ++static void unlock(void) ++{ ++#ifdef UAC_DEV_USE_LOCK ++ up(&sem); ++#endif ++} ++ ++ ++void wake_up_app(void) ++{ ++ if (gStreamStatus == UAC_STREAM_ON) { ++ lock(); ++ gStreamFlag = 1; ++ unlock(); ++ wake_up_interruptible(&outq); ++ } ++} ++ ++ ++void uac_stream(int on) ++{ ++ lock(); ++ gStreamStatus = on; ++ gStaFlag = 1; ++ unlock(); ++ wake_up_interruptible(&outq); ++} ++ ++ ++static int audio_ops_open(struct inode *node, struct file *filp) ++{ ++ audio_dev_open(); ++ return 0; ++} ++ ++ ++ ++static long audio_ops_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ switch (cmd) { ++ case UAC_IOC_SEND_AUDIO: ++ return audio_send_data((void *)arg); ++ break; ++ ++ case UAC_IOC_GET_STREAM_STATUS: ++ return gStreamStatus; ++ break; ++ } ++ return 0; ++} ++ ++ ++static unsigned int audio_ops_poll(struct file *filp, poll_table *wait) ++{ ++ unsigned int mask = 0; ++ poll_wait(filp, &outq, wait); ++ lock(); ++ if (gStreamFlag) { ++ if (gStreamStatus == UAC_STREAM_ON) { ++ /*Write Stream*/ ++ mask |= POLLOUT | POLLWRNORM; ++ } ++ gStreamFlag = 0; ++ } ++ ++ if (gStaFlag) { ++ /*Read Status*/ ++ mask |= POLLIN | POLLRDNORM; ++ gStaFlag = 0; ++ } ++ unlock(); ++ return mask; ++} ++ ++ ++ ++struct file_operations audio_device_fops = { ++poll: ++ audio_ops_poll, ++open : ++ audio_ops_open, ++unlocked_ioctl : ++ audio_ops_ioctl, ++}; ++ ++ ++ ++int __init audio_device_init(void) ++{ ++ int ret, err; ++ ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); ++ if (ret) ++ printk("audio device register failure"); ++ else { ++ cdev_init(&dev_c, &audio_device_fops); ++ err = cdev_add(&dev_c, dev, 1); ++ if (err) { ++ printk(KERN_NOTICE "error %d adding FC_dev\n", err); ++ unregister_chrdev_region(dev, 1); ++ return err; ++ } else ++ printk("device register success!\n"); ++ ++ cdev_class = class_create(THIS_MODULE, DEVICE_NAME); ++ if (IS_ERR(cdev_class)) { ++ printk("ERR:cannot create a cdev_class\n"); ++ unregister_chrdev_region(dev, 1); ++ return -1; ++ } ++ device_create(cdev_class, NULL, dev, 0, DEVICE_NAME); ++ ++ init_MUTEX(&sem); ++ init_waitqueue_head(&outq); ++ } ++ return ret; ++} ++ ++ ++void __exit audio_device_exit(void) ++{ ++ device_destroy(cdev_class, dev); ++ class_destroy(cdev_class); ++ unregister_chrdev_region(dev, 1); ++ /*printk("device");*/ ++} ++ ++ +diff --git a/drivers/usb/gadget/f_uac.c b/drivers/usb/gadget/f_uac.c +new file mode 100644 +index 00000000..3145bff8 +--- /dev/null ++++ b/drivers/usb/gadget/f_uac.c +@@ -0,0 +1,915 @@ ++#include <linux/kernel.h> ++#include <linux/device.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/list.h> ++#include <linux/mutex.h> ++#include <linux/usb/ch9.h> ++#include <linux/usb/gadget.h> ++#include <linux/usb/video.h> ++#include <linux/vmalloc.h> ++#include <linux/wait.h> ++ ++#include <linux/usb/audio.h> ++#include "f_uac.h" ++ ++/*#define UAC_BIND_DEACTIVATE*/ ++static void f_audio_complete(struct usb_ep *ep, struct usb_request *req); ++ ++#define UAC_ERR(msg...) printk(KERN_EMERG "UAC, " msg) ++#define UAC_DBG(msg...) printk(KERN_INFO "UAC, " msg) ++#define UAC_INFO(msg...) printk(KERN_INFO "UAC, " msg) ++ ++ ++ ++#define UAC_STR_ASSOCIATION_IDX 0 ++#define UAC_STR_CONTROL_IDX 1 ++#define UAC_STR_STREAMING_IDX 2 ++ ++ ++static struct usb_string uac_en_us_strings[] = { ++ [UAC_STR_ASSOCIATION_IDX].s = "Fullhan Audio", ++ [UAC_STR_CONTROL_IDX].s = "Audio Control", ++ [UAC_STR_STREAMING_IDX].s = "Audio Streaming", ++ { } ++}; ++ ++static struct usb_gadget_strings uac_stringtab = { ++ .language = 0x0409, /* en-us */ ++ .strings = uac_en_us_strings, ++}; ++ ++static struct usb_gadget_strings *uac_function_strings[] = { ++ &uac_stringtab, ++ NULL, ++}; ++ ++ ++ ++ ++#ifdef ENABLE_SPEAKER_DESC ++ ++#define UAC_IF_COUNT 3 ++#define UAC_COLLECTION_NUM 2 ++#define AC_HEADER_TOTAL_LENGTH 0x44 ++ ++#else ++ ++#define UAC_IF_COUNT 2 ++#define UAC_COLLECTION_NUM 1 ++#define AC_HEADER_TOTAL_LENGTH 0x26 ++ ++ ++#endif ++ ++/* ++* ++*/ ++static struct usb_interface_assoc_descriptor audio_iad_desc = { ++ .bLength = 0x08, ++ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, ++ .bFirstInterface = 2, ++ .bInterfaceCount = UAC_IF_COUNT, ++ .bFunctionClass = USB_CLASS_AUDIO, ++ .bFunctionSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++ .bFunctionProtocol = 0x00, ++ .iFunction = 0, ++}; ++ ++ ++static struct usb_interface_descriptor ac_intf_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 2, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++ ++#define AC_SIZE_NUM 2 ++ ++DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); ++ ++/* B.3.2 Class-Specific AC Interface Descriptor */ ++static struct uac1_ac_header_descriptor_2 ac_header_desc = { ++ .bLength = UAC_DT_AC_HEADER_SIZE(UAC_COLLECTION_NUM), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_HEADER, ++ .bcdADC = __constant_cpu_to_le16(0x0100), ++ .wTotalLength = __constant_cpu_to_le16(AC_HEADER_TOTAL_LENGTH), ++ .bInCollection = UAC_COLLECTION_NUM, ++ .baInterfaceNr[0] = 3, ++ .baInterfaceNr[1] = 4, ++}; ++ ++ ++ ++#define INPUT_TERMINAL_ID 1 ++#define AUDIO_CHN_NUM 1 ++static struct uac_input_terminal_descriptor audio_mic_it_desc = { ++ .bLength = UAC_DT_INPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_INPUT_TERMINAL, ++ .bTerminalID = INPUT_TERMINAL_ID, ++ .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE, ++ .bAssocTerminal = 0, ++ .bNrChannels = 1, ++ .wChannelConfig = 0x0, ++}; ++ ++ ++#define OUTPUT_TERMINAL_ID 3 ++#define FEATURE_UNIT_ID 5 ++ ++static struct uac1_output_terminal_descriptor audio_mic_ot_desc = { ++ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, ++ .bTerminalID = OUTPUT_TERMINAL_ID, ++ .wTerminalType = UAC_TERMINAL_STREAMING, ++ .bAssocTerminal = 0, ++ .bSourceID = FEATURE_UNIT_ID, ++ .iTerminal = 0, ++}; ++ ++ ++DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); ++ ++ ++static struct uac_feature_unit_descriptor_0 audio_mic_fu_desc = { ++ .bLength = 0x08, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FEATURE_UNIT, ++ .bUnitID = FEATURE_UNIT_ID, ++ .bSourceID = INPUT_TERMINAL_ID, ++ .bControlSize = 1, ++ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME), ++}; ++ ++ ++#define SPEAKER_IT_ID 4 ++#define SPEAKER_FU_ID 6 ++#define SPEAKER_OT_ID 8 ++ ++#ifdef ENABLE_SPEAKER_DESC ++static struct uac_input_terminal_descriptor audio_spk_it_desc = { ++ .bLength = UAC_DT_INPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_INPUT_TERMINAL, ++ .bTerminalID = SPEAKER_IT_ID, ++ .wTerminalType = UAC_TERMINAL_STREAMING, ++ .bAssocTerminal = 0, ++ .bNrChannels = 1, ++ .wChannelConfig = 0x0, ++}; ++ ++ ++ ++static struct uac_feature_unit_descriptor_0 audio_spk_fu_desc = { ++ .bLength = 0x08, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FEATURE_UNIT, ++ .bUnitID = SPEAKER_FU_ID, ++ .bSourceID = SPEAKER_IT_ID, ++ .bControlSize = 1, ++ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME), ++}; ++ ++static struct uac1_output_terminal_descriptor audio_spk_ot_desc = { ++ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, ++ .bTerminalID = SPEAKER_OT_ID, ++ .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER, ++ .bAssocTerminal = 0, ++ .bSourceID = SPEAKER_FU_ID, ++ .iTerminal = 0, ++}; ++ ++#endif ++ ++ ++/* Standard AS Interface Descriptor */ ++static struct usb_interface_descriptor as_mic_if_alt_0_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 3, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++}; ++ ++static struct usb_interface_descriptor as_mic_if_alt_1_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 3, ++ .bAlternateSetting = 1, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++}; ++ ++ ++/* B.4.2 Class-Specific AS Interface Descriptor */ ++static struct uac1_as_header_descriptor as_mic_header_desc = { ++ .bLength = UAC_DT_AS_HEADER_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_AS_GENERAL, ++ .bTerminalLink = OUTPUT_TERMINAL_ID, ++ .bDelay = 0xff, ++ .wFormatTag = UAC_FORMAT_TYPE_I_PCM, ++}; ++ ++ ++#define SAMPLE_FREQ (8000) ++DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); ++ ++static struct uac_format_type_i_discrete_descriptor_1 as_mic_type_i_desc = { ++ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_TYPE, ++ .bFormatType = UAC_FORMAT_TYPE_I, ++ .bNrChannels = AUDIO_CHN_NUM, ++ .bSubframeSize = 2, ++ .bBitResolution = 16, ++ .bSamFreqType = 1, ++ .tSamFreq[0][0] = (SAMPLE_FREQ & 0xff), ++ .tSamFreq[0][1] = (SAMPLE_FREQ >> 8) & 0xff, ++ .tSamFreq[0][2] = 0, ++}; ++ ++ ++static struct usb_endpoint_descriptor audio_mic_streaming_ep = { ++ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN|5, ++ .bmAttributes = 0x05,/*USB_ENDPOINT_XFER_ISOC,*/ ++ .wMaxPacketSize = cpu_to_le16(68), ++ .bInterval = 4, ++}; ++ ++ ++/* Class-specific AS ISO OUT Endpoint Descriptor */ ++static struct uac_iso_endpoint_descriptor as_mic_iso_out_desc = { ++ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, ++ .bDescriptorType = USB_DT_CS_ENDPOINT, ++ .bDescriptorSubtype = UAC_EP_GENERAL, ++ .bmAttributes = 1, ++ .bLockDelayUnits = 0, ++ .wLockDelay = 0, ++}; ++ ++ ++#ifdef ENABLE_SPEAKER_DESC ++/*speaker*/ ++/* Standard AS Interface Descriptor */ ++static struct usb_interface_descriptor as_spk_if_alt_0_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 4, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++}; ++ ++static struct usb_interface_descriptor as_spk_if_alt_1_desc = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 4, ++ .bAlternateSetting = 1, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING, ++}; ++ ++ ++/* B.4.2 Class-Specific AS Interface Descriptor */ ++static struct uac1_as_header_descriptor as_spk_header_desc = { ++ .bLength = UAC_DT_AS_HEADER_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_AS_GENERAL, ++ .bTerminalLink = SPEAKER_IT_ID, ++ .bDelay = 0xff, ++ .wFormatTag = UAC_FORMAT_TYPE_I_PCM, ++}; ++ ++ ++static struct uac_format_type_i_discrete_descriptor_1 as_spk_type_i_desc = { ++ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubtype = UAC_FORMAT_TYPE, ++ .bFormatType = UAC_FORMAT_TYPE_I, ++ .bNrChannels = AUDIO_CHN_NUM, ++ .bSubframeSize = 2, ++ .bBitResolution = 16, ++ .bSamFreqType = 1, ++ .tSamFreq[0][0] = (SAMPLE_FREQ & 0xff), ++ .tSamFreq[0][1] = (SAMPLE_FREQ >> 8) & 0xff, ++ .tSamFreq[0][2] = 0, ++ ++}; ++ ++ ++static struct usb_endpoint_descriptor audio_spk_streaming_ep = { ++ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_OUT|6, ++ .bmAttributes = 0x05,/*USB_ENDPOINT_XFER_ISOC,*/ ++ .wMaxPacketSize = cpu_to_le16(68), ++ .bInterval = 4, ++}; ++ ++ ++/* Class-specific AS ISO OUT Endpoint Descriptor */ ++static struct uac_iso_endpoint_descriptor as_spk_iso_out_desc = { ++ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, ++ .bDescriptorType = USB_DT_CS_ENDPOINT, ++ .bDescriptorSubtype = UAC_EP_GENERAL, ++ .bmAttributes = 0, ++ .bLockDelayUnits = 0, ++ .wLockDelay = 0, ++}; ++ ++#endif ++ ++ ++ ++static struct usb_descriptor_header *f_audio_descs[] __initdata = { ++ (struct usb_descriptor_header *)&audio_iad_desc, ++ (struct usb_descriptor_header *)&ac_intf_desc, ++ (struct usb_descriptor_header *)&ac_header_desc, ++ ++ (struct usb_descriptor_header *)&audio_mic_it_desc, ++ (struct usb_descriptor_header *)&audio_mic_ot_desc, ++ (struct usb_descriptor_header *)&audio_mic_fu_desc, ++ ++#ifdef ENABLE_SPEAKER_DESC ++ (struct usb_descriptor_header *)&audio_spk_it_desc, ++ (struct usb_descriptor_header *)&audio_spk_ot_desc, ++ (struct usb_descriptor_header *)&audio_spk_fu_desc, ++#endif ++ ++ ++ (struct usb_descriptor_header *)&as_mic_if_alt_0_desc, ++ (struct usb_descriptor_header *)&as_mic_if_alt_1_desc, ++ (struct usb_descriptor_header *)&as_mic_header_desc, ++ (struct usb_descriptor_header *)&as_mic_type_i_desc, ++ (struct usb_descriptor_header *)&audio_mic_streaming_ep, ++ (struct usb_descriptor_header *)&as_mic_iso_out_desc, ++ ++#ifdef ENABLE_SPEAKER_DESC ++ (struct usb_descriptor_header *)&as_spk_if_alt_0_desc, ++ (struct usb_descriptor_header *)&as_spk_if_alt_1_desc, ++ (struct usb_descriptor_header *)&as_spk_header_desc, ++ (struct usb_descriptor_header *)&as_spk_type_i_desc, ++ (struct usb_descriptor_header *)&audio_spk_streaming_ep, ++ (struct usb_descriptor_header *)&as_spk_iso_out_desc, ++#endif ++ NULL, ++}; ++ ++ ++ ++ ++#define UAC_STREAM_OFF 0 ++#define UAC_STREAM_ON 1 ++#define AUDIO_REQ_NUM 32 ++ ++struct uac_audio { ++ struct usb_function *func; ++ struct usb_ep *ep; ++ struct usb_request *req[AUDIO_REQ_NUM]; ++ void *req_buf[AUDIO_REQ_NUM]; ++ int req_valid[AUDIO_REQ_NUM]; ++ int req_buf_size; ++ ++ int ac_connected; ++ int stream_sta; ++ int ac_intf; ++ int as_mic_intf; ++ int as_spk_intf; ++ ++ int mute_set; ++ int vol_set; ++ int set_cmd; ++ ++}; ++ ++ ++static struct uac_audio *g_audio; ++ ++ ++static int uac_is_stream_on(void) ++{ ++ return (g_audio->stream_sta == UAC_STREAM_ON); ++} ++ ++static int uac_audio_enable(int enable) ++{ ++ unsigned int i; ++ ++ uac_stream(enable); ++ if (!enable) { ++ if (uac_is_stream_on()) { ++ for (i = 0; i < AUDIO_REQ_NUM; ++i) ++ usb_ep_dequeue(g_audio->ep, g_audio->req[i]); ++ ++ usb_ep_disable(g_audio->ep); ++ g_audio->stream_sta = UAC_STREAM_OFF; ++ UAC_INFO("STREAM OFF\n"); ++ } ++ return 0; ++ } ++ ++ ++ usb_ep_enable(g_audio->ep, &audio_mic_streaming_ep); ++ g_audio->stream_sta = UAC_STREAM_ON; ++ UAC_INFO("STREAM ON\n"); ++ return 0; ++} ++ ++ ++ ++ ++ ++void uac_begin_transfer_data(void) ++{ ++ int i, err; ++ struct usb_request *req; ++ for (i = 0; i < AUDIO_REQ_NUM; i++) { ++ req = g_audio->req[i]; ++ req->buf = g_audio->req_buf[i]; ++ req->dma = (~(dma_addr_t)0); ++ ++ g_audio->req_valid[i] = 0; ++ memset(req->buf, 0, g_audio->req_buf_size); ++ req->length = 0; ++ req->context = (void *)i; ++ req->dma = DMA_ADDR_INVALID; ++ req->complete = f_audio_complete; ++#if 1 ++ err = usb_ep_queue(g_audio->ep, req, GFP_ATOMIC); ++ if (err) ++ UAC_ERR("transfer_data usb_ep_queue error, %s req: %d\n", g_audio->ep->name, err); ++#endif ++ } ++ ++ ++ wake_up_app(); ++ err = 0; ++ UAC_INFO("sendMsg audio!\n"); ++} ++ ++ ++static void f_audio_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ ++ int a; ++ ++ int i, avlidCount = 0; ++ unsigned char *pData = NULL; ++ switch (req->status) { ++ case 0: ++ UAC_INFO("f_audio_complete.\n"); ++ if (ep != g_audio->ep) { ++ if (g_audio->set_cmd) { ++ pData = req->buf; ++ if (UAC_FU_MUTE == g_audio->set_cmd) { ++ if (1 == req->actual) { ++ g_audio->mute_set = pData[0]; ++ UAC_INFO("mute set data = %02x\n", pData[0]); ++ } ++ } else if (UAC_FU_VOLUME == g_audio->set_cmd) { ++ if (2 == req->actual) { ++ g_audio->vol_set = pData[0] + pData[1]*256; ++ UAC_INFO("vol set data = %02x, %02x\n", pData[0], pData[1]); ++ } ++ } ++ } ++ g_audio->set_cmd = 0; ++ return; ++ } ++ a = (int)req->context; ++ g_audio->req_valid[a] = 1; ++ for (i = 0; i < AUDIO_REQ_NUM; i++) { ++ if (g_audio->req_valid[a]) ++ avlidCount++; ++ if (avlidCount > 3) { ++ UAC_INFO("f_audio_complete wake_up_app.\n"); ++ wake_up_app(); ++ break; ++ } ++ } ++ break; ++ ++ case -ESHUTDOWN: ++ UAC_INFO("f_audio_complete ESHUTDOWN.\n"); ++ goto requeue; ++ ++ default: ++ UAC_INFO("request completed with status %d.\n", req->status); ++ goto requeue; ++ } ++ ++ ++ return; ++ ++requeue: ++ a = 5; ++ ++} ++ ++ ++struct audio_data { ++ unsigned char *pData; ++ unsigned char *pPos; ++ unsigned char *pEnd; ++}; ++ ++int audio_send_data(void *args) ++{ ++ struct audio_data *pAudio = args; ++ int i; ++ struct usb_request *req = NULL; ++ ++ int len = g_audio->req_buf_size; ++ int send_len = 0; ++ int ret = 0; ++ int err = 0; ++ if (!uac_is_stream_on()) ++ return 0; ++ ++ for (i = 0; i < AUDIO_REQ_NUM; i++) { ++ if (g_audio->req_valid[i]) { ++ g_audio->req_valid[i] = 0; ++ req = g_audio->req[i]; ++ req->buf = g_audio->req_buf[i]; ++ req->dma = DMA_ADDR_INVALID; ++ req->context = (void *)i; ++ req->complete = f_audio_complete; ++ ++ if (pAudio->pPos >= pAudio->pEnd) { ++ pAudio->pPos = pAudio->pData; ++ ret = 1; ++ break; ++ } else if (pAudio->pPos < pAudio->pData) ++ pAudio->pPos = pAudio->pData; ++ ++ if (pAudio->pPos + g_audio->req_buf_size >= pAudio->pEnd) { ++ len = pAudio->pEnd-pAudio->pPos; ++ memcpy(req->buf, pAudio->pPos, len); ++ send_len += len; ++ ++ pAudio->pPos = pAudio->pData; ++ ret = 1; ++ } else { ++ len = g_audio->req_buf_size; ++ memcpy(req->buf, pAudio->pPos, g_audio->req_buf_size); ++ pAudio->pPos += g_audio->req_buf_size; ++ send_len += g_audio->req_buf_size; ++ } ++ req->length = len; ++ ++ /*if (g_audio->mute_set) ++ memset(req->buf, 0, len); ++ */ ++ err = usb_ep_queue(g_audio->ep, req, GFP_ATOMIC); ++ if (err) ++ UAC_ERR("audio usb_ep_queue error, %s req: %d\n", g_audio->ep->name, err); ++ ++ if (ret) ++ break; ++ } ++ } ++ ++ if (send_len > 0) ++ UAC_INFO("audio send = %d\n", send_len); ++ return send_len; ++ ++} ++ ++ ++ ++static int ++uac_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) ++{ ++ struct usb_composite_dev *cdev = f->config->cdev; ++ struct usb_request *req = cdev->req; ++ int value = -EOPNOTSUPP; ++ u16 w_index = le16_to_cpu(ctrl->wIndex); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ u16 w_length = le16_to_cpu(ctrl->wLength); ++ int cs, id; ++ int sendAudioReq = 0; ++ u8 *pData; ++ u8 is_cmd = 1; ++ ++ UAC_INFO("setup, req: %02x.%02x value: %04x index: %04x length: %d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ ++ g_audio->set_cmd = 0; ++ ++ if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE) { ++ value = 3; ++ sendAudioReq = 1; ++ } else { ++ cs = ctrl->wValue >> 8; ++ id = ctrl->wIndex >> 8; ++ UAC_INFO("id = %d, cs = %d\n", id, cs); ++ pData = req->buf; ++ if (FEATURE_UNIT_ID == id || SPEAKER_FU_ID == id) { ++ switch (cs) { ++ case UAC_FU_MUTE: ++ value = 1; ++ pData[0] = 0; ++ break; ++ ++ case UAC_FU_VOLUME: ++ value = 2; ++ pData[0] = 0; ++ pData[1] = 1; ++ break; ++ ++ default: ++ is_cmd = 0; ++ break; ++ } ++ } ++ ++ if (!(ctrl->bRequestType & USB_DIR_IN)) { ++ if (is_cmd) ++ g_audio->set_cmd = cs; ++ } ++ } ++ if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { ++ req->length = value; ++ req->zero = value < w_length; ++ req->complete = f_audio_complete; ++ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) { ++ DBG(cdev, "ep_queue --> %d\n", value); ++ req->status = 0; ++ composite_setup_complete(cdev->gadget->ep0, req); ++ } ++ } ++ if (sendAudioReq) ++ uac_begin_transfer_data(); ++ return 0; ++} ++ ++ ++static int ++uac_function_get_alt(struct usb_function *f, unsigned interface) ++{ ++ UAC_INFO("get_alt\n"); ++ return 0; ++} ++ ++ ++ ++ ++static int ++uac_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) ++{ ++ UAC_INFO("set_alt, intf = %d, alt = %d\n", interface, alt); ++ if (g_audio->as_mic_intf == interface) ++ uac_audio_enable(0 != alt); ++ else if (g_audio->ac_intf == interface) ++ g_audio->ac_connected = 1; ++ return 0; ++} ++ ++ ++void audio_dev_open(void) ++{ ++ UAC_DBG("audio_dev_open!\n"); ++ if (!g_audio->ac_connected) { ++ #ifdef UAC_BIND_DEACTIVATE ++ int ret; ++ ret = usb_function_activate(g_audio->func); ++ if (ret < 0) ++ UAC_DBG("audio_dev_open conn error!\n"); ++ else ++ UAC_DBG("audio_dev_open conn ok!\n"); ++ #endif ++ } ++} ++ ++static void ++uac_function_disable(struct usb_function *f) ++{ ++ ++ INFO(f->config->cdev, "uac_function_disable\n"); ++} ++ ++#define UVC_COPY_DESCRIPTOR(mem, dst, desc) \ ++ do { \ ++ memcpy(mem, desc, (desc)->bLength); \ ++ *(dst)++ = mem; \ ++ mem += (desc)->bLength; \ ++ } while (0); ++ ++#define UVC_COPY_DESCRIPTORS(mem, dst, src) \ ++ do { \ ++ const struct usb_descriptor_header * const *__src; \ ++ for (__src = src; *__src; ++__src) { \ ++ memcpy(mem, *__src, (*__src)->bLength); \ ++ *dst++ = mem; \ ++ mem += (*__src)->bLength; \ ++ } \ ++ } while (0) ++ ++ ++ ++static struct usb_descriptor_header ** __init ++uac_copy_descriptors(enum usb_device_speed speed) ++{ ++ const struct usb_descriptor_header * const *src; ++ struct usb_descriptor_header **dst; ++ struct usb_descriptor_header **hdr; ++ unsigned int n_desc = 0; ++ unsigned int bytes = 0; ++ void *mem; ++ ++ int audio_desc_num = 0; ++ for (src = (const struct usb_descriptor_header **)f_audio_descs; *src; ++src) { ++ bytes += (*src)->bLength; ++ n_desc++; ++ } ++ ++ audio_desc_num = (n_desc + 1) * sizeof(*src) + bytes; ++ UAC_INFO("copy_descriptors bytes = %d, ndesc = %d\n", bytes, n_desc); ++ mem = kmalloc(audio_desc_num+20, GFP_KERNEL); ++ hdr = mem; ++ dst = mem; ++ mem += (n_desc + 1) * sizeof(*src); ++ ++ UVC_COPY_DESCRIPTORS(mem, dst, (const struct usb_descriptor_header * const *)f_audio_descs); ++ *dst = (struct usb_descriptor_header *)NULL; ++ return hdr; ++ ++} ++ ++static void ++uac_function_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ audio_device_exit(); ++} ++ ++static int __init ++uac_function_bind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct usb_composite_dev *cdev = c->cdev; ++ struct usb_ep *ep; ++ int ret = -EINVAL; ++ int i; ++ ++ UAC_DBG("bind~\n"); ++ ++ ep = usb_ep_autoconfig(cdev->gadget, &audio_mic_streaming_ep); ++ if (!ep) { ++ UAC_ERR("Unable to allocate audio EP\n"); ++ goto error; ++ } ++ ++ g_audio->ep = ep; ++ ++ ++ /* Allocate interface IDs. */ ++ ret = usb_interface_id(c, f); ++ if (ret < 0) ++ goto error; ++ ++ UAC_INFO("control_intf = %d\n", ret); ++ audio_iad_desc.bFirstInterface = ret; ++ ac_intf_desc.bInterfaceNumber = ret; ++ g_audio->ac_intf = ret; ++ ++ ret = usb_interface_id(c, f); ++ if (ret < 0) ++ goto error; ++ ++ UAC_INFO("streaming_intf = %d\n", ret); ++ as_mic_if_alt_0_desc.bInterfaceNumber = ret; ++ as_mic_if_alt_1_desc.bInterfaceNumber = ret; ++ g_audio->as_mic_intf = ret; ++ ac_header_desc.baInterfaceNr[0] = ret; ++ ++ ++#ifdef ENABLE_SPEAKER_DESC ++ ++ ep = usb_ep_autoconfig(cdev->gadget, &audio_spk_streaming_ep); ++ UAC_DBG("audio_in_ep_id = %s\n", ep->name); ++ if (!ep) { ++ UAC_ERR("Unable to allocate audio EP\n"); ++ goto error; ++ } ++ ++ ret = usb_interface_id(c, f); ++ if (ret < 0) ++ goto error; ++ ++ UAC_INFO("streaming_intf2 = %d\n", ret); ++ as_spk_if_alt_0_desc.bInterfaceNumber = ret; ++ as_spk_if_alt_1_desc.bInterfaceNumber = ret; ++ g_audio->as_spk_intf = ret; ++ ac_header_desc.baInterfaceNr[1] = ret; ++ #endif ++ ++ /* Copy descriptors. */ ++ f->descriptors = uac_copy_descriptors(USB_SPEED_FULL); ++ f->hs_descriptors = uac_copy_descriptors(USB_SPEED_FULL); ++ ++ ++ g_audio->req_buf_size = 16; ++ for (i = 0; i < AUDIO_REQ_NUM; i++) { ++ g_audio->req[i] = usb_ep_alloc_request(g_audio->ep, GFP_ATOMIC); ++ if (g_audio->req[i]) { ++ g_audio->req_buf[i] = kzalloc(g_audio->req_buf_size, GFP_ATOMIC); ++ g_audio->req[i]->buf = g_audio->req_buf[i]; ++ } ++ } ++ ++ ++#ifdef UAC_BIND_DEACTIVATE ++ ret = usb_function_deactivate(f); ++ if (ret < 0) ++ goto error; ++#endif ++ ++ return 0; ++ ++error: ++ uac_function_unbind(c, f); ++ return ret; ++} ++ ++ ++ ++ ++ ++ ++int __init ++uac_bind_config(struct usb_configuration *c) ++{ ++ ++ int ret = 0; ++ struct usb_function *func; ++ ++ /* Allocate string descriptor numbers. */ ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ goto error; ++ uac_en_us_strings[UAC_STR_ASSOCIATION_IDX].id = ret; ++ audio_iad_desc.iFunction = ret; ++ ++#if 0 ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) ++ goto error; ++ uac_en_us_strings[UAC_STR_CONTROL_IDX].id = ret; ++ ac_intf_desc.iInterface = ret; ++ ++ ret = usb_string_id(c->cdev)); ++ if (ret < 0) ++ goto error; ++ uac_en_us_strings[UAC_STR_STREAMING_IDX].id = ret; ++ as_interface_alt_0_desc.iInterface = ret; ++ as_interface_alt_1_desc.iInterface = ret; ++#endif ++ ++ g_audio = kzalloc(sizeof(*g_audio), GFP_KERNEL); ++ ++ ++ func = kzalloc(sizeof(*func), GFP_KERNEL); ++ ++ /* Register the function. */ ++ func->name = "uac"; ++ func->strings = uac_function_strings; ++ func->bind = uac_function_bind; ++ func->unbind = uac_function_unbind; ++ func->get_alt = uac_function_get_alt; ++ func->set_alt = uac_function_set_alt; ++ func->disable = uac_function_disable; ++ func->setup = uac_function_setup; ++ ++ g_audio->func = func; ++ ret = usb_add_function(c, func); ++ ++ ++ audio_device_init(); ++ ++ return 0; ++ ++error: ++ return ret; ++} ++ ++ +diff --git a/drivers/usb/gadget/f_uac.h b/drivers/usb/gadget/f_uac.h +new file mode 100644 +index 00000000..100a9c80 +--- /dev/null ++++ b/drivers/usb/gadget/f_uac.h +@@ -0,0 +1,17 @@ ++#ifndef _F_UAC_H_ ++#define _F_UAC_H_ ++ ++#include <linux/usb/composite.h> ++#include <linux/poll.h> ++#include <linux/usb/audio.h> ++ ++ ++extern void wake_up_app(void); ++extern int __init audio_device_init(void); ++extern void __exit audio_device_exit(void); ++extern void uac_stream(int on); ++extern void audio_dev_open(void); ++extern int audio_send_data(void *args); ++ ++ ++#endif +\ No newline at end of file +diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c +index be446b7e..974097c4 100644 +--- a/drivers/usb/gadget/f_uvc.c ++++ b/drivers/usb/gadget/f_uvc.c +@@ -29,6 +29,14 @@ + #include "uvc.h" + + unsigned int uvc_gadget_trace_param; ++struct usb_ep *video_stream1_ep1; ++struct usb_ep *video_stream1_ep2; ++struct usb_ep *video_stream2_ep1; ++struct usb_ep *video_stream2_ep2; ++ ++static unsigned int gLastIntf; ++static unsigned int gLastDirOut; ++ + + /* -------------------------------------------------------------------------- + * Function descriptors +@@ -41,7 +49,7 @@ unsigned int uvc_gadget_trace_param; + #define UVC_STRING_STREAMING_IDX 2 + + static struct usb_string uvc_en_us_strings[] = { +- [UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera", ++ [UVC_STRING_ASSOCIATION_IDX].s = "Fullhan Webcam", + [UVC_STRING_CONTROL_IDX].s = "Video Control", + [UVC_STRING_STREAMING_IDX].s = "Video Streaming", + { } +@@ -60,7 +68,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = { + #define UVC_INTF_VIDEO_CONTROL 0 + #define UVC_INTF_VIDEO_STREAMING 1 + +-static struct usb_interface_assoc_descriptor uvc_iad __initdata = { ++static struct usb_interface_assoc_descriptor uvc_iad = { + .bLength = sizeof(uvc_iad), + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, +@@ -71,7 +79,7 @@ static struct usb_interface_assoc_descriptor uvc_iad __initdata = { + .iFunction = 0, + }; + +-static struct usb_interface_descriptor uvc_control_intf __initdata = { ++static struct usb_interface_descriptor uvc_control_intf = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL, +@@ -83,7 +91,7 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { + .iInterface = 0, + }; + +-static struct usb_endpoint_descriptor uvc_control_ep __initdata = { ++static struct usb_endpoint_descriptor uvc_control_ep = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, +@@ -92,14 +100,14 @@ static struct usb_endpoint_descriptor uvc_control_ep __initdata = { + .bInterval = 8, + }; + +-static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { ++static struct uvc_control_endpoint_descriptor uvc_control_cs_ep = { + .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_CS_ENDPOINT, + .bDescriptorSubType = UVC_EP_INTERRUPT, + .wMaxTransferSize = cpu_to_le16(16), + }; + +-static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { ++static struct usb_interface_descriptor uvc_streaming1_intf_alt0 = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, +@@ -111,7 +119,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { + .iInterface = 0, + }; + +-static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { ++static struct usb_interface_descriptor uvc_streaming1_intf_alt1 = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, +@@ -123,7 +131,28 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { + .iInterface = 0, + }; + +-static struct usb_endpoint_descriptor uvc_streaming_ep = { ++static struct usb_endpoint_descriptor uvc_streaming1_ep = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = cpu_to_le16(1020),/*1020*/ ++ .bInterval = 1, ++}; ++ ++static struct usb_interface_descriptor uvc_streaming1_intf_alt2 = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, ++ .bAlternateSetting = 2, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++static struct usb_endpoint_descriptor uvc_streaming1_ep2 = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, +@@ -132,18 +161,96 @@ static struct usb_endpoint_descriptor uvc_streaming_ep = { + .bInterval = 1, + }; + +-static const struct usb_descriptor_header * const uvc_fs_streaming[] = { +- (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, +- (struct usb_descriptor_header *) &uvc_streaming_ep, ++static const struct usb_descriptor_header * const uvc_fs_streaming1[] = { ++ (struct usb_descriptor_header *) &uvc_streaming1_intf_alt1, ++ (struct usb_descriptor_header *) &uvc_streaming1_ep, ++ (struct usb_descriptor_header *) &uvc_streaming1_intf_alt2, ++ (struct usb_descriptor_header *) &uvc_streaming1_ep2, + NULL, + }; + +-static const struct usb_descriptor_header * const uvc_hs_streaming[] = { +- (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, +- (struct usb_descriptor_header *) &uvc_streaming_ep, ++static const struct usb_descriptor_header * const uvc_hs_streaming1[] = { ++ (struct usb_descriptor_header *) &uvc_streaming1_intf_alt1, ++ (struct usb_descriptor_header *) &uvc_streaming1_ep, ++ (struct usb_descriptor_header *) &uvc_streaming1_intf_alt2, ++ (struct usb_descriptor_header *) &uvc_streaming1_ep2, + NULL, + }; + ++ ++ ++ ++static struct usb_interface_descriptor uvc_streaming2_intf_alt0 = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++static struct usb_interface_descriptor uvc_streaming2_intf_alt1 = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, ++ .bAlternateSetting = 1, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++static struct usb_endpoint_descriptor uvc_streaming2_ep = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = cpu_to_le16(1020), /*1020*/ ++ .bInterval = 1, ++}; ++ ++static struct usb_interface_descriptor uvc_streaming2_intf_alt2 = { ++ .bLength = USB_DT_INTERFACE_SIZE, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, ++ .bAlternateSetting = 2, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, ++ .bInterfaceProtocol = 0x00, ++ .iInterface = 0, ++}; ++ ++static struct usb_endpoint_descriptor uvc_streaming2_ep2 = { ++ .bLength = USB_DT_ENDPOINT_SIZE, ++ .bDescriptorType = USB_DT_ENDPOINT, ++ .bEndpointAddress = USB_DIR_IN, ++ .bmAttributes = USB_ENDPOINT_XFER_ISOC, ++ .wMaxPacketSize = cpu_to_le16(512), ++ .bInterval = 1, ++}; ++ ++static const struct usb_descriptor_header * const uvc_fs_streaming2[] = { ++ (struct usb_descriptor_header *) &uvc_streaming2_intf_alt1, ++ (struct usb_descriptor_header *) &uvc_streaming2_ep, ++ (struct usb_descriptor_header *) &uvc_streaming2_intf_alt2, ++ (struct usb_descriptor_header *) &uvc_streaming2_ep2, ++ NULL, ++}; ++ ++static const struct usb_descriptor_header * const uvc_hs_streaming2[] = { ++ (struct usb_descriptor_header *) &uvc_streaming2_intf_alt1, ++ (struct usb_descriptor_header *) &uvc_streaming2_ep, ++ (struct usb_descriptor_header *) &uvc_streaming2_intf_alt2, ++ (struct usb_descriptor_header *) &uvc_streaming2_ep2, ++ NULL, ++}; ++ ++ + /* -------------------------------------------------------------------------- + * Control requests + */ +@@ -169,14 +276,14 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) + static int + uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + { +- struct uvc_device *uvc = to_uvc(f); ++/* struct uvc_device *uvc = to_uvc(f);*/ ++ struct uvc_common *comm = to_common(f); + struct v4l2_event v4l2_event; + struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; ++ unsigned int intf = ctrl->wIndex & 0xff; + +- /* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n", +- * ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue), +- * le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength)); +- */ ++ gLastIntf = intf; ++ gLastDirOut = (ctrl->bRequestType & USB_DIR_OUT) == USB_DIR_OUT; + + if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { + INFO(f->config->cdev, "invalid request type\n"); +@@ -190,8 +297,15 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_SETUP; + memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); +- v4l2_event_queue(uvc->vdev, &v4l2_event); + ++ ++#ifdef UVC_DOUBLE_STREAM ++ if (intf == comm->uvc2->streaming_intf) { ++ v4l2_event_queue(comm->uvc2->vdev, &v4l2_event); ++ } ++ else ++#endif ++ v4l2_event_queue(comm->uvc1->vdev, &v4l2_event); + return 0; + } + +@@ -199,58 +313,82 @@ static int + uvc_function_get_alt(struct usb_function *f, unsigned interface) + { + struct uvc_device *uvc = to_uvc(f); ++ struct uvc_common *comm = to_common(f); + + INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface); + +- if (interface == uvc->control_intf) ++ if (interface == uvc->comm->control_intf) { + return 0; +- else if (interface != uvc->streaming_intf) +- return -EINVAL; ++ } else if (interface == comm->uvc1->streaming_intf) ++ return comm->uvc1->state == ++ UVC_STATE_STREAMING ? 1 : 0; ++ ++#ifdef UVC_DOUBLE_STREAM ++ else if (interface == comm->uvc2->streaming_intf) ++ return comm->uvc2->state == UVC_STATE_STREAMING ? 1 : 0; ++ ++#endif + else +- return uvc->state == UVC_STATE_STREAMING ? 1 : 0; ++ return -EINVAL; ++ + } + + static int + uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) + { + struct uvc_device *uvc = to_uvc(f); ++ struct uvc_common *comm = to_common(f); + struct v4l2_event v4l2_event; + struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; + ++ struct uvc_device *uvc1 = comm->uvc1; ++ struct uvc_device *uvc2 = comm->uvc2; ++ ++ ++ if (interface == uvc1->streaming_intf) ++ uvc = uvc1; ++ ++#ifdef UVC_DOUBLE_STREAM ++ else if (interface == uvc2->streaming_intf) ++ uvc = uvc2; ++ ++#endif ++ + INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); + +- if (interface == uvc->control_intf) { ++ if (interface == uvc->comm->control_intf) { + if (alt) + return -EINVAL; + +- if (uvc->state == UVC_STATE_DISCONNECTED) { ++ if (uvc1->state == UVC_STATE_DISCONNECTED) { + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_CONNECT; + uvc_event->speed = f->config->cdev->gadget->speed; +- v4l2_event_queue(uvc->vdev, &v4l2_event); +- +- uvc->state = UVC_STATE_CONNECTED; ++ v4l2_event_queue(uvc1->vdev, &v4l2_event); ++ uvc1->state = UVC_STATE_CONNECTED; + } + ++#ifdef UVC_DOUBLE_STREAM ++ if (uvc2->state == UVC_STATE_DISCONNECTED) { ++ memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ v4l2_event.type = UVC_EVENT_CONNECT; ++ uvc_event->speed = f->config->cdev->gadget->speed; ++ v4l2_event_queue(uvc2->vdev, &v4l2_event); ++ ++ uvc2->state = UVC_STATE_CONNECTED; ++ } ++#endif + return 0; + } + +- if (interface != uvc->streaming_intf) ++ if (interface != uvc1->streaming_intf && interface != ++ uvc2->streaming_intf) + return -EINVAL; + +- /* TODO +- if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)) +- return alt ? -EINVAL : 0; +- */ +- + switch (alt) { + case 0: + if (uvc->state != UVC_STATE_STREAMING) + return 0; +- +- if (uvc->video.ep) +- usb_ep_disable(uvc->video.ep); +- + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_STREAMOFF; + v4l2_event_queue(uvc->vdev, &v4l2_event); +@@ -259,16 +397,65 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) + break; + + case 1: ++ case 2: + if (uvc->state != UVC_STATE_CONNECTED) + return 0; + +- if (uvc->video.ep) +- usb_ep_enable(uvc->video.ep, &uvc_streaming_ep); +- + memset(&v4l2_event, 0, sizeof(v4l2_event)); ++ if (interface == uvc1->streaming_intf) { ++ if (alt == 2) { ++ uvc->video.ep = video_stream1_ep2; ++ v4l2_event.u.data[0] = ++ uvc_streaming1_ep2.wMaxPacketSize&0xff; ++ v4l2_event.u.data[1] = ++ uvc_streaming1_ep2.wMaxPacketSize>>8; ++ } else { ++ uvc->video.ep = video_stream1_ep1; ++ v4l2_event.u.data[0] = ++ uvc_streaming1_ep.wMaxPacketSize&0xff; ++ v4l2_event.u.data[1] = ++ uvc_streaming1_ep.wMaxPacketSize>>8; ++ ++ } ++ ++ if (uvc->video.ep) { ++ if (alt == 2) ++ usb_ep_enable(uvc->video.ep,\ ++ &uvc_streaming1_ep2); ++ else ++ usb_ep_enable(uvc->video.ep,\ ++ &uvc_streaming1_ep); ++ } ++ } ++#ifdef UVC_DOUBLE_STREAM ++ else if (interface == uvc2->streaming_intf) { ++ if (alt == 2) { ++ uvc->video.ep = video_stream2_ep2; ++ v4l2_event.u.data[0] = ++ uvc_streaming2_ep2.wMaxPacketSize&0xff; ++ v4l2_event.u.data[1] = ++ uvc_streaming2_ep2.wMaxPacketSize>>8; ++ } else { ++ uvc->video.ep = video_stream2_ep1; ++ v4l2_event.u.data[0] = ++ uvc_streaming2_ep.wMaxPacketSize&0xff; ++ v4l2_event.u.data[1] = ++ uvc_streaming2_ep.wMaxPacketSize>>8; ++ ++ } ++ ++ if (uvc->video.ep) { ++ if (alt == 2) ++ usb_ep_enable(uvc->video.ep,\ ++ &uvc_streaming2_ep2); ++ else ++ usb_ep_enable(uvc->video.ep,\ ++ &uvc_streaming2_ep); ++ } ++ } ++#endif + v4l2_event.type = UVC_EVENT_STREAMON; + v4l2_event_queue(uvc->vdev, &v4l2_event); +- + uvc->state = UVC_STATE_STREAMING; + break; + +@@ -282,16 +469,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) + static void + uvc_function_disable(struct usb_function *f) + { +- struct uvc_device *uvc = to_uvc(f); ++ /*struct uvc_device *uvc = to_uvc(f);*/ ++ struct uvc_common *comm = to_common(f); + struct v4l2_event v4l2_event; + + INFO(f->config->cdev, "uvc_function_disable\n"); ++ printk(KERN_EMERG "######### uvc disable #########\n"); + + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_DISCONNECT; +- v4l2_event_queue(uvc->vdev, &v4l2_event); ++ v4l2_event_queue(comm->uvc1->vdev, &v4l2_event); ++ comm->uvc1->state = UVC_STATE_DISCONNECTED; + +- uvc->state = UVC_STATE_DISCONNECTED; ++#ifdef UVC_DOUBLE_STREAM ++ v4l2_event_queue(comm->uvc2->vdev, &v4l2_event); ++ comm->uvc2->state = UVC_STATE_DISCONNECTED; ++#endif + } + + /* -------------------------------------------------------------------------- +@@ -301,20 +494,20 @@ uvc_function_disable(struct usb_function *f) + void + uvc_function_connect(struct uvc_device *uvc) + { +- struct usb_composite_dev *cdev = uvc->func.config->cdev; ++ struct usb_composite_dev *cdev = uvc->comm->func.config->cdev; + int ret; +- +- if ((ret = usb_function_activate(&uvc->func)) < 0) ++ ret = usb_function_activate(&uvc->comm->func); ++ if (ret < 0) + INFO(cdev, "UVC connect failed with %d\n", ret); + } + + void + uvc_function_disconnect(struct uvc_device *uvc) + { +- struct usb_composite_dev *cdev = uvc->func.config->cdev; ++ struct usb_composite_dev *cdev = uvc->comm->func.config->cdev; + int ret; +- +- if ((ret = usb_function_deactivate(&uvc->func)) < 0) ++ ret = usb_function_deactivate(&uvc->comm->func); ++ if (ret < 0) + INFO(cdev, "UVC disconnect failed with %d\n", ret); + } + +@@ -325,7 +518,7 @@ uvc_function_disconnect(struct uvc_device *uvc) + static int + uvc_register_video(struct uvc_device *uvc) + { +- struct usb_composite_dev *cdev = uvc->func.config->cdev; ++ struct usb_composite_dev *cdev = uvc->comm->func.config->cdev; + struct video_device *video; + + /* TODO reference counting. */ +@@ -362,12 +555,12 @@ uvc_register_video(struct uvc_device *uvc) + } \ + } while (0) + +-static struct usb_descriptor_header ** __init ++static struct usb_descriptor_header** /*__init*/ + uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + { + struct uvc_input_header_descriptor *uvc_streaming_header; + struct uvc_header_descriptor *uvc_control_header; +- const struct uvc_descriptor_header * const *uvc_streaming_cls; ++ struct uvc_descriptor_header **uvc_streaming_cls; + const struct usb_descriptor_header * const *uvc_streaming_std; + const struct usb_descriptor_header * const *src; + struct usb_descriptor_header **dst; +@@ -377,11 +570,30 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + unsigned int n_desc; + unsigned int bytes; + void *mem; ++ int needBufLen; ++ ++ ++ unsigned int stream2_avalid = 0; ++ struct uvc_descriptor_header **uvc_streaming2_cls = NULL; ++ const struct usb_descriptor_header * const *uvc_streaming2_std = NULL; ++ unsigned int streaming2_size; ++ ++ stream2_avalid = (uvc->comm->desc.fs_streaming2 != NULL); + + uvc_streaming_cls = (speed == USB_SPEED_FULL) +- ? uvc->desc.fs_streaming : uvc->desc.hs_streaming; ++ ? uvc->comm->desc.fs_streaming : uvc->comm->desc.hs_streaming; + uvc_streaming_std = (speed == USB_SPEED_FULL) +- ? uvc_fs_streaming : uvc_hs_streaming; ++ ? uvc_fs_streaming1 : uvc_hs_streaming1; ++ ++ ++ if (stream2_avalid) { ++ uvc_streaming2_cls = (speed == USB_SPEED_FULL) ++ ? uvc->comm->desc.fs_streaming2 : uvc->comm->desc.hs_streaming2; ++ uvc_streaming2_std = (speed == USB_SPEED_FULL) ++ ? uvc_fs_streaming2 : uvc_hs_streaming2; ++ ++ uvc_iad.bInterfaceCount = 3; ++ } + + /* Descriptors layout + * +@@ -399,16 +611,17 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + control_size = 0; + streaming_size = 0; + bytes = uvc_iad.bLength + uvc_control_intf.bLength +- + uvc_control_ep.bLength + uvc_control_cs_ep.bLength +- + uvc_streaming_intf_alt0.bLength; ++ + uvc_control_ep.bLength + uvc_control_cs_ep.bLength ++ + uvc_streaming1_intf_alt0.bLength; + n_desc = 5; + +- for (src = (const struct usb_descriptor_header**)uvc->desc.control; *src; ++src) { ++ ++ for (src = (const struct usb_descriptor_header **)uvc->comm->desc.control; *src; ++src) { + control_size += (*src)->bLength; + bytes += (*src)->bLength; + n_desc++; + } +- for (src = (const struct usb_descriptor_header**)uvc_streaming_cls; *src; ++src) { ++ for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; *src; ++src) { + streaming_size += (*src)->bLength; + bytes += (*src)->bLength; + n_desc++; +@@ -418,7 +631,28 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + n_desc++; + } + +- mem = kmalloc((n_desc + 1) * sizeof(*src) + bytes, GFP_KERNEL); ++ if (stream2_avalid) { ++ bytes += uvc_streaming2_intf_alt0.bLength; ++ n_desc++; ++ for (src = (const struct usb_descriptor_header **)uvc_streaming2_cls; *src; ++src) { ++ streaming2_size += (*src)->bLength; ++ bytes += (*src)->bLength; ++ n_desc++; ++ } ++ ++ for (src = uvc_streaming2_std; *src; ++src) { ++ bytes += (*src)->bLength; ++ n_desc++; ++ } ++ } ++ ++ ++ ++/* printk(KERN_EMERG "#########uvc_copy_descriptors 44\n");*/ ++ ++ needBufLen = (n_desc + 1) * sizeof(*src) + bytes; ++ ++ mem = kmalloc(needBufLen, GFP_KERNEL); + if (mem == NULL) + return NULL; + +@@ -432,24 +666,51 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) + + uvc_control_header = mem; + UVC_COPY_DESCRIPTORS(mem, dst, +- (const struct usb_descriptor_header**)uvc->desc.control); ++ (const struct usb_descriptor_header **)uvc->comm->desc.control); + uvc_control_header->wTotalLength = cpu_to_le16(control_size); +- uvc_control_header->bInCollection = 1; ++ + uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; ++ if (stream2_avalid) { ++ uvc_control_header->baInterfaceNr[1] = ++ uvc->comm->uvc2->streaming_intf; ++ uvc_control_header->bInCollection = 2; ++ ++ } else { ++ uvc_control_header->bInCollection = 1; ++ } ++ + + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_cs_ep); +- UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0); ++ UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming1_intf_alt0); + + uvc_streaming_header = mem; + UVC_COPY_DESCRIPTORS(mem, dst, +- (const struct usb_descriptor_header**)uvc_streaming_cls); ++ (const struct usb_descriptor_header **)uvc_streaming_cls); + uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); +- uvc_streaming_header->bEndpointAddress = uvc_streaming_ep.bEndpointAddress; ++ uvc_streaming_header->bEndpointAddress = ++ uvc_streaming1_ep.bEndpointAddress; + + UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); + ++ if (stream2_avalid) { ++ UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming2_intf_alt0); ++ uvc_streaming_header = mem; ++ UVC_COPY_DESCRIPTORS(mem, dst, ++ (const struct usb_descriptor_header **)uvc_streaming2_cls); ++ uvc_streaming_header->wTotalLength = ++ cpu_to_le16(streaming2_size); ++ uvc_streaming_header->bEndpointAddress = ++ uvc_streaming2_ep.bEndpointAddress; ++#ifdef UVC_DOUBLE_STREAM ++ uvc_streaming_header->bTerminalLink++; ++#endif ++ ++ UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming2_std); ++ } ++ + *dst = NULL; ++ + return hdr; + } + +@@ -460,6 +721,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) + struct uvc_device *uvc = to_uvc(f); + + INFO(cdev, "uvc_function_unbind\n"); ++ printk(KERN_EMERG "######### uvc unbind #########\n"); + + if (uvc->vdev) { + if (uvc->vdev->minor == -1) +@@ -469,14 +731,14 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) + uvc->vdev = NULL; + } + +- if (uvc->control_ep) +- uvc->control_ep->driver_data = NULL; ++ if (uvc->comm->control_ep) ++ uvc->comm->control_ep->driver_data = NULL; + if (uvc->video.ep) + uvc->video.ep->driver_data = NULL; + +- if (uvc->control_req) { +- usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); +- kfree(uvc->control_buf); ++ if (uvc->comm->control_req) { ++ usb_ep_free_request(cdev->gadget->ep0, uvc->comm->control_req); ++ kfree(uvc->comm->control_buf); + } + + kfree(f->descriptors); +@@ -490,9 +752,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + { + struct usb_composite_dev *cdev = c->cdev; + struct uvc_device *uvc = to_uvc(f); ++ struct uvc_common *comm = to_common(f); ++ struct uvc_device *uvc1, *uvc2; + struct usb_ep *ep; + int ret = -EINVAL; + ++ uvc1 = comm->uvc1; ++ uvc2 = comm->uvc2; ++ + INFO(cdev, "uvc_function_bind\n"); + + /* Allocate endpoints. */ +@@ -501,64 +768,119 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) + INFO(cdev, "Unable to allocate control EP\n"); + goto error; + } +- uvc->control_ep = ep; +- ep->driver_data = uvc; + +- ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming_ep); ++ comm->control_ep = ep; ++ ep->driver_data = uvc; ++ ep = usb_ep_autoconfig(cdev->gadget, &uvc_streaming1_ep); + if (!ep) { + INFO(cdev, "Unable to allocate streaming EP\n"); + goto error; + } ++ video_stream1_ep1 = ep; + uvc->video.ep = ep; +- ep->driver_data = uvc; +- ++ ep->driver_data = uvc1; ++ video_stream1_ep2 = ++ usb_ep_autoconfig(cdev->gadget, &uvc_streaming1_ep2); ++ if (!video_stream1_ep2) { ++ INFO(cdev, "Unable to allocate streaming EP2\n"); ++ goto error; ++ } ++ video_stream1_ep2->driver_data = uvc1; + /* Allocate interface IDs. */ +- if ((ret = usb_interface_id(c, f)) < 0) ++ ret = usb_interface_id(c, f); ++ if (ret < 0) + goto error; + uvc_iad.bFirstInterface = ret; + uvc_control_intf.bInterfaceNumber = ret; +- uvc->control_intf = ret; +- +- if ((ret = usb_interface_id(c, f)) < 0) ++ comm->control_intf = ret; ++ ret = usb_interface_id(c, f); ++ if (ret < 0) + goto error; +- uvc_streaming_intf_alt0.bInterfaceNumber = ret; +- uvc_streaming_intf_alt1.bInterfaceNumber = ret; +- uvc->streaming_intf = ret; ++ ++ uvc_streaming1_intf_alt0.bInterfaceNumber = ret; ++ uvc_streaming1_intf_alt1.bInterfaceNumber = ret; ++ uvc_streaming1_intf_alt2.bInterfaceNumber = ret; ++ uvc1->streaming_intf = ret; ++ ++ ++ if (NULL != comm->desc.fs_streaming2) { ++ ++ video_stream2_ep1 = ++ usb_ep_autoconfig(cdev->gadget, &uvc_streaming2_ep); ++ if (!video_stream2_ep1) { ++ INFO(cdev, "Unable to allocate streaming EP\n"); ++ goto error; ++ } ++ ++ uvc2->video.ep = video_stream2_ep1; ++ video_stream2_ep1->driver_data = uvc2; ++ ++ video_stream2_ep2 = ++ usb_ep_autoconfig(cdev->gadget, &uvc_streaming2_ep2); ++ if (!video_stream2_ep2) { ++ INFO(cdev, "Unable to allocate streaming EP2\n"); ++ goto error; ++ } ++ ++ video_stream2_ep2->driver_data = uvc2; ++ ret = usb_interface_id(c, f); ++ if (ret < 0) ++ goto error; ++ uvc_streaming2_intf_alt0.bInterfaceNumber = ret; ++ uvc_streaming2_intf_alt1.bInterfaceNumber = ret; ++ uvc_streaming2_intf_alt2.bInterfaceNumber = ret; ++ uvc2->streaming_intf = ret; ++ } + + /* Copy descriptors. */ + f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); + f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); + + /* Preallocate control endpoint request. */ +- uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); +- uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); +- if (uvc->control_req == NULL || uvc->control_buf == NULL) { ++ comm->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); ++ comm->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); ++ if (uvc->comm->control_req == NULL || uvc->comm->control_buf == NULL) { + ret = -ENOMEM; + goto error; + } + +- uvc->control_req->buf = uvc->control_buf; +- uvc->control_req->complete = uvc_function_ep0_complete; +- uvc->control_req->context = uvc; ++ comm->control_req->buf = uvc->comm->control_buf; ++ comm->control_req->complete = uvc_function_ep0_complete; ++ comm->control_req->context = uvc; + + /* Avoid letting this gadget enumerate until the userspace server is + * active. + */ +- if ((ret = usb_function_deactivate(f)) < 0) ++ ret = usb_function_deactivate(f); ++ if (ret < 0) + goto error; + + /* Initialise video. */ +- ret = uvc_video_init(&uvc->video); ++ ret = uvc_video_init(&uvc1->video); + if (ret < 0) + goto error; +- + /* Register a V4L2 device. */ +- ret = uvc_register_video(uvc); ++ ret = uvc_register_video(uvc1); + if (ret < 0) { + printk(KERN_INFO "Unable to register video device\n"); + goto error; + } + ++ if (NULL != comm->desc.fs_streaming2) { ++ ret = usb_function_deactivate(f); ++ if (ret < 0) ++ goto error; ++ /* Initialise video. */ ++ ret = uvc_video_init(&uvc2->video); ++ if (ret < 0) ++ goto error; ++ /* Register a V4L2 device. */ ++ ret = uvc_register_video(uvc2); ++ if (ret < 0) { ++ printk(KERN_INFO "Unable to register video2 device\n"); ++ goto error; ++ } ++ } + return 0; + + error: +@@ -587,6 +909,8 @@ uvc_bind_config(struct usb_configuration *c, + const struct uvc_descriptor_header * const *hs_streaming) + { + struct uvc_device *uvc; ++ struct uvc_device *uvc2; ++ struct uvc_common *comm; + int ret = 0; + + /* TODO Check if the USB device controller supports the required +@@ -601,54 +925,92 @@ uvc_bind_config(struct usb_configuration *c, + + uvc->state = UVC_STATE_DISCONNECTED; + ++ ++ comm = kzalloc(sizeof(*comm), GFP_KERNEL); ++ if (comm == NULL) ++ return -ENOMEM; ++ ++ uvc->comm = comm; ++ comm->uvc1 = uvc; ++ ++ ++ uvc2 = kzalloc(sizeof(*uvc), GFP_KERNEL); ++ if (uvc == NULL) ++ return -ENOMEM; ++ ++ uvc2->state = UVC_STATE_DISCONNECTED; ++ uvc2->comm = comm; ++ comm->uvc2 = uvc2; ++ + /* Validate the descriptors. */ + if (control == NULL || control[0] == NULL || +- control[0]->bDescriptorSubType != UVC_VC_HEADER) ++ control[0]->bDescriptorSubType != UVC_VC_HEADER) + goto error; + + if (fs_streaming == NULL || fs_streaming[0] == NULL || +- fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) ++ fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + goto error; + + if (hs_streaming == NULL || hs_streaming[0] == NULL || +- hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) ++ hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + goto error; + +- uvc->desc.control = control; +- uvc->desc.fs_streaming = fs_streaming; +- uvc->desc.hs_streaming = hs_streaming; ++ uvc->comm->desc.control = (struct uvc_descriptor_header **)control; ++ uvc->comm->desc.fs_streaming = ++ (struct uvc_descriptor_header **)fs_streaming; ++ uvc->comm->desc.hs_streaming = ++ (struct uvc_descriptor_header **)hs_streaming; ++ ++#ifdef UVC_DOUBLE_STREAM ++ uvc->comm->desc.fs_streaming2 = ++ (struct uvc_descriptor_header **)fs_streaming; ++ uvc->comm->desc.hs_streaming2 = ++ (struct uvc_descriptor_header **)hs_streaming; ++#endif + + /* Allocate string descriptor numbers. */ +- if ((ret = usb_string_id(c->cdev)) < 0) ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret; + uvc_iad.iFunction = ret; + +- if ((ret = usb_string_id(c->cdev)) < 0) ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret; + uvc_control_intf.iInterface = ret; + +- if ((ret = usb_string_id(c->cdev)) < 0) ++ ret = usb_string_id(c->cdev); ++ if (ret < 0) + goto error; + uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret; +- uvc_streaming_intf_alt0.iInterface = ret; +- uvc_streaming_intf_alt1.iInterface = ret; ++ uvc_streaming1_intf_alt0.iInterface = ret; ++ uvc_streaming1_intf_alt1.iInterface = ret; ++ uvc_streaming1_intf_alt2.iInterface = ret; ++ ++ uvc_streaming2_intf_alt0.iInterface = ret; ++ uvc_streaming2_intf_alt1.iInterface = ret; ++ uvc_streaming2_intf_alt2.iInterface = ret; + + /* Register the function. */ +- uvc->func.name = "uvc"; +- uvc->func.strings = uvc_function_strings; +- uvc->func.bind = uvc_function_bind; +- uvc->func.unbind = uvc_function_unbind; +- uvc->func.get_alt = uvc_function_get_alt; +- uvc->func.set_alt = uvc_function_set_alt; +- uvc->func.disable = uvc_function_disable; +- uvc->func.setup = uvc_function_setup; +- +- ret = usb_add_function(c, &uvc->func); ++ uvc->comm->func.name = "uvc"; ++ uvc->comm->func.strings = uvc_function_strings; ++ uvc->comm->func.bind = uvc_function_bind; ++ uvc->comm->func.unbind = uvc_function_unbind; ++ uvc->comm->func.get_alt = uvc_function_get_alt; ++ uvc->comm->func.set_alt = uvc_function_set_alt; ++ uvc->comm->func.disable = uvc_function_disable; ++ uvc->comm->func.setup = uvc_function_setup; ++ ++ ret = usb_add_function(c, &uvc->comm->func); + if (ret) + kfree(uvc); +- ++#ifdef UVC_DOUBLE_STREAM ++ printk(KERN_EMERG "######### uvc bind 2 streams#########\n"); ++#else ++ printk(KERN_EMERG "######### uvc bind 1 stream#########\n"); ++#endif + return 0; + + error: +diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h +index bcdac7c7..4541dce4 100644 +--- a/drivers/usb/gadget/gadget_chips.h ++++ b/drivers/usb/gadget/gadget_chips.h +@@ -136,6 +136,12 @@ + #define gadget_is_s3c_hsotg(g) 0 + #endif + ++#ifdef CONFIG_CONFIG_USB_FH_OTG ++#define gadget_is_fhotg(g) (!strcmp("fh_otg", (g)->name)) ++#else ++#define gadget_is_fhotg(g) 0 ++#endif ++ + #ifdef CONFIG_USB_S3C_HSUDC + #define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name)) + #else +@@ -223,6 +229,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) + return 0x29; + else if (gadget_is_s3c_hsudc(gadget)) + return 0x30; ++ else if (gadget_is_fhotg(gadget)) ++ return 0x31; + + return -ENOENT; + } +diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c +deleted file mode 100644 +index 0dfee282..00000000 +--- a/drivers/usb/gadget/s3c-hsotg.c ++++ /dev/null +@@ -1,3481 +0,0 @@ +-/* linux/drivers/usb/gadget/s3c-hsotg.c +- * +- * Copyright (c) 2011 Samsung Electronics Co., Ltd. +- * http://www.samsung.com +- * +- * Copyright 2008 Openmoko, Inc. +- * Copyright 2008 Simtec Electronics +- * Ben Dooks <ben@simtec.co.uk> +- * http://armlinux.simtec.co.uk/ +- * +- * S3C USB2.0 High-speed / OtG driver +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +-*/ +- +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/spinlock.h> +-#include <linux/interrupt.h> +-#include <linux/platform_device.h> +-#include <linux/dma-mapping.h> +-#include <linux/debugfs.h> +-#include <linux/seq_file.h> +-#include <linux/delay.h> +-#include <linux/io.h> +-#include <linux/slab.h> +-#include <linux/clk.h> +- +-#include <linux/usb/ch9.h> +-#include <linux/usb/gadget.h> +- +-#include <mach/map.h> +- +-#include <plat/regs-usb-hsotg-phy.h> +-#include <plat/regs-usb-hsotg.h> +-#include <mach/regs-sys.h> +-#include <plat/udc-hs.h> +-#include <plat/cpu.h> +- +-#define DMA_ADDR_INVALID (~((dma_addr_t)0)) +- +-/* EP0_MPS_LIMIT +- * +- * Unfortunately there seems to be a limit of the amount of data that can +- * be transferred by IN transactions on EP0. This is either 127 bytes or 3 +- * packets (which practically means 1 packet and 63 bytes of data) when the +- * MPS is set to 64. +- * +- * This means if we are wanting to move >127 bytes of data, we need to +- * split the transactions up, but just doing one packet at a time does +- * not work (this may be an implicit DATA0 PID on first packet of the +- * transaction) and doing 2 packets is outside the controller's limits. +- * +- * If we try to lower the MPS size for EP0, then no transfers work properly +- * for EP0, and the system will fail basic enumeration. As no cause for this +- * has currently been found, we cannot support any large IN transfers for +- * EP0. +- */ +-#define EP0_MPS_LIMIT 64 +- +-struct s3c_hsotg; +-struct s3c_hsotg_req; +- +-/** +- * struct s3c_hsotg_ep - driver endpoint definition. +- * @ep: The gadget layer representation of the endpoint. +- * @name: The driver generated name for the endpoint. +- * @queue: Queue of requests for this endpoint. +- * @parent: Reference back to the parent device structure. +- * @req: The current request that the endpoint is processing. This is +- * used to indicate an request has been loaded onto the endpoint +- * and has yet to be completed (maybe due to data move, or simply +- * awaiting an ack from the core all the data has been completed). +- * @debugfs: File entry for debugfs file for this endpoint. +- * @lock: State lock to protect contents of endpoint. +- * @dir_in: Set to true if this endpoint is of the IN direction, which +- * means that it is sending data to the Host. +- * @index: The index for the endpoint registers. +- * @name: The name array passed to the USB core. +- * @halted: Set if the endpoint has been halted. +- * @periodic: Set if this is a periodic ep, such as Interrupt +- * @sent_zlp: Set if we've sent a zero-length packet. +- * @total_data: The total number of data bytes done. +- * @fifo_size: The size of the FIFO (for periodic IN endpoints) +- * @fifo_load: The amount of data loaded into the FIFO (periodic IN) +- * @last_load: The offset of data for the last start of request. +- * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN +- * +- * This is the driver's state for each registered enpoint, allowing it +- * to keep track of transactions that need doing. Each endpoint has a +- * lock to protect the state, to try and avoid using an overall lock +- * for the host controller as much as possible. +- * +- * For periodic IN endpoints, we have fifo_size and fifo_load to try +- * and keep track of the amount of data in the periodic FIFO for each +- * of these as we don't have a status register that tells us how much +- * is in each of them. (note, this may actually be useless information +- * as in shared-fifo mode periodic in acts like a single-frame packet +- * buffer than a fifo) +- */ +-struct s3c_hsotg_ep { +- struct usb_ep ep; +- struct list_head queue; +- struct s3c_hsotg *parent; +- struct s3c_hsotg_req *req; +- struct dentry *debugfs; +- +- spinlock_t lock; +- +- unsigned long total_data; +- unsigned int size_loaded; +- unsigned int last_load; +- unsigned int fifo_load; +- unsigned short fifo_size; +- +- unsigned char dir_in; +- unsigned char index; +- +- unsigned int halted:1; +- unsigned int periodic:1; +- unsigned int sent_zlp:1; +- +- char name[10]; +-}; +- +-#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */ +- +-/** +- * struct s3c_hsotg - driver state. +- * @dev: The parent device supplied to the probe function +- * @driver: USB gadget driver +- * @plat: The platform specific configuration data. +- * @regs: The memory area mapped for accessing registers. +- * @regs_res: The resource that was allocated when claiming register space. +- * @irq: The IRQ number we are using +- * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. +- * @debug_root: root directrory for debugfs. +- * @debug_file: main status file for debugfs. +- * @debug_fifo: FIFO status file for debugfs. +- * @ep0_reply: Request used for ep0 reply. +- * @ep0_buff: Buffer for EP0 reply data, if needed. +- * @ctrl_buff: Buffer for EP0 control requests. +- * @ctrl_req: Request for EP0 control packets. +- * @eps: The endpoints being supplied to the gadget framework +- */ +-struct s3c_hsotg { +- struct device *dev; +- struct usb_gadget_driver *driver; +- struct s3c_hsotg_plat *plat; +- +- void __iomem *regs; +- struct resource *regs_res; +- int irq; +- struct clk *clk; +- +- unsigned int dedicated_fifos:1; +- +- struct dentry *debug_root; +- struct dentry *debug_file; +- struct dentry *debug_fifo; +- +- struct usb_request *ep0_reply; +- struct usb_request *ctrl_req; +- u8 ep0_buff[8]; +- u8 ctrl_buff[8]; +- +- struct usb_gadget gadget; +- struct s3c_hsotg_ep eps[]; +-}; +- +-/** +- * struct s3c_hsotg_req - data transfer request +- * @req: The USB gadget request +- * @queue: The list of requests for the endpoint this is queued for. +- * @in_progress: Has already had size/packets written to core +- * @mapped: DMA buffer for this request has been mapped via dma_map_single(). +- */ +-struct s3c_hsotg_req { +- struct usb_request req; +- struct list_head queue; +- unsigned char in_progress; +- unsigned char mapped; +-}; +- +-/* conversion functions */ +-static inline struct s3c_hsotg_req *our_req(struct usb_request *req) +-{ +- return container_of(req, struct s3c_hsotg_req, req); +-} +- +-static inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep) +-{ +- return container_of(ep, struct s3c_hsotg_ep, ep); +-} +- +-static inline struct s3c_hsotg *to_hsotg(struct usb_gadget *gadget) +-{ +- return container_of(gadget, struct s3c_hsotg, gadget); +-} +- +-static inline void __orr32(void __iomem *ptr, u32 val) +-{ +- writel(readl(ptr) | val, ptr); +-} +- +-static inline void __bic32(void __iomem *ptr, u32 val) +-{ +- writel(readl(ptr) & ~val, ptr); +-} +- +-/* forward decleration of functions */ +-static void s3c_hsotg_dump(struct s3c_hsotg *hsotg); +- +-/** +- * using_dma - return the DMA status of the driver. +- * @hsotg: The driver state. +- * +- * Return true if we're using DMA. +- * +- * Currently, we have the DMA support code worked into everywhere +- * that needs it, but the AMBA DMA implementation in the hardware can +- * only DMA from 32bit aligned addresses. This means that gadgets such +- * as the CDC Ethernet cannot work as they often pass packets which are +- * not 32bit aligned. +- * +- * Unfortunately the choice to use DMA or not is global to the controller +- * and seems to be only settable when the controller is being put through +- * a core reset. This means we either need to fix the gadgets to take +- * account of DMA alignment, or add bounce buffers (yuerk). +- * +- * Until this issue is sorted out, we always return 'false'. +- */ +-static inline bool using_dma(struct s3c_hsotg *hsotg) +-{ +- return false; /* support is not complete */ +-} +- +-/** +- * s3c_hsotg_en_gsint - enable one or more of the general interrupt +- * @hsotg: The device state +- * @ints: A bitmask of the interrupts to enable +- */ +-static void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) +-{ +- u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); +- u32 new_gsintmsk; +- +- new_gsintmsk = gsintmsk | ints; +- +- if (new_gsintmsk != gsintmsk) { +- dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk); +- writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); +- } +-} +- +-/** +- * s3c_hsotg_disable_gsint - disable one or more of the general interrupt +- * @hsotg: The device state +- * @ints: A bitmask of the interrupts to enable +- */ +-static void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints) +-{ +- u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); +- u32 new_gsintmsk; +- +- new_gsintmsk = gsintmsk & ~ints; +- +- if (new_gsintmsk != gsintmsk) +- writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); +-} +- +-/** +- * s3c_hsotg_ctrl_epint - enable/disable an endpoint irq +- * @hsotg: The device state +- * @ep: The endpoint index +- * @dir_in: True if direction is in. +- * @en: The enable value, true to enable +- * +- * Set or clear the mask for an individual endpoint's interrupt +- * request. +- */ +-static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg, +- unsigned int ep, unsigned int dir_in, +- unsigned int en) +-{ +- unsigned long flags; +- u32 bit = 1 << ep; +- u32 daint; +- +- if (!dir_in) +- bit <<= 16; +- +- local_irq_save(flags); +- daint = readl(hsotg->regs + S3C_DAINTMSK); +- if (en) +- daint |= bit; +- else +- daint &= ~bit; +- writel(daint, hsotg->regs + S3C_DAINTMSK); +- local_irq_restore(flags); +-} +- +-/** +- * s3c_hsotg_init_fifo - initialise non-periodic FIFOs +- * @hsotg: The device instance. +- */ +-static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) +-{ +- unsigned int ep; +- unsigned int addr; +- unsigned int size; +- int timeout; +- u32 val; +- +- /* the ryu 2.6.24 release ahs +- writel(0x1C0, hsotg->regs + S3C_GRXFSIZ); +- writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | +- S3C_GNPTXFSIZ_NPTxFDep(0x1C0), +- hsotg->regs + S3C_GNPTXFSIZ); +- */ +- +- /* set FIFO sizes to 2048/1024 */ +- +- writel(2048, hsotg->regs + S3C_GRXFSIZ); +- writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | +- S3C_GNPTXFSIZ_NPTxFDep(1024), +- hsotg->regs + S3C_GNPTXFSIZ); +- +- /* arange all the rest of the TX FIFOs, as some versions of this +- * block have overlapping default addresses. This also ensures +- * that if the settings have been changed, then they are set to +- * known values. */ +- +- /* start at the end of the GNPTXFSIZ, rounded up */ +- addr = 2048 + 1024; +- size = 768; +- +- /* currently we allocate TX FIFOs for all possible endpoints, +- * and assume that they are all the same size. */ +- +- for (ep = 0; ep <= 15; ep++) { +- val = addr; +- val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; +- addr += size; +- +- writel(val, hsotg->regs + S3C_DPTXFSIZn(ep)); +- } +- +- /* according to p428 of the design guide, we need to ensure that +- * all fifos are flushed before continuing */ +- +- writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh | +- S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL); +- +- /* wait until the fifos are both flushed */ +- timeout = 100; +- while (1) { +- val = readl(hsotg->regs + S3C_GRSTCTL); +- +- if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0) +- break; +- +- if (--timeout == 0) { +- dev_err(hsotg->dev, +- "%s: timeout flushing fifos (GRSTCTL=%08x)\n", +- __func__, val); +- } +- +- udelay(1); +- } +- +- dev_dbg(hsotg->dev, "FIFOs reset, timeout at %d\n", timeout); +-} +- +-/** +- * @ep: USB endpoint to allocate request for. +- * @flags: Allocation flags +- * +- * Allocate a new USB request structure appropriate for the specified endpoint +- */ +-static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, +- gfp_t flags) +-{ +- struct s3c_hsotg_req *req; +- +- req = kzalloc(sizeof(struct s3c_hsotg_req), flags); +- if (!req) +- return NULL; +- +- INIT_LIST_HEAD(&req->queue); +- +- req->req.dma = DMA_ADDR_INVALID; +- return &req->req; +-} +- +-/** +- * is_ep_periodic - return true if the endpoint is in periodic mode. +- * @hs_ep: The endpoint to query. +- * +- * Returns true if the endpoint is in periodic mode, meaning it is being +- * used for an Interrupt or ISO transfer. +- */ +-static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep) +-{ +- return hs_ep->periodic; +-} +- +-/** +- * s3c_hsotg_unmap_dma - unmap the DMA memory being used for the request +- * @hsotg: The device state. +- * @hs_ep: The endpoint for the request +- * @hs_req: The request being processed. +- * +- * This is the reverse of s3c_hsotg_map_dma(), called for the completion +- * of a request to ensure the buffer is ready for access by the caller. +-*/ +-static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct s3c_hsotg_req *hs_req) +-{ +- struct usb_request *req = &hs_req->req; +- enum dma_data_direction dir; +- +- dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +- +- /* ignore this if we're not moving any data */ +- if (hs_req->req.length == 0) +- return; +- +- if (hs_req->mapped) { +- /* we mapped this, so unmap and remove the dma */ +- +- dma_unmap_single(hsotg->dev, req->dma, req->length, dir); +- +- req->dma = DMA_ADDR_INVALID; +- hs_req->mapped = 0; +- } else { +- dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); +- } +-} +- +-/** +- * s3c_hsotg_write_fifo - write packet Data to the TxFIFO +- * @hsotg: The controller state. +- * @hs_ep: The endpoint we're going to write for. +- * @hs_req: The request to write data for. +- * +- * This is called when the TxFIFO has some space in it to hold a new +- * transmission and we have something to give it. The actual setup of +- * the data size is done elsewhere, so all we have to do is to actually +- * write the data. +- * +- * The return value is zero if there is more space (or nothing was done) +- * otherwise -ENOSPC is returned if the FIFO space was used up. +- * +- * This routine is only needed for PIO +-*/ +-static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct s3c_hsotg_req *hs_req) +-{ +- bool periodic = is_ep_periodic(hs_ep); +- u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS); +- int buf_pos = hs_req->req.actual; +- int to_write = hs_ep->size_loaded; +- void *data; +- int can_write; +- int pkt_round; +- +- to_write -= (buf_pos - hs_ep->last_load); +- +- /* if there's nothing to write, get out early */ +- if (to_write == 0) +- return 0; +- +- if (periodic && !hsotg->dedicated_fifos) { +- u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); +- int size_left; +- int size_done; +- +- /* work out how much data was loaded so we can calculate +- * how much data is left in the fifo. */ +- +- size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); +- +- /* if shared fifo, we cannot write anything until the +- * previous data has been completely sent. +- */ +- if (hs_ep->fifo_load != 0) { +- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); +- return -ENOSPC; +- } +- +- dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n", +- __func__, size_left, +- hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size); +- +- /* how much of the data has moved */ +- size_done = hs_ep->size_loaded - size_left; +- +- /* how much data is left in the fifo */ +- can_write = hs_ep->fifo_load - size_done; +- dev_dbg(hsotg->dev, "%s: => can_write1=%d\n", +- __func__, can_write); +- +- can_write = hs_ep->fifo_size - can_write; +- dev_dbg(hsotg->dev, "%s: => can_write2=%d\n", +- __func__, can_write); +- +- if (can_write <= 0) { +- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); +- return -ENOSPC; +- } +- } else if (hsotg->dedicated_fifos && hs_ep->index != 0) { +- can_write = readl(hsotg->regs + S3C_DTXFSTS(hs_ep->index)); +- +- can_write &= 0xffff; +- can_write *= 4; +- } else { +- if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { +- dev_dbg(hsotg->dev, +- "%s: no queue slots available (0x%08x)\n", +- __func__, gnptxsts); +- +- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); +- return -ENOSPC; +- } +- +- can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); +- can_write *= 4; /* fifo size is in 32bit quantities. */ +- } +- +- dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", +- __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); +- +- /* limit to 512 bytes of data, it seems at least on the non-periodic +- * FIFO, requests of >512 cause the endpoint to get stuck with a +- * fragment of the end of the transfer in it. +- */ +- if (can_write > 512) +- can_write = 512; +- +- /* limit the write to one max-packet size worth of data, but allow +- * the transfer to return that it did not run out of fifo space +- * doing it. */ +- if (to_write > hs_ep->ep.maxpacket) { +- to_write = hs_ep->ep.maxpacket; +- +- s3c_hsotg_en_gsint(hsotg, +- periodic ? S3C_GINTSTS_PTxFEmp : +- S3C_GINTSTS_NPTxFEmp); +- } +- +- /* see if we can write data */ +- +- if (to_write > can_write) { +- to_write = can_write; +- pkt_round = to_write % hs_ep->ep.maxpacket; +- +- /* Not sure, but we probably shouldn't be writing partial +- * packets into the FIFO, so round the write down to an +- * exact number of packets. +- * +- * Note, we do not currently check to see if we can ever +- * write a full packet or not to the FIFO. +- */ +- +- if (pkt_round) +- to_write -= pkt_round; +- +- /* enable correct FIFO interrupt to alert us when there +- * is more room left. */ +- +- s3c_hsotg_en_gsint(hsotg, +- periodic ? S3C_GINTSTS_PTxFEmp : +- S3C_GINTSTS_NPTxFEmp); +- } +- +- dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", +- to_write, hs_req->req.length, can_write, buf_pos); +- +- if (to_write <= 0) +- return -ENOSPC; +- +- hs_req->req.actual = buf_pos + to_write; +- hs_ep->total_data += to_write; +- +- if (periodic) +- hs_ep->fifo_load += to_write; +- +- to_write = DIV_ROUND_UP(to_write, 4); +- data = hs_req->req.buf + buf_pos; +- +- writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write); +- +- return (to_write >= can_write) ? -ENOSPC : 0; +-} +- +-/** +- * get_ep_limit - get the maximum data legnth for this endpoint +- * @hs_ep: The endpoint +- * +- * Return the maximum data that can be queued in one go on a given endpoint +- * so that transfers that are too long can be split. +- */ +-static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) +-{ +- int index = hs_ep->index; +- unsigned maxsize; +- unsigned maxpkt; +- +- if (index != 0) { +- maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; +- maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; +- } else { +- maxsize = 64+64; +- if (hs_ep->dir_in) +- maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; +- else +- maxpkt = 2; +- } +- +- /* we made the constant loading easier above by using +1 */ +- maxpkt--; +- maxsize--; +- +- /* constrain by packet count if maxpkts*pktsize is greater +- * than the length register size. */ +- +- if ((maxpkt * hs_ep->ep.maxpacket) < maxsize) +- maxsize = maxpkt * hs_ep->ep.maxpacket; +- +- return maxsize; +-} +- +-/** +- * s3c_hsotg_start_req - start a USB request from an endpoint's queue +- * @hsotg: The controller state. +- * @hs_ep: The endpoint to process a request for +- * @hs_req: The request to start. +- * @continuing: True if we are doing more for the current request. +- * +- * Start the given request running by setting the endpoint registers +- * appropriately, and writing any data to the FIFOs. +- */ +-static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct s3c_hsotg_req *hs_req, +- bool continuing) +-{ +- struct usb_request *ureq = &hs_req->req; +- int index = hs_ep->index; +- int dir_in = hs_ep->dir_in; +- u32 epctrl_reg; +- u32 epsize_reg; +- u32 epsize; +- u32 ctrl; +- unsigned length; +- unsigned packets; +- unsigned maxreq; +- +- if (index != 0) { +- if (hs_ep->req && !continuing) { +- dev_err(hsotg->dev, "%s: active request\n", __func__); +- WARN_ON(1); +- return; +- } else if (hs_ep->req != hs_req && continuing) { +- dev_err(hsotg->dev, +- "%s: continue different req\n", __func__); +- WARN_ON(1); +- return; +- } +- } +- +- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); +- epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index); +- +- dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n", +- __func__, readl(hsotg->regs + epctrl_reg), index, +- hs_ep->dir_in ? "in" : "out"); +- +- /* If endpoint is stalled, we will restart request later */ +- ctrl = readl(hsotg->regs + epctrl_reg); +- +- if (ctrl & S3C_DxEPCTL_Stall) { +- dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); +- return; +- } +- +- length = ureq->length - ureq->actual; +- +- if (0) +- dev_dbg(hsotg->dev, +- "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", +- ureq->buf, length, ureq->dma, +- ureq->no_interrupt, ureq->zero, ureq->short_not_ok); +- +- maxreq = get_ep_limit(hs_ep); +- if (length > maxreq) { +- int round = maxreq % hs_ep->ep.maxpacket; +- +- dev_dbg(hsotg->dev, "%s: length %d, max-req %d, r %d\n", +- __func__, length, maxreq, round); +- +- /* round down to multiple of packets */ +- if (round) +- maxreq -= round; +- +- length = maxreq; +- } +- +- if (length) +- packets = DIV_ROUND_UP(length, hs_ep->ep.maxpacket); +- else +- packets = 1; /* send one packet if length is zero. */ +- +- if (dir_in && index != 0) +- epsize = S3C_DxEPTSIZ_MC(1); +- else +- epsize = 0; +- +- if (index != 0 && ureq->zero) { +- /* test for the packets being exactly right for the +- * transfer */ +- +- if (length == (packets * hs_ep->ep.maxpacket)) +- packets++; +- } +- +- epsize |= S3C_DxEPTSIZ_PktCnt(packets); +- epsize |= S3C_DxEPTSIZ_XferSize(length); +- +- dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n", +- __func__, packets, length, ureq->length, epsize, epsize_reg); +- +- /* store the request as the current one we're doing */ +- hs_ep->req = hs_req; +- +- /* write size / packets */ +- writel(epsize, hsotg->regs + epsize_reg); +- +- if (using_dma(hsotg)) { +- unsigned int dma_reg; +- +- /* write DMA address to control register, buffer already +- * synced by s3c_hsotg_ep_queue(). */ +- +- dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index); +- writel(ureq->dma, hsotg->regs + dma_reg); +- +- dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n", +- __func__, ureq->dma, dma_reg); +- } +- +- ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ +- ctrl |= S3C_DxEPCTL_USBActEp; +- ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ +- +- dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); +- writel(ctrl, hsotg->regs + epctrl_reg); +- +- /* set these, it seems that DMA support increments past the end +- * of the packet buffer so we need to calculate the length from +- * this information. */ +- hs_ep->size_loaded = length; +- hs_ep->last_load = ureq->actual; +- +- if (dir_in && !using_dma(hsotg)) { +- /* set these anyway, we may need them for non-periodic in */ +- hs_ep->fifo_load = 0; +- +- s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); +- } +- +- /* clear the INTknTXFEmpMsk when we start request, more as a aide +- * to debugging to see what is going on. */ +- if (dir_in) +- writel(S3C_DIEPMSK_INTknTXFEmpMsk, +- hsotg->regs + S3C_DIEPINT(index)); +- +- /* Note, trying to clear the NAK here causes problems with transmit +- * on the S3C6400 ending up with the TXFIFO becoming full. */ +- +- /* check ep is enabled */ +- if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna)) +- dev_warn(hsotg->dev, +- "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n", +- index, readl(hsotg->regs + epctrl_reg)); +- +- dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", +- __func__, readl(hsotg->regs + epctrl_reg)); +-} +- +-/** +- * s3c_hsotg_map_dma - map the DMA memory being used for the request +- * @hsotg: The device state. +- * @hs_ep: The endpoint the request is on. +- * @req: The request being processed. +- * +- * We've been asked to queue a request, so ensure that the memory buffer +- * is correctly setup for DMA. If we've been passed an extant DMA address +- * then ensure the buffer has been synced to memory. If our buffer has no +- * DMA memory, then we map the memory and mark our request to allow us to +- * cleanup on completion. +-*/ +-static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct usb_request *req) +-{ +- enum dma_data_direction dir; +- struct s3c_hsotg_req *hs_req = our_req(req); +- +- dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +- +- /* if the length is zero, ignore the DMA data */ +- if (hs_req->req.length == 0) +- return 0; +- +- if (req->dma == DMA_ADDR_INVALID) { +- dma_addr_t dma; +- +- dma = dma_map_single(hsotg->dev, req->buf, req->length, dir); +- +- if (unlikely(dma_mapping_error(hsotg->dev, dma))) +- goto dma_error; +- +- if (dma & 3) { +- dev_err(hsotg->dev, "%s: unaligned dma buffer\n", +- __func__); +- +- dma_unmap_single(hsotg->dev, dma, req->length, dir); +- return -EINVAL; +- } +- +- hs_req->mapped = 1; +- req->dma = dma; +- } else { +- dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); +- hs_req->mapped = 0; +- } +- +- return 0; +- +-dma_error: +- dev_err(hsotg->dev, "%s: failed to map buffer %p, %d bytes\n", +- __func__, req->buf, req->length); +- +- return -EIO; +-} +- +-static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, +- gfp_t gfp_flags) +-{ +- struct s3c_hsotg_req *hs_req = our_req(req); +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hs = hs_ep->parent; +- unsigned long irqflags; +- bool first; +- +- dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", +- ep->name, req, req->length, req->buf, req->no_interrupt, +- req->zero, req->short_not_ok); +- +- /* initialise status of the request */ +- INIT_LIST_HEAD(&hs_req->queue); +- req->actual = 0; +- req->status = -EINPROGRESS; +- +- /* if we're using DMA, sync the buffers as necessary */ +- if (using_dma(hs)) { +- int ret = s3c_hsotg_map_dma(hs, hs_ep, req); +- if (ret) +- return ret; +- } +- +- spin_lock_irqsave(&hs_ep->lock, irqflags); +- +- first = list_empty(&hs_ep->queue); +- list_add_tail(&hs_req->queue, &hs_ep->queue); +- +- if (first) +- s3c_hsotg_start_req(hs, hs_ep, hs_req, false); +- +- spin_unlock_irqrestore(&hs_ep->lock, irqflags); +- +- return 0; +-} +- +-static void s3c_hsotg_ep_free_request(struct usb_ep *ep, +- struct usb_request *req) +-{ +- struct s3c_hsotg_req *hs_req = our_req(req); +- +- kfree(hs_req); +-} +- +-/** +- * s3c_hsotg_complete_oursetup - setup completion callback +- * @ep: The endpoint the request was on. +- * @req: The request completed. +- * +- * Called on completion of any requests the driver itself +- * submitted that need cleaning up. +- */ +-static void s3c_hsotg_complete_oursetup(struct usb_ep *ep, +- struct usb_request *req) +-{ +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hsotg = hs_ep->parent; +- +- dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req); +- +- s3c_hsotg_ep_free_request(ep, req); +-} +- +-/** +- * ep_from_windex - convert control wIndex value to endpoint +- * @hsotg: The driver state. +- * @windex: The control request wIndex field (in host order). +- * +- * Convert the given wIndex into a pointer to an driver endpoint +- * structure, or return NULL if it is not a valid endpoint. +-*/ +-static struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, +- u32 windex) +-{ +- struct s3c_hsotg_ep *ep = &hsotg->eps[windex & 0x7F]; +- int dir = (windex & USB_DIR_IN) ? 1 : 0; +- int idx = windex & 0x7F; +- +- if (windex >= 0x100) +- return NULL; +- +- if (idx > S3C_HSOTG_EPS) +- return NULL; +- +- if (idx && ep->dir_in != dir) +- return NULL; +- +- return ep; +-} +- +-/** +- * s3c_hsotg_send_reply - send reply to control request +- * @hsotg: The device state +- * @ep: Endpoint 0 +- * @buff: Buffer for request +- * @length: Length of reply. +- * +- * Create a request and queue it on the given endpoint. This is useful as +- * an internal method of sending replies to certain control requests, etc. +- */ +-static int s3c_hsotg_send_reply(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *ep, +- void *buff, +- int length) +-{ +- struct usb_request *req; +- int ret; +- +- dev_dbg(hsotg->dev, "%s: buff %p, len %d\n", __func__, buff, length); +- +- req = s3c_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC); +- hsotg->ep0_reply = req; +- if (!req) { +- dev_warn(hsotg->dev, "%s: cannot alloc req\n", __func__); +- return -ENOMEM; +- } +- +- req->buf = hsotg->ep0_buff; +- req->length = length; +- req->zero = 1; /* always do zero-length final transfer */ +- req->complete = s3c_hsotg_complete_oursetup; +- +- if (length) +- memcpy(req->buf, buff, length); +- else +- ep->sent_zlp = 1; +- +- ret = s3c_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC); +- if (ret) { +- dev_warn(hsotg->dev, "%s: cannot queue req\n", __func__); +- return ret; +- } +- +- return 0; +-} +- +-/** +- * s3c_hsotg_process_req_status - process request GET_STATUS +- * @hsotg: The device state +- * @ctrl: USB control request +- */ +-static int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg, +- struct usb_ctrlrequest *ctrl) +-{ +- struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; +- struct s3c_hsotg_ep *ep; +- __le16 reply; +- int ret; +- +- dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__); +- +- if (!ep0->dir_in) { +- dev_warn(hsotg->dev, "%s: direction out?\n", __func__); +- return -EINVAL; +- } +- +- switch (ctrl->bRequestType & USB_RECIP_MASK) { +- case USB_RECIP_DEVICE: +- reply = cpu_to_le16(0); /* bit 0 => self powered, +- * bit 1 => remote wakeup */ +- break; +- +- case USB_RECIP_INTERFACE: +- /* currently, the data result should be zero */ +- reply = cpu_to_le16(0); +- break; +- +- case USB_RECIP_ENDPOINT: +- ep = ep_from_windex(hsotg, le16_to_cpu(ctrl->wIndex)); +- if (!ep) +- return -ENOENT; +- +- reply = cpu_to_le16(ep->halted ? 1 : 0); +- break; +- +- default: +- return 0; +- } +- +- if (le16_to_cpu(ctrl->wLength) != 2) +- return -EINVAL; +- +- ret = s3c_hsotg_send_reply(hsotg, ep0, &reply, 2); +- if (ret) { +- dev_err(hsotg->dev, "%s: failed to send reply\n", __func__); +- return ret; +- } +- +- return 1; +-} +- +-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); +- +-/** +- * get_ep_head - return the first request on the endpoint +- * @hs_ep: The controller endpoint to get +- * +- * Get the first request on the endpoint. +- */ +-static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) +-{ +- if (list_empty(&hs_ep->queue)) +- return NULL; +- +- return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); +-} +- +-/** +- * s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE +- * @hsotg: The device state +- * @ctrl: USB control request +- */ +-static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, +- struct usb_ctrlrequest *ctrl) +-{ +- struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; +- struct s3c_hsotg_req *hs_req; +- bool restart; +- bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); +- struct s3c_hsotg_ep *ep; +- int ret; +- +- dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", +- __func__, set ? "SET" : "CLEAR"); +- +- if (ctrl->bRequestType == USB_RECIP_ENDPOINT) { +- ep = ep_from_windex(hsotg, le16_to_cpu(ctrl->wIndex)); +- if (!ep) { +- dev_dbg(hsotg->dev, "%s: no endpoint for 0x%04x\n", +- __func__, le16_to_cpu(ctrl->wIndex)); +- return -ENOENT; +- } +- +- switch (le16_to_cpu(ctrl->wValue)) { +- case USB_ENDPOINT_HALT: +- s3c_hsotg_ep_sethalt(&ep->ep, set); +- +- ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); +- if (ret) { +- dev_err(hsotg->dev, +- "%s: failed to send reply\n", __func__); +- return ret; +- } +- +- if (!set) { +- /* +- * If we have request in progress, +- * then complete it +- */ +- if (ep->req) { +- hs_req = ep->req; +- ep->req = NULL; +- list_del_init(&hs_req->queue); +- hs_req->req.complete(&ep->ep, +- &hs_req->req); +- } +- +- /* If we have pending request, then start it */ +- restart = !list_empty(&ep->queue); +- if (restart) { +- hs_req = get_ep_head(ep); +- s3c_hsotg_start_req(hsotg, ep, +- hs_req, false); +- } +- } +- +- break; +- +- default: +- return -ENOENT; +- } +- } else +- return -ENOENT; /* currently only deal with endpoint */ +- +- return 1; +-} +- +-/** +- * s3c_hsotg_process_control - process a control request +- * @hsotg: The device state +- * @ctrl: The control request received +- * +- * The controller has received the SETUP phase of a control request, and +- * needs to work out what to do next (and whether to pass it on to the +- * gadget driver). +- */ +-static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, +- struct usb_ctrlrequest *ctrl) +-{ +- struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; +- int ret = 0; +- u32 dcfg; +- +- ep0->sent_zlp = 0; +- +- dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n", +- ctrl->bRequest, ctrl->bRequestType, +- ctrl->wValue, ctrl->wLength); +- +- /* record the direction of the request, for later use when enquing +- * packets onto EP0. */ +- +- ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0; +- dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in); +- +- /* if we've no data with this request, then the last part of the +- * transaction is going to implicitly be IN. */ +- if (ctrl->wLength == 0) +- ep0->dir_in = 1; +- +- if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { +- switch (ctrl->bRequest) { +- case USB_REQ_SET_ADDRESS: +- dcfg = readl(hsotg->regs + S3C_DCFG); +- dcfg &= ~S3C_DCFG_DevAddr_MASK; +- dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT; +- writel(dcfg, hsotg->regs + S3C_DCFG); +- +- dev_info(hsotg->dev, "new address %d\n", ctrl->wValue); +- +- ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); +- return; +- +- case USB_REQ_GET_STATUS: +- ret = s3c_hsotg_process_req_status(hsotg, ctrl); +- break; +- +- case USB_REQ_CLEAR_FEATURE: +- case USB_REQ_SET_FEATURE: +- ret = s3c_hsotg_process_req_feature(hsotg, ctrl); +- break; +- } +- } +- +- /* as a fallback, try delivering it to the driver to deal with */ +- +- if (ret == 0 && hsotg->driver) { +- ret = hsotg->driver->setup(&hsotg->gadget, ctrl); +- if (ret < 0) +- dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); +- } +- +- /* the request is either unhandlable, or is not formatted correctly +- * so respond with a STALL for the status stage to indicate failure. +- */ +- +- if (ret < 0) { +- u32 reg; +- u32 ctrl; +- +- dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); +- reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0; +- +- /* S3C_DxEPCTL_Stall will be cleared by EP once it has +- * taken effect, so no need to clear later. */ +- +- ctrl = readl(hsotg->regs + reg); +- ctrl |= S3C_DxEPCTL_Stall; +- ctrl |= S3C_DxEPCTL_CNAK; +- writel(ctrl, hsotg->regs + reg); +- +- dev_dbg(hsotg->dev, +- "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", +- ctrl, reg, readl(hsotg->regs + reg)); +- +- /* don't believe we need to anything more to get the EP +- * to reply with a STALL packet */ +- } +-} +- +-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); +- +-/** +- * s3c_hsotg_complete_setup - completion of a setup transfer +- * @ep: The endpoint the request was on. +- * @req: The request completed. +- * +- * Called on completion of any requests the driver itself submitted for +- * EP0 setup packets +- */ +-static void s3c_hsotg_complete_setup(struct usb_ep *ep, +- struct usb_request *req) +-{ +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hsotg = hs_ep->parent; +- +- if (req->status < 0) { +- dev_dbg(hsotg->dev, "%s: failed %d\n", __func__, req->status); +- return; +- } +- +- if (req->actual == 0) +- s3c_hsotg_enqueue_setup(hsotg); +- else +- s3c_hsotg_process_control(hsotg, req->buf); +-} +- +-/** +- * s3c_hsotg_enqueue_setup - start a request for EP0 packets +- * @hsotg: The device state. +- * +- * Enqueue a request on EP0 if necessary to received any SETUP packets +- * received from the host. +- */ +-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) +-{ +- struct usb_request *req = hsotg->ctrl_req; +- struct s3c_hsotg_req *hs_req = our_req(req); +- int ret; +- +- dev_dbg(hsotg->dev, "%s: queueing setup request\n", __func__); +- +- req->zero = 0; +- req->length = 8; +- req->buf = hsotg->ctrl_buff; +- req->complete = s3c_hsotg_complete_setup; +- +- if (!list_empty(&hs_req->queue)) { +- dev_dbg(hsotg->dev, "%s already queued???\n", __func__); +- return; +- } +- +- hsotg->eps[0].dir_in = 0; +- +- ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC); +- if (ret < 0) { +- dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret); +- /* Don't think there's much we can do other than watch the +- * driver fail. */ +- } +-} +- +-/** +- * s3c_hsotg_complete_request - complete a request given to us +- * @hsotg: The device state. +- * @hs_ep: The endpoint the request was on. +- * @hs_req: The request to complete. +- * @result: The result code (0 => Ok, otherwise errno) +- * +- * The given request has finished, so call the necessary completion +- * if it has one and then look to see if we can start a new request +- * on the endpoint. +- * +- * Note, expects the ep to already be locked as appropriate. +-*/ +-static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct s3c_hsotg_req *hs_req, +- int result) +-{ +- bool restart; +- +- if (!hs_req) { +- dev_dbg(hsotg->dev, "%s: nothing to complete?\n", __func__); +- return; +- } +- +- dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n", +- hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete); +- +- /* only replace the status if we've not already set an error +- * from a previous transaction */ +- +- if (hs_req->req.status == -EINPROGRESS) +- hs_req->req.status = result; +- +- hs_ep->req = NULL; +- list_del_init(&hs_req->queue); +- +- if (using_dma(hsotg)) +- s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req); +- +- /* call the complete request with the locks off, just in case the +- * request tries to queue more work for this endpoint. */ +- +- if (hs_req->req.complete) { +- spin_unlock(&hs_ep->lock); +- hs_req->req.complete(&hs_ep->ep, &hs_req->req); +- spin_lock(&hs_ep->lock); +- } +- +- /* Look to see if there is anything else to do. Note, the completion +- * of the previous request may have caused a new request to be started +- * so be careful when doing this. */ +- +- if (!hs_ep->req && result >= 0) { +- restart = !list_empty(&hs_ep->queue); +- if (restart) { +- hs_req = get_ep_head(hs_ep); +- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, false); +- } +- } +-} +- +-/** +- * s3c_hsotg_complete_request_lock - complete a request given to us (locked) +- * @hsotg: The device state. +- * @hs_ep: The endpoint the request was on. +- * @hs_req: The request to complete. +- * @result: The result code (0 => Ok, otherwise errno) +- * +- * See s3c_hsotg_complete_request(), but called with the endpoint's +- * lock held. +-*/ +-static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- struct s3c_hsotg_req *hs_req, +- int result) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&hs_ep->lock, flags); +- s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); +- spin_unlock_irqrestore(&hs_ep->lock, flags); +-} +- +-/** +- * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint +- * @hsotg: The device state. +- * @ep_idx: The endpoint index for the data +- * @size: The size of data in the fifo, in bytes +- * +- * The FIFO status shows there is data to read from the FIFO for a given +- * endpoint, so sort out whether we need to read the data into a request +- * that has been made for that endpoint. +- */ +-static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) +-{ +- struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx]; +- struct s3c_hsotg_req *hs_req = hs_ep->req; +- void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx); +- int to_read; +- int max_req; +- int read_ptr; +- +- if (!hs_req) { +- u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx)); +- int ptr; +- +- dev_warn(hsotg->dev, +- "%s: FIFO %d bytes on ep%d but no req (DxEPCTl=0x%08x)\n", +- __func__, size, ep_idx, epctl); +- +- /* dump the data from the FIFO, we've nothing we can do */ +- for (ptr = 0; ptr < size; ptr += 4) +- (void)readl(fifo); +- +- return; +- } +- +- spin_lock(&hs_ep->lock); +- +- to_read = size; +- read_ptr = hs_req->req.actual; +- max_req = hs_req->req.length - read_ptr; +- +- dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n", +- __func__, to_read, max_req, read_ptr, hs_req->req.length); +- +- if (to_read > max_req) { +- /* more data appeared than we where willing +- * to deal with in this request. +- */ +- +- /* currently we don't deal this */ +- WARN_ON_ONCE(1); +- } +- +- hs_ep->total_data += to_read; +- hs_req->req.actual += to_read; +- to_read = DIV_ROUND_UP(to_read, 4); +- +- /* note, we might over-write the buffer end by 3 bytes depending on +- * alignment of the data. */ +- readsl(fifo, hs_req->req.buf + read_ptr, to_read); +- +- spin_unlock(&hs_ep->lock); +-} +- +-/** +- * s3c_hsotg_send_zlp - send zero-length packet on control endpoint +- * @hsotg: The device instance +- * @req: The request currently on this endpoint +- * +- * Generate a zero-length IN packet request for terminating a SETUP +- * transaction. +- * +- * Note, since we don't write any data to the TxFIFO, then it is +- * currently believed that we do not need to wait for any space in +- * the TxFIFO. +- */ +-static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_req *req) +-{ +- u32 ctrl; +- +- if (!req) { +- dev_warn(hsotg->dev, "%s: no request?\n", __func__); +- return; +- } +- +- if (req->req.length == 0) { +- hsotg->eps[0].sent_zlp = 1; +- s3c_hsotg_enqueue_setup(hsotg); +- return; +- } +- +- hsotg->eps[0].dir_in = 1; +- hsotg->eps[0].sent_zlp = 1; +- +- dev_dbg(hsotg->dev, "sending zero-length packet\n"); +- +- /* issue a zero-sized packet to terminate this */ +- writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | +- S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0)); +- +- ctrl = readl(hsotg->regs + S3C_DIEPCTL0); +- ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ +- ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ +- ctrl |= S3C_DxEPCTL_USBActEp; +- writel(ctrl, hsotg->regs + S3C_DIEPCTL0); +-} +- +-/** +- * s3c_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO +- * @hsotg: The device instance +- * @epnum: The endpoint received from +- * @was_setup: Set if processing a SetupDone event. +- * +- * The RXFIFO has delivered an OutDone event, which means that the data +- * transfer for an OUT endpoint has been completed, either by a short +- * packet or by the finish of a transfer. +-*/ +-static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, +- int epnum, bool was_setup) +-{ +- u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); +- struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; +- struct s3c_hsotg_req *hs_req = hs_ep->req; +- struct usb_request *req = &hs_req->req; +- unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); +- int result = 0; +- +- if (!hs_req) { +- dev_dbg(hsotg->dev, "%s: no request active\n", __func__); +- return; +- } +- +- if (using_dma(hsotg)) { +- unsigned size_done; +- +- /* Calculate the size of the transfer by checking how much +- * is left in the endpoint size register and then working it +- * out from the amount we loaded for the transfer. +- * +- * We need to do this as DMA pointers are always 32bit aligned +- * so may overshoot/undershoot the transfer. +- */ +- +- size_done = hs_ep->size_loaded - size_left; +- size_done += hs_ep->last_load; +- +- req->actual = size_done; +- } +- +- /* if there is more request to do, schedule new transfer */ +- if (req->actual < req->length && size_left == 0) { +- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); +- return; +- } +- +- if (req->actual < req->length && req->short_not_ok) { +- dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", +- __func__, req->actual, req->length); +- +- /* todo - what should we return here? there's no one else +- * even bothering to check the status. */ +- } +- +- if (epnum == 0) { +- if (!was_setup && req->complete != s3c_hsotg_complete_setup) +- s3c_hsotg_send_zlp(hsotg, hs_req); +- } +- +- s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); +-} +- +-/** +- * s3c_hsotg_read_frameno - read current frame number +- * @hsotg: The device instance +- * +- * Return the current frame number +-*/ +-static u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) +-{ +- u32 dsts; +- +- dsts = readl(hsotg->regs + S3C_DSTS); +- dsts &= S3C_DSTS_SOFFN_MASK; +- dsts >>= S3C_DSTS_SOFFN_SHIFT; +- +- return dsts; +-} +- +-/** +- * s3c_hsotg_handle_rx - RX FIFO has data +- * @hsotg: The device instance +- * +- * The IRQ handler has detected that the RX FIFO has some data in it +- * that requires processing, so find out what is in there and do the +- * appropriate read. +- * +- * The RXFIFO is a true FIFO, the packets coming out are still in packet +- * chunks, so if you have x packets received on an endpoint you'll get x +- * FIFO events delivered, each with a packet's worth of data in it. +- * +- * When using DMA, we should not be processing events from the RXFIFO +- * as the actual data should be sent to the memory directly and we turn +- * on the completion interrupts to get notifications of transfer completion. +- */ +-static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) +-{ +- u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP); +- u32 epnum, status, size; +- +- WARN_ON(using_dma(hsotg)); +- +- epnum = grxstsr & S3C_GRXSTS_EPNum_MASK; +- status = grxstsr & S3C_GRXSTS_PktSts_MASK; +- +- size = grxstsr & S3C_GRXSTS_ByteCnt_MASK; +- size >>= S3C_GRXSTS_ByteCnt_SHIFT; +- +- if (1) +- dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n", +- __func__, grxstsr, size, epnum); +- +-#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT) +- +- switch (status >> S3C_GRXSTS_PktSts_SHIFT) { +- case __status(S3C_GRXSTS_PktSts_GlobalOutNAK): +- dev_dbg(hsotg->dev, "GlobalOutNAK\n"); +- break; +- +- case __status(S3C_GRXSTS_PktSts_OutDone): +- dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n", +- s3c_hsotg_read_frameno(hsotg)); +- +- if (!using_dma(hsotg)) +- s3c_hsotg_handle_outdone(hsotg, epnum, false); +- break; +- +- case __status(S3C_GRXSTS_PktSts_SetupDone): +- dev_dbg(hsotg->dev, +- "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n", +- s3c_hsotg_read_frameno(hsotg), +- readl(hsotg->regs + S3C_DOEPCTL(0))); +- +- s3c_hsotg_handle_outdone(hsotg, epnum, true); +- break; +- +- case __status(S3C_GRXSTS_PktSts_OutRX): +- s3c_hsotg_rx_data(hsotg, epnum, size); +- break; +- +- case __status(S3C_GRXSTS_PktSts_SetupRX): +- dev_dbg(hsotg->dev, +- "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n", +- s3c_hsotg_read_frameno(hsotg), +- readl(hsotg->regs + S3C_DOEPCTL(0))); +- +- s3c_hsotg_rx_data(hsotg, epnum, size); +- break; +- +- default: +- dev_warn(hsotg->dev, "%s: unknown status %08x\n", +- __func__, grxstsr); +- +- s3c_hsotg_dump(hsotg); +- break; +- } +-} +- +-/** +- * s3c_hsotg_ep0_mps - turn max packet size into register setting +- * @mps: The maximum packet size in bytes. +-*/ +-static u32 s3c_hsotg_ep0_mps(unsigned int mps) +-{ +- switch (mps) { +- case 64: +- return S3C_D0EPCTL_MPS_64; +- case 32: +- return S3C_D0EPCTL_MPS_32; +- case 16: +- return S3C_D0EPCTL_MPS_16; +- case 8: +- return S3C_D0EPCTL_MPS_8; +- } +- +- /* bad max packet size, warn and return invalid result */ +- WARN_ON(1); +- return (u32)-1; +-} +- +-/** +- * s3c_hsotg_set_ep_maxpacket - set endpoint's max-packet field +- * @hsotg: The driver state. +- * @ep: The index number of the endpoint +- * @mps: The maximum packet size in bytes +- * +- * Configure the maximum packet size for the given endpoint, updating +- * the hardware control registers to reflect this. +- */ +-static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, +- unsigned int ep, unsigned int mps) +-{ +- struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep]; +- void __iomem *regs = hsotg->regs; +- u32 mpsval; +- u32 reg; +- +- if (ep == 0) { +- /* EP0 is a special case */ +- mpsval = s3c_hsotg_ep0_mps(mps); +- if (mpsval > 3) +- goto bad_mps; +- } else { +- if (mps >= S3C_DxEPCTL_MPS_LIMIT+1) +- goto bad_mps; +- +- mpsval = mps; +- } +- +- hs_ep->ep.maxpacket = mps; +- +- /* update both the in and out endpoint controldir_ registers, even +- * if one of the directions may not be in use. */ +- +- reg = readl(regs + S3C_DIEPCTL(ep)); +- reg &= ~S3C_DxEPCTL_MPS_MASK; +- reg |= mpsval; +- writel(reg, regs + S3C_DIEPCTL(ep)); +- +- reg = readl(regs + S3C_DOEPCTL(ep)); +- reg &= ~S3C_DxEPCTL_MPS_MASK; +- reg |= mpsval; +- writel(reg, regs + S3C_DOEPCTL(ep)); +- +- return; +- +-bad_mps: +- dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps); +-} +- +-/** +- * s3c_hsotg_txfifo_flush - flush Tx FIFO +- * @hsotg: The driver state +- * @idx: The index for the endpoint (0..15) +- */ +-static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) +-{ +- int timeout; +- int val; +- +- writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh, +- hsotg->regs + S3C_GRSTCTL); +- +- /* wait until the fifo is flushed */ +- timeout = 100; +- +- while (1) { +- val = readl(hsotg->regs + S3C_GRSTCTL); +- +- if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0) +- break; +- +- if (--timeout == 0) { +- dev_err(hsotg->dev, +- "%s: timeout flushing fifo (GRSTCTL=%08x)\n", +- __func__, val); +- } +- +- udelay(1); +- } +-} +- +-/** +- * s3c_hsotg_trytx - check to see if anything needs transmitting +- * @hsotg: The driver state +- * @hs_ep: The driver endpoint to check. +- * +- * Check to see if there is a request that has data to send, and if so +- * make an attempt to write data into the FIFO. +- */ +-static int s3c_hsotg_trytx(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep) +-{ +- struct s3c_hsotg_req *hs_req = hs_ep->req; +- +- if (!hs_ep->dir_in || !hs_req) +- return 0; +- +- if (hs_req->req.actual < hs_req->req.length) { +- dev_dbg(hsotg->dev, "trying to write more for ep%d\n", +- hs_ep->index); +- return s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); +- } +- +- return 0; +-} +- +-/** +- * s3c_hsotg_complete_in - complete IN transfer +- * @hsotg: The device state. +- * @hs_ep: The endpoint that has just completed. +- * +- * An IN transfer has been completed, update the transfer's state and then +- * call the relevant completion routines. +- */ +-static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep) +-{ +- struct s3c_hsotg_req *hs_req = hs_ep->req; +- u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); +- int size_left, size_done; +- +- if (!hs_req) { +- dev_dbg(hsotg->dev, "XferCompl but no req\n"); +- return; +- } +- +- /* Calculate the size of the transfer by checking how much is left +- * in the endpoint size register and then working it out from +- * the amount we loaded for the transfer. +- * +- * We do this even for DMA, as the transfer may have incremented +- * past the end of the buffer (DMA transfers are always 32bit +- * aligned). +- */ +- +- size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); +- +- size_done = hs_ep->size_loaded - size_left; +- size_done += hs_ep->last_load; +- +- if (hs_req->req.actual != size_done) +- dev_dbg(hsotg->dev, "%s: adjusting size done %d => %d\n", +- __func__, hs_req->req.actual, size_done); +- +- hs_req->req.actual = size_done; +- +- /* if we did all of the transfer, and there is more data left +- * around, then try restarting the rest of the request */ +- +- if (!size_left && hs_req->req.actual < hs_req->req.length) { +- dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); +- s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); +- } else +- s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); +-} +- +-/** +- * s3c_hsotg_epint - handle an in/out endpoint interrupt +- * @hsotg: The driver state +- * @idx: The index for the endpoint (0..15) +- * @dir_in: Set if this is an IN endpoint +- * +- * Process and clear any interrupt pending for an individual endpoint +-*/ +-static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, +- int dir_in) +-{ +- struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx]; +- u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx); +- u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); +- u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); +- u32 ints; +- +- ints = readl(hsotg->regs + epint_reg); +- +- /* Clear endpoint interrupts */ +- writel(ints, hsotg->regs + epint_reg); +- +- dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", +- __func__, idx, dir_in ? "in" : "out", ints); +- +- if (ints & S3C_DxEPINT_XferCompl) { +- dev_dbg(hsotg->dev, +- "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", +- __func__, readl(hsotg->regs + epctl_reg), +- readl(hsotg->regs + epsiz_reg)); +- +- /* we get OutDone from the FIFO, so we only need to look +- * at completing IN requests here */ +- if (dir_in) { +- s3c_hsotg_complete_in(hsotg, hs_ep); +- +- if (idx == 0 && !hs_ep->req) +- s3c_hsotg_enqueue_setup(hsotg); +- } else if (using_dma(hsotg)) { +- /* We're using DMA, we need to fire an OutDone here +- * as we ignore the RXFIFO. */ +- +- s3c_hsotg_handle_outdone(hsotg, idx, false); +- } +- } +- +- if (ints & S3C_DxEPINT_EPDisbld) { +- dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); +- +- if (dir_in) { +- int epctl = readl(hsotg->regs + epctl_reg); +- +- s3c_hsotg_txfifo_flush(hsotg, idx); +- +- if ((epctl & S3C_DxEPCTL_Stall) && +- (epctl & S3C_DxEPCTL_EPType_Bulk)) { +- int dctl = readl(hsotg->regs + S3C_DCTL); +- +- dctl |= S3C_DCTL_CGNPInNAK; +- writel(dctl, hsotg->regs + S3C_DCTL); +- } +- } +- } +- +- if (ints & S3C_DxEPINT_AHBErr) +- dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); +- +- if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ +- dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); +- +- if (using_dma(hsotg) && idx == 0) { +- /* this is the notification we've received a +- * setup packet. In non-DMA mode we'd get this +- * from the RXFIFO, instead we need to process +- * the setup here. */ +- +- if (dir_in) +- WARN_ON_ONCE(1); +- else +- s3c_hsotg_handle_outdone(hsotg, 0, true); +- } +- } +- +- if (ints & S3C_DxEPINT_Back2BackSetup) +- dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); +- +- if (dir_in) { +- /* not sure if this is important, but we'll clear it anyway +- */ +- if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { +- dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", +- __func__, idx); +- } +- +- /* this probably means something bad is happening */ +- if (ints & S3C_DIEPMSK_INTknEPMisMsk) { +- dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", +- __func__, idx); +- } +- +- /* FIFO has space or is empty (see GAHBCFG) */ +- if (hsotg->dedicated_fifos && +- ints & S3C_DIEPMSK_TxFIFOEmpty) { +- dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", +- __func__, idx); +- s3c_hsotg_trytx(hsotg, hs_ep); +- } +- } +-} +- +-/** +- * s3c_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done) +- * @hsotg: The device state. +- * +- * Handle updating the device settings after the enumeration phase has +- * been completed. +-*/ +-static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) +-{ +- u32 dsts = readl(hsotg->regs + S3C_DSTS); +- int ep0_mps = 0, ep_mps; +- +- /* This should signal the finish of the enumeration phase +- * of the USB handshaking, so we should now know what rate +- * we connected at. */ +- +- dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts); +- +- /* note, since we're limited by the size of transfer on EP0, and +- * it seems IN transfers must be a even number of packets we do +- * not advertise a 64byte MPS on EP0. */ +- +- /* catch both EnumSpd_FS and EnumSpd_FS48 */ +- switch (dsts & S3C_DSTS_EnumSpd_MASK) { +- case S3C_DSTS_EnumSpd_FS: +- case S3C_DSTS_EnumSpd_FS48: +- hsotg->gadget.speed = USB_SPEED_FULL; +- dev_info(hsotg->dev, "new device is full-speed\n"); +- +- ep0_mps = EP0_MPS_LIMIT; +- ep_mps = 64; +- break; +- +- case S3C_DSTS_EnumSpd_HS: +- dev_info(hsotg->dev, "new device is high-speed\n"); +- hsotg->gadget.speed = USB_SPEED_HIGH; +- +- ep0_mps = EP0_MPS_LIMIT; +- ep_mps = 512; +- break; +- +- case S3C_DSTS_EnumSpd_LS: +- hsotg->gadget.speed = USB_SPEED_LOW; +- dev_info(hsotg->dev, "new device is low-speed\n"); +- +- /* note, we don't actually support LS in this driver at the +- * moment, and the documentation seems to imply that it isn't +- * supported by the PHYs on some of the devices. +- */ +- break; +- } +- +- /* we should now know the maximum packet size for an +- * endpoint, so set the endpoints to a default value. */ +- +- if (ep0_mps) { +- int i; +- s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps); +- for (i = 1; i < S3C_HSOTG_EPS; i++) +- s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps); +- } +- +- /* ensure after enumeration our EP0 is active */ +- +- s3c_hsotg_enqueue_setup(hsotg); +- +- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", +- readl(hsotg->regs + S3C_DIEPCTL0), +- readl(hsotg->regs + S3C_DOEPCTL0)); +-} +- +-/** +- * kill_all_requests - remove all requests from the endpoint's queue +- * @hsotg: The device state. +- * @ep: The endpoint the requests may be on. +- * @result: The result code to use. +- * @force: Force removal of any current requests +- * +- * Go through the requests on the given endpoint and mark them +- * completed with the given result code. +- */ +-static void kill_all_requests(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *ep, +- int result, bool force) +-{ +- struct s3c_hsotg_req *req, *treq; +- unsigned long flags; +- +- spin_lock_irqsave(&ep->lock, flags); +- +- list_for_each_entry_safe(req, treq, &ep->queue, queue) { +- /* currently, we can't do much about an already +- * running request on an in endpoint */ +- +- if (ep->req == req && ep->dir_in && !force) +- continue; +- +- s3c_hsotg_complete_request(hsotg, ep, req, +- result); +- } +- +- spin_unlock_irqrestore(&ep->lock, flags); +-} +- +-#define call_gadget(_hs, _entry) \ +- if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ +- (_hs)->driver && (_hs)->driver->_entry) \ +- (_hs)->driver->_entry(&(_hs)->gadget); +- +-/** +- * s3c_hsotg_disconnect_irq - disconnect irq service +- * @hsotg: The device state. +- * +- * A disconnect IRQ has been received, meaning that the host has +- * lost contact with the bus. Remove all current transactions +- * and signal the gadget driver that this has happened. +-*/ +-static void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg) +-{ +- unsigned ep; +- +- for (ep = 0; ep < S3C_HSOTG_EPS; ep++) +- kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true); +- +- call_gadget(hsotg, disconnect); +-} +- +-/** +- * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler +- * @hsotg: The device state: +- * @periodic: True if this is a periodic FIFO interrupt +- */ +-static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) +-{ +- struct s3c_hsotg_ep *ep; +- int epno, ret; +- +- /* look through for any more data to transmit */ +- +- for (epno = 0; epno < S3C_HSOTG_EPS; epno++) { +- ep = &hsotg->eps[epno]; +- +- if (!ep->dir_in) +- continue; +- +- if ((periodic && !ep->periodic) || +- (!periodic && ep->periodic)) +- continue; +- +- ret = s3c_hsotg_trytx(hsotg, ep); +- if (ret < 0) +- break; +- } +-} +- +-static struct s3c_hsotg *our_hsotg; +- +-/* IRQ flags which will trigger a retry around the IRQ loop */ +-#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \ +- S3C_GINTSTS_PTxFEmp | \ +- S3C_GINTSTS_RxFLvl) +- +-/** +- * s3c_hsotg_irq - handle device interrupt +- * @irq: The IRQ number triggered +- * @pw: The pw value when registered the handler. +- */ +-static irqreturn_t s3c_hsotg_irq(int irq, void *pw) +-{ +- struct s3c_hsotg *hsotg = pw; +- int retry_count = 8; +- u32 gintsts; +- u32 gintmsk; +- +-irq_retry: +- gintsts = readl(hsotg->regs + S3C_GINTSTS); +- gintmsk = readl(hsotg->regs + S3C_GINTMSK); +- +- dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n", +- __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count); +- +- gintsts &= gintmsk; +- +- if (gintsts & S3C_GINTSTS_OTGInt) { +- u32 otgint = readl(hsotg->regs + S3C_GOTGINT); +- +- dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); +- +- writel(otgint, hsotg->regs + S3C_GOTGINT); +- } +- +- if (gintsts & S3C_GINTSTS_DisconnInt) { +- dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__); +- writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS); +- +- s3c_hsotg_disconnect_irq(hsotg); +- } +- +- if (gintsts & S3C_GINTSTS_SessReqInt) { +- dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__); +- writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS); +- } +- +- if (gintsts & S3C_GINTSTS_EnumDone) { +- writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); +- +- s3c_hsotg_irq_enumdone(hsotg); +- } +- +- if (gintsts & S3C_GINTSTS_ConIDStsChng) { +- dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n", +- readl(hsotg->regs + S3C_DSTS), +- readl(hsotg->regs + S3C_GOTGCTL)); +- +- writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS); +- } +- +- if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) { +- u32 daint = readl(hsotg->regs + S3C_DAINT); +- u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT; +- u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT); +- int ep; +- +- dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); +- +- for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) { +- if (daint_out & 1) +- s3c_hsotg_epint(hsotg, ep, 0); +- } +- +- for (ep = 0; ep < 15 && daint_in; ep++, daint_in >>= 1) { +- if (daint_in & 1) +- s3c_hsotg_epint(hsotg, ep, 1); +- } +- } +- +- if (gintsts & S3C_GINTSTS_USBRst) { +- dev_info(hsotg->dev, "%s: USBRst\n", __func__); +- dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", +- readl(hsotg->regs + S3C_GNPTXSTS)); +- +- writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); +- +- kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); +- +- /* it seems after a reset we can end up with a situation +- * where the TXFIFO still has data in it... the docs +- * suggest resetting all the fifos, so use the init_fifo +- * code to relayout and flush the fifos. +- */ +- +- s3c_hsotg_init_fifo(hsotg); +- +- s3c_hsotg_enqueue_setup(hsotg); +- } +- +- /* check both FIFOs */ +- +- if (gintsts & S3C_GINTSTS_NPTxFEmp) { +- dev_dbg(hsotg->dev, "NPTxFEmp\n"); +- +- /* Disable the interrupt to stop it happening again +- * unless one of these endpoint routines decides that +- * it needs re-enabling */ +- +- s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); +- s3c_hsotg_irq_fifoempty(hsotg, false); +- } +- +- if (gintsts & S3C_GINTSTS_PTxFEmp) { +- dev_dbg(hsotg->dev, "PTxFEmp\n"); +- +- /* See note in S3C_GINTSTS_NPTxFEmp */ +- +- s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); +- s3c_hsotg_irq_fifoempty(hsotg, true); +- } +- +- if (gintsts & S3C_GINTSTS_RxFLvl) { +- /* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, +- * we need to retry s3c_hsotg_handle_rx if this is still +- * set. */ +- +- s3c_hsotg_handle_rx(hsotg); +- } +- +- if (gintsts & S3C_GINTSTS_ModeMis) { +- dev_warn(hsotg->dev, "warning, mode mismatch triggered\n"); +- writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS); +- } +- +- if (gintsts & S3C_GINTSTS_USBSusp) { +- dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n"); +- writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS); +- +- call_gadget(hsotg, suspend); +- } +- +- if (gintsts & S3C_GINTSTS_WkUpInt) { +- dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n"); +- writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS); +- +- call_gadget(hsotg, resume); +- } +- +- if (gintsts & S3C_GINTSTS_ErlySusp) { +- dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n"); +- writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS); +- } +- +- /* these next two seem to crop-up occasionally causing the core +- * to shutdown the USB transfer, so try clearing them and logging +- * the occurrence. */ +- +- if (gintsts & S3C_GINTSTS_GOUTNakEff) { +- dev_info(hsotg->dev, "GOUTNakEff triggered\n"); +- +- writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); +- +- s3c_hsotg_dump(hsotg); +- } +- +- if (gintsts & S3C_GINTSTS_GINNakEff) { +- dev_info(hsotg->dev, "GINNakEff triggered\n"); +- +- writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); +- +- s3c_hsotg_dump(hsotg); +- } +- +- /* if we've had fifo events, we should try and go around the +- * loop again to see if there's any point in returning yet. */ +- +- if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) +- goto irq_retry; +- +- return IRQ_HANDLED; +-} +- +-/** +- * s3c_hsotg_ep_enable - enable the given endpoint +- * @ep: The USB endpint to configure +- * @desc: The USB endpoint descriptor to configure with. +- * +- * This is called from the USB gadget code's usb_ep_enable(). +-*/ +-static int s3c_hsotg_ep_enable(struct usb_ep *ep, +- const struct usb_endpoint_descriptor *desc) +-{ +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hsotg = hs_ep->parent; +- unsigned long flags; +- int index = hs_ep->index; +- u32 epctrl_reg; +- u32 epctrl; +- u32 mps; +- int dir_in; +- int ret = 0; +- +- dev_dbg(hsotg->dev, +- "%s: ep %s: a 0x%02x, attr 0x%02x, mps 0x%04x, intr %d\n", +- __func__, ep->name, desc->bEndpointAddress, desc->bmAttributes, +- desc->wMaxPacketSize, desc->bInterval); +- +- /* not to be called for EP0 */ +- WARN_ON(index == 0); +- +- dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0; +- if (dir_in != hs_ep->dir_in) { +- dev_err(hsotg->dev, "%s: direction mismatch!\n", __func__); +- return -EINVAL; +- } +- +- mps = le16_to_cpu(desc->wMaxPacketSize); +- +- /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ +- +- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); +- epctrl = readl(hsotg->regs + epctrl_reg); +- +- dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", +- __func__, epctrl, epctrl_reg); +- +- spin_lock_irqsave(&hs_ep->lock, flags); +- +- epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK); +- epctrl |= S3C_DxEPCTL_MPS(mps); +- +- /* mark the endpoint as active, otherwise the core may ignore +- * transactions entirely for this endpoint */ +- epctrl |= S3C_DxEPCTL_USBActEp; +- +- /* set the NAK status on the endpoint, otherwise we might try and +- * do something with data that we've yet got a request to process +- * since the RXFIFO will take data for an endpoint even if the +- * size register hasn't been set. +- */ +- +- epctrl |= S3C_DxEPCTL_SNAK; +- +- /* update the endpoint state */ +- hs_ep->ep.maxpacket = mps; +- +- /* default, set to non-periodic */ +- hs_ep->periodic = 0; +- +- switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { +- case USB_ENDPOINT_XFER_ISOC: +- dev_err(hsotg->dev, "no current ISOC support\n"); +- ret = -EINVAL; +- goto out; +- +- case USB_ENDPOINT_XFER_BULK: +- epctrl |= S3C_DxEPCTL_EPType_Bulk; +- break; +- +- case USB_ENDPOINT_XFER_INT: +- if (dir_in) { +- /* Allocate our TxFNum by simply using the index +- * of the endpoint for the moment. We could do +- * something better if the host indicates how +- * many FIFOs we are expecting to use. */ +- +- hs_ep->periodic = 1; +- epctrl |= S3C_DxEPCTL_TxFNum(index); +- } +- +- epctrl |= S3C_DxEPCTL_EPType_Intterupt; +- break; +- +- case USB_ENDPOINT_XFER_CONTROL: +- epctrl |= S3C_DxEPCTL_EPType_Control; +- break; +- } +- +- /* if the hardware has dedicated fifos, we must give each IN EP +- * a unique tx-fifo even if it is non-periodic. +- */ +- if (dir_in && hsotg->dedicated_fifos) +- epctrl |= S3C_DxEPCTL_TxFNum(index); +- +- /* for non control endpoints, set PID to D0 */ +- if (index) +- epctrl |= S3C_DxEPCTL_SetD0PID; +- +- dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", +- __func__, epctrl); +- +- writel(epctrl, hsotg->regs + epctrl_reg); +- dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n", +- __func__, readl(hsotg->regs + epctrl_reg)); +- +- /* enable the endpoint interrupt */ +- s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); +- +-out: +- spin_unlock_irqrestore(&hs_ep->lock, flags); +- return ret; +-} +- +-static int s3c_hsotg_ep_disable(struct usb_ep *ep) +-{ +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hsotg = hs_ep->parent; +- int dir_in = hs_ep->dir_in; +- int index = hs_ep->index; +- unsigned long flags; +- u32 epctrl_reg; +- u32 ctrl; +- +- dev_info(hsotg->dev, "%s(ep %p)\n", __func__, ep); +- +- if (ep == &hsotg->eps[0].ep) { +- dev_err(hsotg->dev, "%s: called for ep0\n", __func__); +- return -EINVAL; +- } +- +- epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); +- +- /* terminate all requests with shutdown */ +- kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); +- +- spin_lock_irqsave(&hs_ep->lock, flags); +- +- ctrl = readl(hsotg->regs + epctrl_reg); +- ctrl &= ~S3C_DxEPCTL_EPEna; +- ctrl &= ~S3C_DxEPCTL_USBActEp; +- ctrl |= S3C_DxEPCTL_SNAK; +- +- dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); +- writel(ctrl, hsotg->regs + epctrl_reg); +- +- /* disable endpoint interrupts */ +- s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); +- +- spin_unlock_irqrestore(&hs_ep->lock, flags); +- return 0; +-} +- +-/** +- * on_list - check request is on the given endpoint +- * @ep: The endpoint to check. +- * @test: The request to test if it is on the endpoint. +-*/ +-static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) +-{ +- struct s3c_hsotg_req *req, *treq; +- +- list_for_each_entry_safe(req, treq, &ep->queue, queue) { +- if (req == test) +- return true; +- } +- +- return false; +-} +- +-static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) +-{ +- struct s3c_hsotg_req *hs_req = our_req(req); +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hs = hs_ep->parent; +- unsigned long flags; +- +- dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); +- +- spin_lock_irqsave(&hs_ep->lock, flags); +- +- if (!on_list(hs_ep, hs_req)) { +- spin_unlock_irqrestore(&hs_ep->lock, flags); +- return -EINVAL; +- } +- +- s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); +- spin_unlock_irqrestore(&hs_ep->lock, flags); +- +- return 0; +-} +- +-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) +-{ +- struct s3c_hsotg_ep *hs_ep = our_ep(ep); +- struct s3c_hsotg *hs = hs_ep->parent; +- int index = hs_ep->index; +- unsigned long irqflags; +- u32 epreg; +- u32 epctl; +- u32 xfertype; +- +- dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); +- +- spin_lock_irqsave(&hs_ep->lock, irqflags); +- +- /* write both IN and OUT control registers */ +- +- epreg = S3C_DIEPCTL(index); +- epctl = readl(hs->regs + epreg); +- +- if (value) { +- epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK; +- if (epctl & S3C_DxEPCTL_EPEna) +- epctl |= S3C_DxEPCTL_EPDis; +- } else { +- epctl &= ~S3C_DxEPCTL_Stall; +- xfertype = epctl & S3C_DxEPCTL_EPType_MASK; +- if (xfertype == S3C_DxEPCTL_EPType_Bulk || +- xfertype == S3C_DxEPCTL_EPType_Intterupt) +- epctl |= S3C_DxEPCTL_SetD0PID; +- } +- +- writel(epctl, hs->regs + epreg); +- +- epreg = S3C_DOEPCTL(index); +- epctl = readl(hs->regs + epreg); +- +- if (value) +- epctl |= S3C_DxEPCTL_Stall; +- else { +- epctl &= ~S3C_DxEPCTL_Stall; +- xfertype = epctl & S3C_DxEPCTL_EPType_MASK; +- if (xfertype == S3C_DxEPCTL_EPType_Bulk || +- xfertype == S3C_DxEPCTL_EPType_Intterupt) +- epctl |= S3C_DxEPCTL_SetD0PID; +- } +- +- writel(epctl, hs->regs + epreg); +- +- spin_unlock_irqrestore(&hs_ep->lock, irqflags); +- +- return 0; +-} +- +-static struct usb_ep_ops s3c_hsotg_ep_ops = { +- .enable = s3c_hsotg_ep_enable, +- .disable = s3c_hsotg_ep_disable, +- .alloc_request = s3c_hsotg_ep_alloc_request, +- .free_request = s3c_hsotg_ep_free_request, +- .queue = s3c_hsotg_ep_queue, +- .dequeue = s3c_hsotg_ep_dequeue, +- .set_halt = s3c_hsotg_ep_sethalt, +- /* note, don't believe we have any call for the fifo routines */ +-}; +- +-/** +- * s3c_hsotg_corereset - issue softreset to the core +- * @hsotg: The device state +- * +- * Issue a soft reset to the core, and await the core finishing it. +-*/ +-static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) +-{ +- int timeout; +- u32 grstctl; +- +- dev_dbg(hsotg->dev, "resetting core\n"); +- +- /* issue soft reset */ +- writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL); +- +- timeout = 1000; +- do { +- grstctl = readl(hsotg->regs + S3C_GRSTCTL); +- } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); +- +- if (grstctl & S3C_GRSTCTL_CSftRst) { +- dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); +- return -EINVAL; +- } +- +- timeout = 1000; +- +- while (1) { +- u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL); +- +- if (timeout-- < 0) { +- dev_info(hsotg->dev, +- "%s: reset failed, GRSTCTL=%08x\n", +- __func__, grstctl); +- return -ETIMEDOUT; +- } +- +- if (!(grstctl & S3C_GRSTCTL_AHBIdle)) +- continue; +- +- break; /* reset done */ +- } +- +- dev_dbg(hsotg->dev, "reset successful\n"); +- return 0; +-} +- +-int usb_gadget_probe_driver(struct usb_gadget_driver *driver, +- int (*bind)(struct usb_gadget *)) +-{ +- struct s3c_hsotg *hsotg = our_hsotg; +- int ret; +- +- if (!hsotg) { +- printk(KERN_ERR "%s: called with no device\n", __func__); +- return -ENODEV; +- } +- +- if (!driver) { +- dev_err(hsotg->dev, "%s: no driver\n", __func__); +- return -EINVAL; +- } +- +- if (driver->speed != USB_SPEED_HIGH && +- driver->speed != USB_SPEED_FULL) { +- dev_err(hsotg->dev, "%s: bad speed\n", __func__); +- } +- +- if (!bind || !driver->setup) { +- dev_err(hsotg->dev, "%s: missing entry points\n", __func__); +- return -EINVAL; +- } +- +- WARN_ON(hsotg->driver); +- +- driver->driver.bus = NULL; +- hsotg->driver = driver; +- hsotg->gadget.dev.driver = &driver->driver; +- hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; +- hsotg->gadget.speed = USB_SPEED_UNKNOWN; +- +- ret = device_add(&hsotg->gadget.dev); +- if (ret) { +- dev_err(hsotg->dev, "failed to register gadget device\n"); +- goto err; +- } +- +- ret = bind(&hsotg->gadget); +- if (ret) { +- dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name); +- +- hsotg->gadget.dev.driver = NULL; +- hsotg->driver = NULL; +- goto err; +- } +- +- /* we must now enable ep0 ready for host detection and then +- * set configuration. */ +- +- s3c_hsotg_corereset(hsotg); +- +- /* set the PLL on, remove the HNP/SRP and set the PHY */ +- writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | +- (0x5 << 10), hsotg->regs + S3C_GUSBCFG); +- +- /* looks like soft-reset changes state of FIFOs */ +- s3c_hsotg_init_fifo(hsotg); +- +- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); +- +- writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); +- +- /* Clear any pending OTG interrupts */ +- writel(0xffffffff, hsotg->regs + S3C_GOTGINT); +- +- /* Clear any pending interrupts */ +- writel(0xffffffff, hsotg->regs + S3C_GINTSTS); +- +- writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | +- S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | +- S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | +- S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt | +- S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff | +- S3C_GINTSTS_ErlySusp, +- hsotg->regs + S3C_GINTMSK); +- +- if (using_dma(hsotg)) +- writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn | +- S3C_GAHBCFG_HBstLen_Incr4, +- hsotg->regs + S3C_GAHBCFG); +- else +- writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG); +- +- /* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end +- * up being flooded with interrupts if the host is polling the +- * endpoint to try and read data. */ +- +- writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | +- S3C_DIEPMSK_INTknEPMisMsk | +- S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk | +- ((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0), +- hsotg->regs + S3C_DIEPMSK); +- +- /* don't need XferCompl, we get that from RXFIFO in slave mode. In +- * DMA mode we may need this. */ +- writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | +- S3C_DOEPMSK_EPDisbldMsk | +- (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | +- S3C_DIEPMSK_TimeOUTMsk) : 0), +- hsotg->regs + S3C_DOEPMSK); +- +- writel(0, hsotg->regs + S3C_DAINTMSK); +- +- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", +- readl(hsotg->regs + S3C_DIEPCTL0), +- readl(hsotg->regs + S3C_DOEPCTL0)); +- +- /* enable in and out endpoint interrupts */ +- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt); +- +- /* Enable the RXFIFO when in slave mode, as this is how we collect +- * the data. In DMA mode, we get events from the FIFO but also +- * things we cannot process, so do not use it. */ +- if (!using_dma(hsotg)) +- s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl); +- +- /* Enable interrupts for EP0 in and out */ +- s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); +- s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); +- +- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); +- udelay(10); /* see openiboot */ +- __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); +- +- dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); +- +- /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by +- writing to the EPCTL register.. */ +- +- /* set to read 1 8byte packet */ +- writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | +- S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); +- +- writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | +- S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna | +- S3C_DxEPCTL_USBActEp, +- hsotg->regs + S3C_DOEPCTL0); +- +- /* enable, but don't activate EP0in */ +- writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | +- S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0); +- +- s3c_hsotg_enqueue_setup(hsotg); +- +- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", +- readl(hsotg->regs + S3C_DIEPCTL0), +- readl(hsotg->regs + S3C_DOEPCTL0)); +- +- /* clear global NAKs */ +- writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, +- hsotg->regs + S3C_DCTL); +- +- /* must be at-least 3ms to allow bus to see disconnect */ +- msleep(3); +- +- /* remove the soft-disconnect and let's go */ +- __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); +- +- /* report to the user, and return */ +- +- dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); +- return 0; +- +-err: +- hsotg->driver = NULL; +- hsotg->gadget.dev.driver = NULL; +- return ret; +-} +-EXPORT_SYMBOL(usb_gadget_probe_driver); +- +-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +-{ +- struct s3c_hsotg *hsotg = our_hsotg; +- int ep; +- +- if (!hsotg) +- return -ENODEV; +- +- if (!driver || driver != hsotg->driver || !driver->unbind) +- return -EINVAL; +- +- /* all endpoints should be shutdown */ +- for (ep = 0; ep < S3C_HSOTG_EPS; ep++) +- s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); +- +- call_gadget(hsotg, disconnect); +- +- driver->unbind(&hsotg->gadget); +- hsotg->driver = NULL; +- hsotg->gadget.speed = USB_SPEED_UNKNOWN; +- +- device_del(&hsotg->gadget.dev); +- +- dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", +- driver->driver.name); +- +- return 0; +-} +-EXPORT_SYMBOL(usb_gadget_unregister_driver); +- +-static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) +-{ +- return s3c_hsotg_read_frameno(to_hsotg(gadget)); +-} +- +-static struct usb_gadget_ops s3c_hsotg_gadget_ops = { +- .get_frame = s3c_hsotg_gadget_getframe, +-}; +- +-/** +- * s3c_hsotg_initep - initialise a single endpoint +- * @hsotg: The device state. +- * @hs_ep: The endpoint to be initialised. +- * @epnum: The endpoint number +- * +- * Initialise the given endpoint (as part of the probe and device state +- * creation) to give to the gadget driver. Setup the endpoint name, any +- * direction information and other state that may be required. +- */ +-static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, +- struct s3c_hsotg_ep *hs_ep, +- int epnum) +-{ +- u32 ptxfifo; +- char *dir; +- +- if (epnum == 0) +- dir = ""; +- else if ((epnum % 2) == 0) { +- dir = "out"; +- } else { +- dir = "in"; +- hs_ep->dir_in = 1; +- } +- +- hs_ep->index = epnum; +- +- snprintf(hs_ep->name, sizeof(hs_ep->name), "ep%d%s", epnum, dir); +- +- INIT_LIST_HEAD(&hs_ep->queue); +- INIT_LIST_HEAD(&hs_ep->ep.ep_list); +- +- spin_lock_init(&hs_ep->lock); +- +- /* add to the list of endpoints known by the gadget driver */ +- if (epnum) +- list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); +- +- hs_ep->parent = hsotg; +- hs_ep->ep.name = hs_ep->name; +- hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; +- hs_ep->ep.ops = &s3c_hsotg_ep_ops; +- +- /* Read the FIFO size for the Periodic TX FIFO, even if we're +- * an OUT endpoint, we may as well do this if in future the +- * code is changed to make each endpoint's direction changeable. +- */ +- +- ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); +- hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4; +- +- /* if we're using dma, we need to set the next-endpoint pointer +- * to be something valid. +- */ +- +- if (using_dma(hsotg)) { +- u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15); +- writel(next, hsotg->regs + S3C_DIEPCTL(epnum)); +- writel(next, hsotg->regs + S3C_DOEPCTL(epnum)); +- } +-} +- +-/** +- * s3c_hsotg_otgreset - reset the OtG phy block +- * @hsotg: The host state. +- * +- * Power up the phy, set the basic configuration and start the PHY. +- */ +-static void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) +-{ +- struct clk *xusbxti; +- u32 pwr, osc; +- +- pwr = readl(S3C_PHYPWR); +- pwr &= ~0x19; +- writel(pwr, S3C_PHYPWR); +- mdelay(1); +- +- osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; +- +- xusbxti = clk_get(hsotg->dev, "xusbxti"); +- if (xusbxti && !IS_ERR(xusbxti)) { +- switch (clk_get_rate(xusbxti)) { +- case 12*MHZ: +- osc |= S3C_PHYCLK_CLKSEL_12M; +- break; +- case 24*MHZ: +- osc |= S3C_PHYCLK_CLKSEL_24M; +- break; +- default: +- case 48*MHZ: +- /* default reference clock */ +- break; +- } +- clk_put(xusbxti); +- } +- +- writel(osc | 0x10, S3C_PHYCLK); +- +- /* issue a full set of resets to the otg and core */ +- +- writel(S3C_RSTCON_PHY, S3C_RSTCON); +- udelay(20); /* at-least 10uS */ +- writel(0, S3C_RSTCON); +-} +- +- +-static void s3c_hsotg_init(struct s3c_hsotg *hsotg) +-{ +- u32 cfg4; +- +- /* unmask subset of endpoint interrupts */ +- +- writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | +- S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, +- hsotg->regs + S3C_DIEPMSK); +- +- writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | +- S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk, +- hsotg->regs + S3C_DOEPMSK); +- +- writel(0, hsotg->regs + S3C_DAINTMSK); +- +- /* Be in disconnected state until gadget is registered */ +- __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); +- +- if (0) { +- /* post global nak until we're ready */ +- writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak, +- hsotg->regs + S3C_DCTL); +- } +- +- /* setup fifos */ +- +- dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", +- readl(hsotg->regs + S3C_GRXFSIZ), +- readl(hsotg->regs + S3C_GNPTXFSIZ)); +- +- s3c_hsotg_init_fifo(hsotg); +- +- /* set the PLL on, remove the HNP/SRP and set the PHY */ +- writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10), +- hsotg->regs + S3C_GUSBCFG); +- +- writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, +- hsotg->regs + S3C_GAHBCFG); +- +- /* check hardware configuration */ +- +- cfg4 = readl(hsotg->regs + 0x50); +- hsotg->dedicated_fifos = (cfg4 >> 25) & 1; +- +- dev_info(hsotg->dev, "%s fifos\n", +- hsotg->dedicated_fifos ? "dedicated" : "shared"); +-} +- +-static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) +-{ +-#ifdef DEBUG +- struct device *dev = hsotg->dev; +- void __iomem *regs = hsotg->regs; +- u32 val; +- int idx; +- +- dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n", +- readl(regs + S3C_DCFG), readl(regs + S3C_DCTL), +- readl(regs + S3C_DIEPMSK)); +- +- dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n", +- readl(regs + S3C_GAHBCFG), readl(regs + 0x44)); +- +- dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", +- readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ)); +- +- /* show periodic fifo settings */ +- +- for (idx = 1; idx <= 15; idx++) { +- val = readl(regs + S3C_DPTXFSIZn(idx)); +- dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx, +- val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, +- val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); +- } +- +- for (idx = 0; idx < 15; idx++) { +- dev_info(dev, +- "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx, +- readl(regs + S3C_DIEPCTL(idx)), +- readl(regs + S3C_DIEPTSIZ(idx)), +- readl(regs + S3C_DIEPDMA(idx))); +- +- val = readl(regs + S3C_DOEPCTL(idx)); +- dev_info(dev, +- "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", +- idx, readl(regs + S3C_DOEPCTL(idx)), +- readl(regs + S3C_DOEPTSIZ(idx)), +- readl(regs + S3C_DOEPDMA(idx))); +- +- } +- +- dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", +- readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); +-#endif +-} +- +- +-/** +- * state_show - debugfs: show overall driver and device state. +- * @seq: The seq file to write to. +- * @v: Unused parameter. +- * +- * This debugfs entry shows the overall state of the hardware and +- * some general information about each of the endpoints available +- * to the system. +- */ +-static int state_show(struct seq_file *seq, void *v) +-{ +- struct s3c_hsotg *hsotg = seq->private; +- void __iomem *regs = hsotg->regs; +- int idx; +- +- seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", +- readl(regs + S3C_DCFG), +- readl(regs + S3C_DCTL), +- readl(regs + S3C_DSTS)); +- +- seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", +- readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK)); +- +- seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", +- readl(regs + S3C_GINTMSK), +- readl(regs + S3C_GINTSTS)); +- +- seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", +- readl(regs + S3C_DAINTMSK), +- readl(regs + S3C_DAINT)); +- +- seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", +- readl(regs + S3C_GNPTXSTS), +- readl(regs + S3C_GRXSTSR)); +- +- seq_printf(seq, "\nEndpoint status:\n"); +- +- for (idx = 0; idx < 15; idx++) { +- u32 in, out; +- +- in = readl(regs + S3C_DIEPCTL(idx)); +- out = readl(regs + S3C_DOEPCTL(idx)); +- +- seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", +- idx, in, out); +- +- in = readl(regs + S3C_DIEPTSIZ(idx)); +- out = readl(regs + S3C_DOEPTSIZ(idx)); +- +- seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", +- in, out); +- +- seq_printf(seq, "\n"); +- } +- +- return 0; +-} +- +-static int state_open(struct inode *inode, struct file *file) +-{ +- return single_open(file, state_show, inode->i_private); +-} +- +-static const struct file_operations state_fops = { +- .owner = THIS_MODULE, +- .open = state_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-/** +- * fifo_show - debugfs: show the fifo information +- * @seq: The seq_file to write data to. +- * @v: Unused parameter. +- * +- * Show the FIFO information for the overall fifo and all the +- * periodic transmission FIFOs. +-*/ +-static int fifo_show(struct seq_file *seq, void *v) +-{ +- struct s3c_hsotg *hsotg = seq->private; +- void __iomem *regs = hsotg->regs; +- u32 val; +- int idx; +- +- seq_printf(seq, "Non-periodic FIFOs:\n"); +- seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ)); +- +- val = readl(regs + S3C_GNPTXFSIZ); +- seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", +- val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT, +- val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK); +- +- seq_printf(seq, "\nPeriodic TXFIFOs:\n"); +- +- for (idx = 1; idx <= 15; idx++) { +- val = readl(regs + S3C_DPTXFSIZn(idx)); +- +- seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, +- val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, +- val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); +- } +- +- return 0; +-} +- +-static int fifo_open(struct inode *inode, struct file *file) +-{ +- return single_open(file, fifo_show, inode->i_private); +-} +- +-static const struct file_operations fifo_fops = { +- .owner = THIS_MODULE, +- .open = fifo_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +- +-static const char *decode_direction(int is_in) +-{ +- return is_in ? "in" : "out"; +-} +- +-/** +- * ep_show - debugfs: show the state of an endpoint. +- * @seq: The seq_file to write data to. +- * @v: Unused parameter. +- * +- * This debugfs entry shows the state of the given endpoint (one is +- * registered for each available). +-*/ +-static int ep_show(struct seq_file *seq, void *v) +-{ +- struct s3c_hsotg_ep *ep = seq->private; +- struct s3c_hsotg *hsotg = ep->parent; +- struct s3c_hsotg_req *req; +- void __iomem *regs = hsotg->regs; +- int index = ep->index; +- int show_limit = 15; +- unsigned long flags; +- +- seq_printf(seq, "Endpoint index %d, named %s, dir %s:\n", +- ep->index, ep->ep.name, decode_direction(ep->dir_in)); +- +- /* first show the register state */ +- +- seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", +- readl(regs + S3C_DIEPCTL(index)), +- readl(regs + S3C_DOEPCTL(index))); +- +- seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", +- readl(regs + S3C_DIEPDMA(index)), +- readl(regs + S3C_DOEPDMA(index))); +- +- seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", +- readl(regs + S3C_DIEPINT(index)), +- readl(regs + S3C_DOEPINT(index))); +- +- seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", +- readl(regs + S3C_DIEPTSIZ(index)), +- readl(regs + S3C_DOEPTSIZ(index))); +- +- seq_printf(seq, "\n"); +- seq_printf(seq, "mps %d\n", ep->ep.maxpacket); +- seq_printf(seq, "total_data=%ld\n", ep->total_data); +- +- seq_printf(seq, "request list (%p,%p):\n", +- ep->queue.next, ep->queue.prev); +- +- spin_lock_irqsave(&ep->lock, flags); +- +- list_for_each_entry(req, &ep->queue, queue) { +- if (--show_limit < 0) { +- seq_printf(seq, "not showing more requests...\n"); +- break; +- } +- +- seq_printf(seq, "%c req %p: %d bytes @%p, ", +- req == ep->req ? '*' : ' ', +- req, req->req.length, req->req.buf); +- seq_printf(seq, "%d done, res %d\n", +- req->req.actual, req->req.status); +- } +- +- spin_unlock_irqrestore(&ep->lock, flags); +- +- return 0; +-} +- +-static int ep_open(struct inode *inode, struct file *file) +-{ +- return single_open(file, ep_show, inode->i_private); +-} +- +-static const struct file_operations ep_fops = { +- .owner = THIS_MODULE, +- .open = ep_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-/** +- * s3c_hsotg_create_debug - create debugfs directory and files +- * @hsotg: The driver state +- * +- * Create the debugfs files to allow the user to get information +- * about the state of the system. The directory name is created +- * with the same name as the device itself, in case we end up +- * with multiple blocks in future systems. +-*/ +-static void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) +-{ +- struct dentry *root; +- unsigned epidx; +- +- root = debugfs_create_dir(dev_name(hsotg->dev), NULL); +- hsotg->debug_root = root; +- if (IS_ERR(root)) { +- dev_err(hsotg->dev, "cannot create debug root\n"); +- return; +- } +- +- /* create general state file */ +- +- hsotg->debug_file = debugfs_create_file("state", 0444, root, +- hsotg, &state_fops); +- +- if (IS_ERR(hsotg->debug_file)) +- dev_err(hsotg->dev, "%s: failed to create state\n", __func__); +- +- hsotg->debug_fifo = debugfs_create_file("fifo", 0444, root, +- hsotg, &fifo_fops); +- +- if (IS_ERR(hsotg->debug_fifo)) +- dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); +- +- /* create one file for each endpoint */ +- +- for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { +- struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; +- +- ep->debugfs = debugfs_create_file(ep->name, 0444, +- root, ep, &ep_fops); +- +- if (IS_ERR(ep->debugfs)) +- dev_err(hsotg->dev, "failed to create %s debug file\n", +- ep->name); +- } +-} +- +-/** +- * s3c_hsotg_delete_debug - cleanup debugfs entries +- * @hsotg: The driver state +- * +- * Cleanup (remove) the debugfs files for use on module exit. +-*/ +-static void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) +-{ +- unsigned epidx; +- +- for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { +- struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; +- debugfs_remove(ep->debugfs); +- } +- +- debugfs_remove(hsotg->debug_file); +- debugfs_remove(hsotg->debug_fifo); +- debugfs_remove(hsotg->debug_root); +-} +- +-/** +- * s3c_hsotg_gate - set the hardware gate for the block +- * @pdev: The device we bound to +- * @on: On or off. +- * +- * Set the hardware gate setting into the block. If we end up on +- * something other than an S3C64XX, then we might need to change this +- * to using a platform data callback, or some other mechanism. +- */ +-static void s3c_hsotg_gate(struct platform_device *pdev, bool on) +-{ +- unsigned long flags; +- u32 others; +- +- local_irq_save(flags); +- +- others = __raw_readl(S3C64XX_OTHERS); +- if (on) +- others |= S3C64XX_OTHERS_USBMASK; +- else +- others &= ~S3C64XX_OTHERS_USBMASK; +- __raw_writel(others, S3C64XX_OTHERS); +- +- local_irq_restore(flags); +-} +- +-static struct s3c_hsotg_plat s3c_hsotg_default_pdata; +- +-static int __devinit s3c_hsotg_probe(struct platform_device *pdev) +-{ +- struct s3c_hsotg_plat *plat = pdev->dev.platform_data; +- struct device *dev = &pdev->dev; +- struct s3c_hsotg *hsotg; +- struct resource *res; +- int epnum; +- int ret; +- +- if (!plat) +- plat = &s3c_hsotg_default_pdata; +- +- hsotg = kzalloc(sizeof(struct s3c_hsotg) + +- sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS, +- GFP_KERNEL); +- if (!hsotg) { +- dev_err(dev, "cannot get memory\n"); +- return -ENOMEM; +- } +- +- hsotg->dev = dev; +- hsotg->plat = plat; +- +- hsotg->clk = clk_get(&pdev->dev, "otg"); +- if (IS_ERR(hsotg->clk)) { +- dev_err(dev, "cannot get otg clock\n"); +- ret = PTR_ERR(hsotg->clk); +- goto err_mem; +- } +- +- platform_set_drvdata(pdev, hsotg); +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(dev, "cannot find register resource 0\n"); +- ret = -EINVAL; +- goto err_clk; +- } +- +- hsotg->regs_res = request_mem_region(res->start, resource_size(res), +- dev_name(dev)); +- if (!hsotg->regs_res) { +- dev_err(dev, "cannot reserve registers\n"); +- ret = -ENOENT; +- goto err_clk; +- } +- +- hsotg->regs = ioremap(res->start, resource_size(res)); +- if (!hsotg->regs) { +- dev_err(dev, "cannot map registers\n"); +- ret = -ENXIO; +- goto err_regs_res; +- } +- +- ret = platform_get_irq(pdev, 0); +- if (ret < 0) { +- dev_err(dev, "cannot find IRQ\n"); +- goto err_regs; +- } +- +- hsotg->irq = ret; +- +- ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg); +- if (ret < 0) { +- dev_err(dev, "cannot claim IRQ\n"); +- goto err_regs; +- } +- +- dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); +- +- device_initialize(&hsotg->gadget.dev); +- +- dev_set_name(&hsotg->gadget.dev, "gadget"); +- +- hsotg->gadget.is_dualspeed = 1; +- hsotg->gadget.ops = &s3c_hsotg_gadget_ops; +- hsotg->gadget.name = dev_name(dev); +- +- hsotg->gadget.dev.parent = dev; +- hsotg->gadget.dev.dma_mask = dev->dma_mask; +- +- /* setup endpoint information */ +- +- INIT_LIST_HEAD(&hsotg->gadget.ep_list); +- hsotg->gadget.ep0 = &hsotg->eps[0].ep; +- +- /* allocate EP0 request */ +- +- hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps[0].ep, +- GFP_KERNEL); +- if (!hsotg->ctrl_req) { +- dev_err(dev, "failed to allocate ctrl req\n"); +- goto err_regs; +- } +- +- /* reset the system */ +- +- clk_enable(hsotg->clk); +- +- s3c_hsotg_gate(pdev, true); +- +- s3c_hsotg_otgreset(hsotg); +- s3c_hsotg_corereset(hsotg); +- s3c_hsotg_init(hsotg); +- +- /* initialise the endpoints now the core has been initialised */ +- for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++) +- s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); +- +- s3c_hsotg_create_debug(hsotg); +- +- s3c_hsotg_dump(hsotg); +- +- our_hsotg = hsotg; +- return 0; +- +-err_regs: +- iounmap(hsotg->regs); +- +-err_regs_res: +- release_resource(hsotg->regs_res); +- kfree(hsotg->regs_res); +-err_clk: +- clk_put(hsotg->clk); +-err_mem: +- kfree(hsotg); +- return ret; +-} +- +-static int __devexit s3c_hsotg_remove(struct platform_device *pdev) +-{ +- struct s3c_hsotg *hsotg = platform_get_drvdata(pdev); +- +- s3c_hsotg_delete_debug(hsotg); +- +- usb_gadget_unregister_driver(hsotg->driver); +- +- free_irq(hsotg->irq, hsotg); +- iounmap(hsotg->regs); +- +- release_resource(hsotg->regs_res); +- kfree(hsotg->regs_res); +- +- s3c_hsotg_gate(pdev, false); +- +- clk_disable(hsotg->clk); +- clk_put(hsotg->clk); +- +- kfree(hsotg); +- return 0; +-} +- +-#if 1 +-#define s3c_hsotg_suspend NULL +-#define s3c_hsotg_resume NULL +-#endif +- +-static struct platform_driver s3c_hsotg_driver = { +- .driver = { +- .name = "s3c-hsotg", +- .owner = THIS_MODULE, +- }, +- .probe = s3c_hsotg_probe, +- .remove = __devexit_p(s3c_hsotg_remove), +- .suspend = s3c_hsotg_suspend, +- .resume = s3c_hsotg_resume, +-}; +- +-static int __init s3c_hsotg_modinit(void) +-{ +- return platform_driver_register(&s3c_hsotg_driver); +-} +- +-static void __exit s3c_hsotg_modexit(void) +-{ +- platform_driver_unregister(&s3c_hsotg_driver); +-} +- +-module_init(s3c_hsotg_modinit); +-module_exit(s3c_hsotg_modexit); +- +-MODULE_DESCRIPTION("Samsung S3C USB High-speed/OtG device"); +-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +-MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:s3c-hsotg"); +diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c +deleted file mode 100644 +index d5e3e1e5..00000000 +--- a/drivers/usb/gadget/s3c-hsudc.c ++++ /dev/null +@@ -1,1352 +0,0 @@ +-/* linux/drivers/usb/gadget/s3c-hsudc.c +- * +- * Copyright (c) 2010 Samsung Electronics Co., Ltd. +- * http://www.samsung.com/ +- * +- * S3C24XX USB 2.0 High-speed USB controller gadget driver +- * +- * The S3C24XX USB 2.0 high-speed USB controller supports upto 9 endpoints. +- * Each endpoint can be configured as either in or out endpoint. Endpoints +- * can be configured for Bulk or Interrupt transfer mode. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +-*/ +- +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/spinlock.h> +-#include <linux/interrupt.h> +-#include <linux/platform_device.h> +-#include <linux/dma-mapping.h> +-#include <linux/delay.h> +-#include <linux/io.h> +-#include <linux/slab.h> +-#include <linux/clk.h> +-#include <linux/usb/ch9.h> +-#include <linux/usb/gadget.h> +-#include <linux/prefetch.h> +- +-#include <mach/regs-s3c2443-clock.h> +-#include <plat/udc.h> +- +-#define S3C_HSUDC_REG(x) (x) +- +-/* Non-Indexed Registers */ +-#define S3C_IR S3C_HSUDC_REG(0x00) /* Index Register */ +-#define S3C_EIR S3C_HSUDC_REG(0x04) /* EP Intr Status */ +-#define S3C_EIR_EP0 (1<<0) +-#define S3C_EIER S3C_HSUDC_REG(0x08) /* EP Intr Enable */ +-#define S3C_FAR S3C_HSUDC_REG(0x0c) /* Gadget Address */ +-#define S3C_FNR S3C_HSUDC_REG(0x10) /* Frame Number */ +-#define S3C_EDR S3C_HSUDC_REG(0x14) /* EP Direction */ +-#define S3C_TR S3C_HSUDC_REG(0x18) /* Test Register */ +-#define S3C_SSR S3C_HSUDC_REG(0x1c) /* System Status */ +-#define S3C_SSR_DTZIEN_EN (0xff8f) +-#define S3C_SSR_ERR (0xff80) +-#define S3C_SSR_VBUSON (1 << 8) +-#define S3C_SSR_HSP (1 << 4) +-#define S3C_SSR_SDE (1 << 3) +-#define S3C_SSR_RESUME (1 << 2) +-#define S3C_SSR_SUSPEND (1 << 1) +-#define S3C_SSR_RESET (1 << 0) +-#define S3C_SCR S3C_HSUDC_REG(0x20) /* System Control */ +-#define S3C_SCR_DTZIEN_EN (1 << 14) +-#define S3C_SCR_RRD_EN (1 << 5) +-#define S3C_SCR_SUS_EN (1 << 1) +-#define S3C_SCR_RST_EN (1 << 0) +-#define S3C_EP0SR S3C_HSUDC_REG(0x24) /* EP0 Status */ +-#define S3C_EP0SR_EP0_LWO (1 << 6) +-#define S3C_EP0SR_STALL (1 << 4) +-#define S3C_EP0SR_TX_SUCCESS (1 << 1) +-#define S3C_EP0SR_RX_SUCCESS (1 << 0) +-#define S3C_EP0CR S3C_HSUDC_REG(0x28) /* EP0 Control */ +-#define S3C_BR(_x) S3C_HSUDC_REG(0x60 + (_x * 4)) +- +-/* Indexed Registers */ +-#define S3C_ESR S3C_HSUDC_REG(0x2c) /* EPn Status */ +-#define S3C_ESR_FLUSH (1 << 6) +-#define S3C_ESR_STALL (1 << 5) +-#define S3C_ESR_LWO (1 << 4) +-#define S3C_ESR_PSIF_ONE (1 << 2) +-#define S3C_ESR_PSIF_TWO (2 << 2) +-#define S3C_ESR_TX_SUCCESS (1 << 1) +-#define S3C_ESR_RX_SUCCESS (1 << 0) +-#define S3C_ECR S3C_HSUDC_REG(0x30) /* EPn Control */ +-#define S3C_ECR_DUEN (1 << 7) +-#define S3C_ECR_FLUSH (1 << 6) +-#define S3C_ECR_STALL (1 << 1) +-#define S3C_ECR_IEMS (1 << 0) +-#define S3C_BRCR S3C_HSUDC_REG(0x34) /* Read Count */ +-#define S3C_BWCR S3C_HSUDC_REG(0x38) /* Write Count */ +-#define S3C_MPR S3C_HSUDC_REG(0x3c) /* Max Pkt Size */ +- +-#define WAIT_FOR_SETUP (0) +-#define DATA_STATE_XMIT (1) +-#define DATA_STATE_RECV (2) +- +-/** +- * struct s3c_hsudc_ep - Endpoint representation used by driver. +- * @ep: USB gadget layer representation of device endpoint. +- * @name: Endpoint name (as required by ep autoconfiguration). +- * @dev: Reference to the device controller to which this EP belongs. +- * @desc: Endpoint descriptor obtained from the gadget driver. +- * @queue: Transfer request queue for the endpoint. +- * @stopped: Maintains state of endpoint, set if EP is halted. +- * @bEndpointAddress: EP address (including direction bit). +- * @fifo: Base address of EP FIFO. +- */ +-struct s3c_hsudc_ep { +- struct usb_ep ep; +- char name[20]; +- struct s3c_hsudc *dev; +- const struct usb_endpoint_descriptor *desc; +- struct list_head queue; +- u8 stopped; +- u8 wedge; +- u8 bEndpointAddress; +- void __iomem *fifo; +-}; +- +-/** +- * struct s3c_hsudc_req - Driver encapsulation of USB gadget transfer request. +- * @req: Reference to USB gadget transfer request. +- * @queue: Used for inserting this request to the endpoint request queue. +- */ +-struct s3c_hsudc_req { +- struct usb_request req; +- struct list_head queue; +-}; +- +-/** +- * struct s3c_hsudc - Driver's abstraction of the device controller. +- * @gadget: Instance of usb_gadget which is referenced by gadget driver. +- * @driver: Reference to currenty active gadget driver. +- * @dev: The device reference used by probe function. +- * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed). +- * @regs: Remapped base address of controller's register space. +- * @mem_rsrc: Device memory resource used for remapping device register space. +- * irq: IRQ number used by the controller. +- * uclk: Reference to the controller clock. +- * ep0state: Current state of EP0. +- * ep: List of endpoints supported by the controller. +- */ +-struct s3c_hsudc { +- struct usb_gadget gadget; +- struct usb_gadget_driver *driver; +- struct device *dev; +- struct s3c24xx_hsudc_platdata *pd; +- spinlock_t lock; +- void __iomem *regs; +- struct resource *mem_rsrc; +- int irq; +- struct clk *uclk; +- int ep0state; +- struct s3c_hsudc_ep ep[]; +-}; +- +-#define ep_maxpacket(_ep) ((_ep)->ep.maxpacket) +-#define ep_is_in(_ep) ((_ep)->bEndpointAddress & USB_DIR_IN) +-#define ep_index(_ep) ((_ep)->bEndpointAddress & \ +- USB_ENDPOINT_NUMBER_MASK) +- +-static struct s3c_hsudc *the_controller; +-static const char driver_name[] = "s3c-udc"; +-static const char ep0name[] = "ep0-control"; +- +-static inline struct s3c_hsudc_req *our_req(struct usb_request *req) +-{ +- return container_of(req, struct s3c_hsudc_req, req); +-} +- +-static inline struct s3c_hsudc_ep *our_ep(struct usb_ep *ep) +-{ +- return container_of(ep, struct s3c_hsudc_ep, ep); +-} +- +-static inline struct s3c_hsudc *to_hsudc(struct usb_gadget *gadget) +-{ +- return container_of(gadget, struct s3c_hsudc, gadget); +-} +- +-static inline void set_index(struct s3c_hsudc *hsudc, int ep_addr) +-{ +- ep_addr &= USB_ENDPOINT_NUMBER_MASK; +- writel(ep_addr, hsudc->regs + S3C_IR); +-} +- +-static inline void __orr32(void __iomem *ptr, u32 val) +-{ +- writel(readl(ptr) | val, ptr); +-} +- +-static void s3c_hsudc_init_phy(void) +-{ +- u32 cfg; +- +- cfg = readl(S3C2443_PWRCFG) | S3C2443_PWRCFG_USBPHY; +- writel(cfg, S3C2443_PWRCFG); +- +- cfg = readl(S3C2443_URSTCON); +- cfg |= (S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST); +- writel(cfg, S3C2443_URSTCON); +- mdelay(1); +- +- cfg = readl(S3C2443_URSTCON); +- cfg &= ~(S3C2443_URSTCON_FUNCRST | S3C2443_URSTCON_PHYRST); +- writel(cfg, S3C2443_URSTCON); +- +- cfg = readl(S3C2443_PHYCTRL); +- cfg &= ~(S3C2443_PHYCTRL_CLKSEL | S3C2443_PHYCTRL_DSPORT); +- cfg |= (S3C2443_PHYCTRL_EXTCLK | S3C2443_PHYCTRL_PLLSEL); +- writel(cfg, S3C2443_PHYCTRL); +- +- cfg = readl(S3C2443_PHYPWR); +- cfg &= ~(S3C2443_PHYPWR_FSUSPEND | S3C2443_PHYPWR_PLL_PWRDN | +- S3C2443_PHYPWR_XO_ON | S3C2443_PHYPWR_PLL_REFCLK | +- S3C2443_PHYPWR_ANALOG_PD); +- cfg |= S3C2443_PHYPWR_COMMON_ON; +- writel(cfg, S3C2443_PHYPWR); +- +- cfg = readl(S3C2443_UCLKCON); +- cfg |= (S3C2443_UCLKCON_DETECT_VBUS | S3C2443_UCLKCON_FUNC_CLKEN | +- S3C2443_UCLKCON_TCLKEN); +- writel(cfg, S3C2443_UCLKCON); +-} +- +-static void s3c_hsudc_uninit_phy(void) +-{ +- u32 cfg; +- +- cfg = readl(S3C2443_PWRCFG) & ~S3C2443_PWRCFG_USBPHY; +- writel(cfg, S3C2443_PWRCFG); +- +- writel(S3C2443_PHYPWR_FSUSPEND, S3C2443_PHYPWR); +- +- cfg = readl(S3C2443_UCLKCON) & ~S3C2443_UCLKCON_FUNC_CLKEN; +- writel(cfg, S3C2443_UCLKCON); +-} +- +-/** +- * s3c_hsudc_complete_request - Complete a transfer request. +- * @hsep: Endpoint to which the request belongs. +- * @hsreq: Transfer request to be completed. +- * @status: Transfer completion status for the transfer request. +- */ +-static void s3c_hsudc_complete_request(struct s3c_hsudc_ep *hsep, +- struct s3c_hsudc_req *hsreq, int status) +-{ +- unsigned int stopped = hsep->stopped; +- struct s3c_hsudc *hsudc = hsep->dev; +- +- list_del_init(&hsreq->queue); +- hsreq->req.status = status; +- +- if (!ep_index(hsep)) { +- hsudc->ep0state = WAIT_FOR_SETUP; +- hsep->bEndpointAddress &= ~USB_DIR_IN; +- } +- +- hsep->stopped = 1; +- spin_unlock(&hsudc->lock); +- if (hsreq->req.complete != NULL) +- hsreq->req.complete(&hsep->ep, &hsreq->req); +- spin_lock(&hsudc->lock); +- hsep->stopped = stopped; +-} +- +-/** +- * s3c_hsudc_nuke_ep - Terminate all requests queued for a endpoint. +- * @hsep: Endpoint for which queued requests have to be terminated. +- * @status: Transfer completion status for the transfer request. +- */ +-static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status) +-{ +- struct s3c_hsudc_req *hsreq; +- +- while (!list_empty(&hsep->queue)) { +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- s3c_hsudc_complete_request(hsep, hsreq, status); +- } +-} +- +-/** +- * s3c_hsudc_stop_activity - Stop activity on all endpoints. +- * @hsudc: Device controller for which EP activity is to be stopped. +- * @driver: Reference to the gadget driver which is currently active. +- * +- * All the endpoints are stopped and any pending transfer requests if any on +- * the endpoint are terminated. +- */ +-static void s3c_hsudc_stop_activity(struct s3c_hsudc *hsudc, +- struct usb_gadget_driver *driver) +-{ +- struct s3c_hsudc_ep *hsep; +- int epnum; +- +- hsudc->gadget.speed = USB_SPEED_UNKNOWN; +- +- for (epnum = 0; epnum < hsudc->pd->epnum; epnum++) { +- hsep = &hsudc->ep[epnum]; +- hsep->stopped = 1; +- s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); +- } +- +- spin_unlock(&hsudc->lock); +- driver->disconnect(&hsudc->gadget); +- spin_lock(&hsudc->lock); +-} +- +-/** +- * s3c_hsudc_read_setup_pkt - Read the received setup packet from EP0 fifo. +- * @hsudc: Device controller from which setup packet is to be read. +- * @buf: The buffer into which the setup packet is read. +- * +- * The setup packet received in the EP0 fifo is read and stored into a +- * given buffer address. +- */ +- +-static void s3c_hsudc_read_setup_pkt(struct s3c_hsudc *hsudc, u16 *buf) +-{ +- int count; +- +- count = readl(hsudc->regs + S3C_BRCR); +- while (count--) +- *buf++ = (u16)readl(hsudc->regs + S3C_BR(0)); +- +- writel(S3C_EP0SR_RX_SUCCESS, hsudc->regs + S3C_EP0SR); +-} +- +-/** +- * s3c_hsudc_write_fifo - Write next chunk of transfer data to EP fifo. +- * @hsep: Endpoint to which the data is to be written. +- * @hsreq: Transfer request from which the next chunk of data is written. +- * +- * Write the next chunk of data from a transfer request to the endpoint FIFO. +- * If the transfer request completes, 1 is returned, otherwise 0 is returned. +- */ +-static int s3c_hsudc_write_fifo(struct s3c_hsudc_ep *hsep, +- struct s3c_hsudc_req *hsreq) +-{ +- u16 *buf; +- u32 max = ep_maxpacket(hsep); +- u32 count, length; +- bool is_last; +- void __iomem *fifo = hsep->fifo; +- +- buf = hsreq->req.buf + hsreq->req.actual; +- prefetch(buf); +- +- length = hsreq->req.length - hsreq->req.actual; +- length = min(length, max); +- hsreq->req.actual += length; +- +- writel(length, hsep->dev->regs + S3C_BWCR); +- for (count = 0; count < length; count += 2) +- writel(*buf++, fifo); +- +- if (count != max) { +- is_last = true; +- } else { +- if (hsreq->req.length != hsreq->req.actual || hsreq->req.zero) +- is_last = false; +- else +- is_last = true; +- } +- +- if (is_last) { +- s3c_hsudc_complete_request(hsep, hsreq, 0); +- return 1; +- } +- +- return 0; +-} +- +-/** +- * s3c_hsudc_read_fifo - Read the next chunk of data from EP fifo. +- * @hsep: Endpoint from which the data is to be read. +- * @hsreq: Transfer request to which the next chunk of data read is written. +- * +- * Read the next chunk of data from the endpoint FIFO and a write it to the +- * transfer request buffer. If the transfer request completes, 1 is returned, +- * otherwise 0 is returned. +- */ +-static int s3c_hsudc_read_fifo(struct s3c_hsudc_ep *hsep, +- struct s3c_hsudc_req *hsreq) +-{ +- struct s3c_hsudc *hsudc = hsep->dev; +- u32 csr, offset; +- u16 *buf, word; +- u32 buflen, rcnt, rlen; +- void __iomem *fifo = hsep->fifo; +- u32 is_short = 0; +- +- offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR; +- csr = readl(hsudc->regs + offset); +- if (!(csr & S3C_ESR_RX_SUCCESS)) +- return -EINVAL; +- +- buf = hsreq->req.buf + hsreq->req.actual; +- prefetchw(buf); +- buflen = hsreq->req.length - hsreq->req.actual; +- +- rcnt = readl(hsudc->regs + S3C_BRCR); +- rlen = (csr & S3C_ESR_LWO) ? (rcnt * 2 - 1) : (rcnt * 2); +- +- hsreq->req.actual += min(rlen, buflen); +- is_short = (rlen < hsep->ep.maxpacket); +- +- while (rcnt-- != 0) { +- word = (u16)readl(fifo); +- if (buflen) { +- *buf++ = word; +- buflen--; +- } else { +- hsreq->req.status = -EOVERFLOW; +- } +- } +- +- writel(S3C_ESR_RX_SUCCESS, hsudc->regs + offset); +- +- if (is_short || hsreq->req.actual == hsreq->req.length) { +- s3c_hsudc_complete_request(hsep, hsreq, 0); +- return 1; +- } +- +- return 0; +-} +- +-/** +- * s3c_hsudc_epin_intr - Handle in-endpoint interrupt. +- * @hsudc - Device controller for which the interrupt is to be handled. +- * @ep_idx - Endpoint number on which an interrupt is pending. +- * +- * Handles interrupt for a in-endpoint. The interrupts that are handled are +- * stall and data transmit complete interrupt. +- */ +-static void s3c_hsudc_epin_intr(struct s3c_hsudc *hsudc, u32 ep_idx) +-{ +- struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx]; +- struct s3c_hsudc_req *hsreq; +- u32 csr; +- +- csr = readl((u32)hsudc->regs + S3C_ESR); +- if (csr & S3C_ESR_STALL) { +- writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR); +- return; +- } +- +- if (csr & S3C_ESR_TX_SUCCESS) { +- writel(S3C_ESR_TX_SUCCESS, hsudc->regs + S3C_ESR); +- if (list_empty(&hsep->queue)) +- return; +- +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- if ((s3c_hsudc_write_fifo(hsep, hsreq) == 0) && +- (csr & S3C_ESR_PSIF_TWO)) +- s3c_hsudc_write_fifo(hsep, hsreq); +- } +-} +- +-/** +- * s3c_hsudc_epout_intr - Handle out-endpoint interrupt. +- * @hsudc - Device controller for which the interrupt is to be handled. +- * @ep_idx - Endpoint number on which an interrupt is pending. +- * +- * Handles interrupt for a out-endpoint. The interrupts that are handled are +- * stall, flush and data ready interrupt. +- */ +-static void s3c_hsudc_epout_intr(struct s3c_hsudc *hsudc, u32 ep_idx) +-{ +- struct s3c_hsudc_ep *hsep = &hsudc->ep[ep_idx]; +- struct s3c_hsudc_req *hsreq; +- u32 csr; +- +- csr = readl((u32)hsudc->regs + S3C_ESR); +- if (csr & S3C_ESR_STALL) { +- writel(S3C_ESR_STALL, hsudc->regs + S3C_ESR); +- return; +- } +- +- if (csr & S3C_ESR_FLUSH) { +- __orr32(hsudc->regs + S3C_ECR, S3C_ECR_FLUSH); +- return; +- } +- +- if (csr & S3C_ESR_RX_SUCCESS) { +- if (list_empty(&hsep->queue)) +- return; +- +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- if (((s3c_hsudc_read_fifo(hsep, hsreq)) == 0) && +- (csr & S3C_ESR_PSIF_TWO)) +- s3c_hsudc_read_fifo(hsep, hsreq); +- } +-} +- +-/** s3c_hsudc_set_halt - Set or clear a endpoint halt. +- * @_ep: Endpoint on which halt has to be set or cleared. +- * @value: 1 for setting halt on endpoint, 0 to clear halt. +- * +- * Set or clear endpoint halt. If halt is set, the endpoint is stopped. +- * If halt is cleared, for in-endpoints, if there are any pending +- * transfer requests, transfers are started. +- */ +-static int s3c_hsudc_set_halt(struct usb_ep *_ep, int value) +-{ +- struct s3c_hsudc_ep *hsep = our_ep(_ep); +- struct s3c_hsudc *hsudc = hsep->dev; +- struct s3c_hsudc_req *hsreq; +- unsigned long irqflags; +- u32 ecr; +- u32 offset; +- +- if (value && ep_is_in(hsep) && !list_empty(&hsep->queue)) +- return -EAGAIN; +- +- spin_lock_irqsave(&hsudc->lock, irqflags); +- set_index(hsudc, ep_index(hsep)); +- offset = (ep_index(hsep)) ? S3C_ECR : S3C_EP0CR; +- ecr = readl(hsudc->regs + offset); +- +- if (value) { +- ecr |= S3C_ECR_STALL; +- if (ep_index(hsep)) +- ecr |= S3C_ECR_FLUSH; +- hsep->stopped = 1; +- } else { +- ecr &= ~S3C_ECR_STALL; +- hsep->stopped = hsep->wedge = 0; +- } +- writel(ecr, hsudc->regs + offset); +- +- if (ep_is_in(hsep) && !list_empty(&hsep->queue) && !value) { +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- if (hsreq) +- s3c_hsudc_write_fifo(hsep, hsreq); +- } +- +- spin_unlock_irqrestore(&hsudc->lock, irqflags); +- return 0; +-} +- +-/** s3c_hsudc_set_wedge - Sets the halt feature with the clear requests ignored +- * @_ep: Endpoint on which wedge has to be set. +- * +- * Sets the halt feature with the clear requests ignored. +- */ +-static int s3c_hsudc_set_wedge(struct usb_ep *_ep) +-{ +- struct s3c_hsudc_ep *hsep = our_ep(_ep); +- +- if (!hsep) +- return -EINVAL; +- +- hsep->wedge = 1; +- return usb_ep_set_halt(_ep); +-} +- +-/** s3c_hsudc_handle_reqfeat - Handle set feature or clear feature requests. +- * @_ep: Device controller on which the set/clear feature needs to be handled. +- * @ctrl: Control request as received on the endpoint 0. +- * +- * Handle set feature or clear feature control requests on the control endpoint. +- */ +-static int s3c_hsudc_handle_reqfeat(struct s3c_hsudc *hsudc, +- struct usb_ctrlrequest *ctrl) +-{ +- struct s3c_hsudc_ep *hsep; +- bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); +- u8 ep_num = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK; +- +- if (ctrl->bRequestType == USB_RECIP_ENDPOINT) { +- hsep = &hsudc->ep[ep_num]; +- switch (le16_to_cpu(ctrl->wValue)) { +- case USB_ENDPOINT_HALT: +- if (set || (!set && !hsep->wedge)) +- s3c_hsudc_set_halt(&hsep->ep, set); +- return 0; +- } +- } +- +- return -ENOENT; +-} +- +-/** +- * s3c_hsudc_process_req_status - Handle get status control request. +- * @hsudc: Device controller on which get status request has be handled. +- * @ctrl: Control request as received on the endpoint 0. +- * +- * Handle get status control request received on control endpoint. +- */ +-static void s3c_hsudc_process_req_status(struct s3c_hsudc *hsudc, +- struct usb_ctrlrequest *ctrl) +-{ +- struct s3c_hsudc_ep *hsep0 = &hsudc->ep[0]; +- struct s3c_hsudc_req hsreq; +- struct s3c_hsudc_ep *hsep; +- __le16 reply; +- u8 epnum; +- +- switch (ctrl->bRequestType & USB_RECIP_MASK) { +- case USB_RECIP_DEVICE: +- reply = cpu_to_le16(0); +- break; +- +- case USB_RECIP_INTERFACE: +- reply = cpu_to_le16(0); +- break; +- +- case USB_RECIP_ENDPOINT: +- epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; +- hsep = &hsudc->ep[epnum]; +- reply = cpu_to_le16(hsep->stopped ? 1 : 0); +- break; +- } +- +- INIT_LIST_HEAD(&hsreq.queue); +- hsreq.req.length = 2; +- hsreq.req.buf = &reply; +- hsreq.req.actual = 0; +- hsreq.req.complete = NULL; +- s3c_hsudc_write_fifo(hsep0, &hsreq); +-} +- +-/** +- * s3c_hsudc_process_setup - Process control request received on endpoint 0. +- * @hsudc: Device controller on which control request has been received. +- * +- * Read the control request received on endpoint 0, decode it and handle +- * the request. +- */ +-static void s3c_hsudc_process_setup(struct s3c_hsudc *hsudc) +-{ +- struct s3c_hsudc_ep *hsep = &hsudc->ep[0]; +- struct usb_ctrlrequest ctrl = {0}; +- int ret; +- +- s3c_hsudc_nuke_ep(hsep, -EPROTO); +- s3c_hsudc_read_setup_pkt(hsudc, (u16 *)&ctrl); +- +- if (ctrl.bRequestType & USB_DIR_IN) { +- hsep->bEndpointAddress |= USB_DIR_IN; +- hsudc->ep0state = DATA_STATE_XMIT; +- } else { +- hsep->bEndpointAddress &= ~USB_DIR_IN; +- hsudc->ep0state = DATA_STATE_RECV; +- } +- +- switch (ctrl.bRequest) { +- case USB_REQ_SET_ADDRESS: +- if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE)) +- break; +- hsudc->ep0state = WAIT_FOR_SETUP; +- return; +- +- case USB_REQ_GET_STATUS: +- if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) +- break; +- s3c_hsudc_process_req_status(hsudc, &ctrl); +- return; +- +- case USB_REQ_SET_FEATURE: +- case USB_REQ_CLEAR_FEATURE: +- if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) +- break; +- s3c_hsudc_handle_reqfeat(hsudc, &ctrl); +- hsudc->ep0state = WAIT_FOR_SETUP; +- return; +- } +- +- if (hsudc->driver) { +- spin_unlock(&hsudc->lock); +- ret = hsudc->driver->setup(&hsudc->gadget, &ctrl); +- spin_lock(&hsudc->lock); +- +- if (ctrl.bRequest == USB_REQ_SET_CONFIGURATION) { +- hsep->bEndpointAddress &= ~USB_DIR_IN; +- hsudc->ep0state = WAIT_FOR_SETUP; +- } +- +- if (ret < 0) { +- dev_err(hsudc->dev, "setup failed, returned %d\n", +- ret); +- s3c_hsudc_set_halt(&hsep->ep, 1); +- hsudc->ep0state = WAIT_FOR_SETUP; +- hsep->bEndpointAddress &= ~USB_DIR_IN; +- } +- } +-} +- +-/** s3c_hsudc_handle_ep0_intr - Handle endpoint 0 interrupt. +- * @hsudc: Device controller on which endpoint 0 interrupt has occured. +- * +- * Handle endpoint 0 interrupt when it occurs. EP0 interrupt could occur +- * when a stall handshake is sent to host or data is sent/received on +- * endpoint 0. +- */ +-static void s3c_hsudc_handle_ep0_intr(struct s3c_hsudc *hsudc) +-{ +- struct s3c_hsudc_ep *hsep = &hsudc->ep[0]; +- struct s3c_hsudc_req *hsreq; +- u32 csr = readl(hsudc->regs + S3C_EP0SR); +- u32 ecr; +- +- if (csr & S3C_EP0SR_STALL) { +- ecr = readl(hsudc->regs + S3C_EP0CR); +- ecr &= ~(S3C_ECR_STALL | S3C_ECR_FLUSH); +- writel(ecr, hsudc->regs + S3C_EP0CR); +- +- writel(S3C_EP0SR_STALL, hsudc->regs + S3C_EP0SR); +- hsep->stopped = 0; +- +- s3c_hsudc_nuke_ep(hsep, -ECONNABORTED); +- hsudc->ep0state = WAIT_FOR_SETUP; +- hsep->bEndpointAddress &= ~USB_DIR_IN; +- return; +- } +- +- if (csr & S3C_EP0SR_TX_SUCCESS) { +- writel(S3C_EP0SR_TX_SUCCESS, hsudc->regs + S3C_EP0SR); +- if (ep_is_in(hsep)) { +- if (list_empty(&hsep->queue)) +- return; +- +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- s3c_hsudc_write_fifo(hsep, hsreq); +- } +- } +- +- if (csr & S3C_EP0SR_RX_SUCCESS) { +- if (hsudc->ep0state == WAIT_FOR_SETUP) +- s3c_hsudc_process_setup(hsudc); +- else { +- if (!ep_is_in(hsep)) { +- if (list_empty(&hsep->queue)) +- return; +- hsreq = list_entry(hsep->queue.next, +- struct s3c_hsudc_req, queue); +- s3c_hsudc_read_fifo(hsep, hsreq); +- } +- } +- } +-} +- +-/** +- * s3c_hsudc_ep_enable - Enable a endpoint. +- * @_ep: The endpoint to be enabled. +- * @desc: Endpoint descriptor. +- * +- * Enables a endpoint when called from the gadget driver. Endpoint stall if +- * any is cleared, transfer type is configured and endpoint interrupt is +- * enabled. +- */ +-static int s3c_hsudc_ep_enable(struct usb_ep *_ep, +- const struct usb_endpoint_descriptor *desc) +-{ +- struct s3c_hsudc_ep *hsep; +- struct s3c_hsudc *hsudc; +- unsigned long flags; +- u32 ecr = 0; +- +- hsep = container_of(_ep, struct s3c_hsudc_ep, ep); +- if (!_ep || !desc || hsep->desc || _ep->name == ep0name +- || desc->bDescriptorType != USB_DT_ENDPOINT +- || hsep->bEndpointAddress != desc->bEndpointAddress +- || ep_maxpacket(hsep) < le16_to_cpu(desc->wMaxPacketSize)) +- return -EINVAL; +- +- if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK +- && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(hsep)) +- || !desc->wMaxPacketSize) +- return -ERANGE; +- +- hsudc = hsep->dev; +- if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN) +- return -ESHUTDOWN; +- +- spin_lock_irqsave(&hsudc->lock, flags); +- +- set_index(hsudc, hsep->bEndpointAddress); +- ecr |= ((usb_endpoint_xfer_int(desc)) ? S3C_ECR_IEMS : S3C_ECR_DUEN); +- writel(ecr, hsudc->regs + S3C_ECR); +- +- hsep->stopped = hsep->wedge = 0; +- hsep->desc = desc; +- hsep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); +- +- s3c_hsudc_set_halt(_ep, 0); +- __set_bit(ep_index(hsep), hsudc->regs + S3C_EIER); +- +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return 0; +-} +- +-/** +- * s3c_hsudc_ep_disable - Disable a endpoint. +- * @_ep: The endpoint to be disabled. +- * @desc: Endpoint descriptor. +- * +- * Disables a endpoint when called from the gadget driver. +- */ +-static int s3c_hsudc_ep_disable(struct usb_ep *_ep) +-{ +- struct s3c_hsudc_ep *hsep = our_ep(_ep); +- struct s3c_hsudc *hsudc = hsep->dev; +- unsigned long flags; +- +- if (!_ep || !hsep->desc) +- return -EINVAL; +- +- spin_lock_irqsave(&hsudc->lock, flags); +- +- set_index(hsudc, hsep->bEndpointAddress); +- __clear_bit(ep_index(hsep), hsudc->regs + S3C_EIER); +- +- s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); +- +- hsep->desc = 0; +- hsep->stopped = 1; +- +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return 0; +-} +- +-/** +- * s3c_hsudc_alloc_request - Allocate a new request. +- * @_ep: Endpoint for which request is allocated (not used). +- * @gfp_flags: Flags used for the allocation. +- * +- * Allocates a single transfer request structure when called from gadget driver. +- */ +-static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep, +- gfp_t gfp_flags) +-{ +- struct s3c_hsudc_req *hsreq; +- +- hsreq = kzalloc(sizeof *hsreq, gfp_flags); +- if (!hsreq) +- return 0; +- +- INIT_LIST_HEAD(&hsreq->queue); +- return &hsreq->req; +-} +- +-/** +- * s3c_hsudc_free_request - Deallocate a request. +- * @ep: Endpoint for which request is deallocated (not used). +- * @_req: Request to be deallocated. +- * +- * Allocates a single transfer request structure when called from gadget driver. +- */ +-static void s3c_hsudc_free_request(struct usb_ep *ep, struct usb_request *_req) +-{ +- struct s3c_hsudc_req *hsreq; +- +- hsreq = container_of(_req, struct s3c_hsudc_req, req); +- WARN_ON(!list_empty(&hsreq->queue)); +- kfree(hsreq); +-} +- +-/** +- * s3c_hsudc_queue - Queue a transfer request for the endpoint. +- * @_ep: Endpoint for which the request is queued. +- * @_req: Request to be queued. +- * @gfp_flags: Not used. +- * +- * Start or enqueue a request for a endpoint when called from gadget driver. +- */ +-static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req, +- gfp_t gfp_flags) +-{ +- struct s3c_hsudc_req *hsreq; +- struct s3c_hsudc_ep *hsep; +- struct s3c_hsudc *hsudc; +- unsigned long flags; +- u32 offset; +- u32 csr; +- +- hsreq = container_of(_req, struct s3c_hsudc_req, req); +- if ((!_req || !_req->complete || !_req->buf || +- !list_empty(&hsreq->queue))) +- return -EINVAL; +- +- hsep = container_of(_ep, struct s3c_hsudc_ep, ep); +- hsudc = hsep->dev; +- if (!hsudc->driver || hsudc->gadget.speed == USB_SPEED_UNKNOWN) +- return -ESHUTDOWN; +- +- spin_lock_irqsave(&hsudc->lock, flags); +- set_index(hsudc, hsep->bEndpointAddress); +- +- _req->status = -EINPROGRESS; +- _req->actual = 0; +- +- if (!ep_index(hsep) && _req->length == 0) { +- hsudc->ep0state = WAIT_FOR_SETUP; +- s3c_hsudc_complete_request(hsep, hsreq, 0); +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return 0; +- } +- +- if (list_empty(&hsep->queue) && !hsep->stopped) { +- offset = (ep_index(hsep)) ? S3C_ESR : S3C_EP0SR; +- if (ep_is_in(hsep)) { +- csr = readl((u32)hsudc->regs + offset); +- if (!(csr & S3C_ESR_TX_SUCCESS) && +- (s3c_hsudc_write_fifo(hsep, hsreq) == 1)) +- hsreq = 0; +- } else { +- csr = readl((u32)hsudc->regs + offset); +- if ((csr & S3C_ESR_RX_SUCCESS) +- && (s3c_hsudc_read_fifo(hsep, hsreq) == 1)) +- hsreq = 0; +- } +- } +- +- if (hsreq != 0) +- list_add_tail(&hsreq->queue, &hsep->queue); +- +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return 0; +-} +- +-/** +- * s3c_hsudc_dequeue - Dequeue a transfer request from an endpoint. +- * @_ep: Endpoint from which the request is dequeued. +- * @_req: Request to be dequeued. +- * +- * Dequeue a request from a endpoint when called from gadget driver. +- */ +-static int s3c_hsudc_dequeue(struct usb_ep *_ep, struct usb_request *_req) +-{ +- struct s3c_hsudc_ep *hsep = our_ep(_ep); +- struct s3c_hsudc *hsudc = hsep->dev; +- struct s3c_hsudc_req *hsreq; +- unsigned long flags; +- +- hsep = container_of(_ep, struct s3c_hsudc_ep, ep); +- if (!_ep || hsep->ep.name == ep0name) +- return -EINVAL; +- +- spin_lock_irqsave(&hsudc->lock, flags); +- +- list_for_each_entry(hsreq, &hsep->queue, queue) { +- if (&hsreq->req == _req) +- break; +- } +- if (&hsreq->req != _req) { +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return -EINVAL; +- } +- +- set_index(hsudc, hsep->bEndpointAddress); +- s3c_hsudc_complete_request(hsep, hsreq, -ECONNRESET); +- +- spin_unlock_irqrestore(&hsudc->lock, flags); +- return 0; +-} +- +-static struct usb_ep_ops s3c_hsudc_ep_ops = { +- .enable = s3c_hsudc_ep_enable, +- .disable = s3c_hsudc_ep_disable, +- .alloc_request = s3c_hsudc_alloc_request, +- .free_request = s3c_hsudc_free_request, +- .queue = s3c_hsudc_queue, +- .dequeue = s3c_hsudc_dequeue, +- .set_halt = s3c_hsudc_set_halt, +- .set_wedge = s3c_hsudc_set_wedge, +-}; +- +-/** +- * s3c_hsudc_initep - Initialize a endpoint to default state. +- * @hsudc - Reference to the device controller. +- * @hsep - Endpoint to be initialized. +- * @epnum - Address to be assigned to the endpoint. +- * +- * Initialize a endpoint with default configuration. +- */ +-static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, +- struct s3c_hsudc_ep *hsep, int epnum) +-{ +- char *dir; +- +- if ((epnum % 2) == 0) { +- dir = "out"; +- } else { +- dir = "in"; +- hsep->bEndpointAddress = USB_DIR_IN; +- } +- +- hsep->bEndpointAddress |= epnum; +- if (epnum) +- snprintf(hsep->name, sizeof(hsep->name), "ep%d%s", epnum, dir); +- else +- snprintf(hsep->name, sizeof(hsep->name), "%s", ep0name); +- +- INIT_LIST_HEAD(&hsep->queue); +- INIT_LIST_HEAD(&hsep->ep.ep_list); +- if (epnum) +- list_add_tail(&hsep->ep.ep_list, &hsudc->gadget.ep_list); +- +- hsep->dev = hsudc; +- hsep->ep.name = hsep->name; +- hsep->ep.maxpacket = epnum ? 512 : 64; +- hsep->ep.ops = &s3c_hsudc_ep_ops; +- hsep->fifo = hsudc->regs + S3C_BR(epnum); +- hsep->desc = 0; +- hsep->stopped = 0; +- hsep->wedge = 0; +- +- set_index(hsudc, epnum); +- writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR); +-} +- +-/** +- * s3c_hsudc_setup_ep - Configure all endpoints to default state. +- * @hsudc: Reference to device controller. +- * +- * Configures all endpoints to default state. +- */ +-static void s3c_hsudc_setup_ep(struct s3c_hsudc *hsudc) +-{ +- int epnum; +- +- hsudc->ep0state = WAIT_FOR_SETUP; +- INIT_LIST_HEAD(&hsudc->gadget.ep_list); +- for (epnum = 0; epnum < hsudc->pd->epnum; epnum++) +- s3c_hsudc_initep(hsudc, &hsudc->ep[epnum], epnum); +-} +- +-/** +- * s3c_hsudc_reconfig - Reconfigure the device controller to default state. +- * @hsudc: Reference to device controller. +- * +- * Reconfigures the device controller registers to a default state. +- */ +-static void s3c_hsudc_reconfig(struct s3c_hsudc *hsudc) +-{ +- writel(0xAA, hsudc->regs + S3C_EDR); +- writel(1, hsudc->regs + S3C_EIER); +- writel(0, hsudc->regs + S3C_TR); +- writel(S3C_SCR_DTZIEN_EN | S3C_SCR_RRD_EN | S3C_SCR_SUS_EN | +- S3C_SCR_RST_EN, hsudc->regs + S3C_SCR); +- writel(0, hsudc->regs + S3C_EP0CR); +- +- s3c_hsudc_setup_ep(hsudc); +-} +- +-/** +- * s3c_hsudc_irq - Interrupt handler for device controller. +- * @irq: Not used. +- * @_dev: Reference to the device controller. +- * +- * Interrupt handler for the device controller. This handler handles controller +- * interrupts and endpoint interrupts. +- */ +-static irqreturn_t s3c_hsudc_irq(int irq, void *_dev) +-{ +- struct s3c_hsudc *hsudc = _dev; +- struct s3c_hsudc_ep *hsep; +- u32 ep_intr; +- u32 sys_status; +- u32 ep_idx; +- +- spin_lock(&hsudc->lock); +- +- sys_status = readl(hsudc->regs + S3C_SSR); +- ep_intr = readl(hsudc->regs + S3C_EIR) & 0x3FF; +- +- if (!ep_intr && !(sys_status & S3C_SSR_DTZIEN_EN)) { +- spin_unlock(&hsudc->lock); +- return IRQ_HANDLED; +- } +- +- if (sys_status) { +- if (sys_status & S3C_SSR_VBUSON) +- writel(S3C_SSR_VBUSON, hsudc->regs + S3C_SSR); +- +- if (sys_status & S3C_SSR_ERR) +- writel(S3C_SSR_ERR, hsudc->regs + S3C_SSR); +- +- if (sys_status & S3C_SSR_SDE) { +- writel(S3C_SSR_SDE, hsudc->regs + S3C_SSR); +- hsudc->gadget.speed = (sys_status & S3C_SSR_HSP) ? +- USB_SPEED_HIGH : USB_SPEED_FULL; +- } +- +- if (sys_status & S3C_SSR_SUSPEND) { +- writel(S3C_SSR_SUSPEND, hsudc->regs + S3C_SSR); +- if (hsudc->gadget.speed != USB_SPEED_UNKNOWN +- && hsudc->driver && hsudc->driver->suspend) +- hsudc->driver->suspend(&hsudc->gadget); +- } +- +- if (sys_status & S3C_SSR_RESUME) { +- writel(S3C_SSR_RESUME, hsudc->regs + S3C_SSR); +- if (hsudc->gadget.speed != USB_SPEED_UNKNOWN +- && hsudc->driver && hsudc->driver->resume) +- hsudc->driver->resume(&hsudc->gadget); +- } +- +- if (sys_status & S3C_SSR_RESET) { +- writel(S3C_SSR_RESET, hsudc->regs + S3C_SSR); +- for (ep_idx = 0; ep_idx < hsudc->pd->epnum; ep_idx++) { +- hsep = &hsudc->ep[ep_idx]; +- hsep->stopped = 1; +- s3c_hsudc_nuke_ep(hsep, -ECONNRESET); +- } +- s3c_hsudc_reconfig(hsudc); +- hsudc->ep0state = WAIT_FOR_SETUP; +- } +- } +- +- if (ep_intr & S3C_EIR_EP0) { +- writel(S3C_EIR_EP0, hsudc->regs + S3C_EIR); +- set_index(hsudc, 0); +- s3c_hsudc_handle_ep0_intr(hsudc); +- } +- +- ep_intr >>= 1; +- ep_idx = 1; +- while (ep_intr) { +- if (ep_intr & 1) { +- hsep = &hsudc->ep[ep_idx]; +- set_index(hsudc, ep_idx); +- writel(1 << ep_idx, hsudc->regs + S3C_EIR); +- if (ep_is_in(hsep)) +- s3c_hsudc_epin_intr(hsudc, ep_idx); +- else +- s3c_hsudc_epout_intr(hsudc, ep_idx); +- } +- ep_intr >>= 1; +- ep_idx++; +- } +- +- spin_unlock(&hsudc->lock); +- return IRQ_HANDLED; +-} +- +-int usb_gadget_probe_driver(struct usb_gadget_driver *driver, +- int (*bind)(struct usb_gadget *)) +-{ +- struct s3c_hsudc *hsudc = the_controller; +- int ret; +- +- if (!driver +- || (driver->speed != USB_SPEED_FULL && +- driver->speed != USB_SPEED_HIGH) +- || !bind +- || !driver->unbind || !driver->disconnect || !driver->setup) +- return -EINVAL; +- +- if (!hsudc) +- return -ENODEV; +- +- if (hsudc->driver) +- return -EBUSY; +- +- hsudc->driver = driver; +- hsudc->gadget.dev.driver = &driver->driver; +- hsudc->gadget.speed = USB_SPEED_UNKNOWN; +- ret = device_add(&hsudc->gadget.dev); +- if (ret) { +- dev_err(hsudc->dev, "failed to probe gadget device"); +- return ret; +- } +- +- ret = bind(&hsudc->gadget); +- if (ret) { +- dev_err(hsudc->dev, "%s: bind failed\n", hsudc->gadget.name); +- device_del(&hsudc->gadget.dev); +- +- hsudc->driver = NULL; +- hsudc->gadget.dev.driver = NULL; +- return ret; +- } +- +- enable_irq(hsudc->irq); +- dev_info(hsudc->dev, "bound driver %s\n", driver->driver.name); +- +- s3c_hsudc_reconfig(hsudc); +- s3c_hsudc_init_phy(); +- if (hsudc->pd->gpio_init) +- hsudc->pd->gpio_init(); +- +- return 0; +-} +-EXPORT_SYMBOL(usb_gadget_probe_driver); +- +-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +-{ +- struct s3c_hsudc *hsudc = the_controller; +- unsigned long flags; +- +- if (!hsudc) +- return -ENODEV; +- +- if (!driver || driver != hsudc->driver || !driver->unbind) +- return -EINVAL; +- +- spin_lock_irqsave(&hsudc->lock, flags); +- hsudc->driver = 0; +- s3c_hsudc_uninit_phy(); +- if (hsudc->pd->gpio_uninit) +- hsudc->pd->gpio_uninit(); +- s3c_hsudc_stop_activity(hsudc, driver); +- spin_unlock_irqrestore(&hsudc->lock, flags); +- +- driver->unbind(&hsudc->gadget); +- device_del(&hsudc->gadget.dev); +- disable_irq(hsudc->irq); +- +- dev_info(hsudc->dev, "unregistered gadget driver '%s'\n", +- driver->driver.name); +- return 0; +-} +-EXPORT_SYMBOL(usb_gadget_unregister_driver); +- +-static inline u32 s3c_hsudc_read_frameno(struct s3c_hsudc *hsudc) +-{ +- return readl(hsudc->regs + S3C_FNR) & 0x3FF; +-} +- +-static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget) +-{ +- return s3c_hsudc_read_frameno(to_hsudc(gadget)); +-} +- +-static struct usb_gadget_ops s3c_hsudc_gadget_ops = { +- .get_frame = s3c_hsudc_gadget_getframe, +-}; +- +-static int s3c_hsudc_probe(struct platform_device *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct resource *res; +- struct s3c_hsudc *hsudc; +- struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; +- int ret; +- +- hsudc = kzalloc(sizeof(struct s3c_hsudc) + +- sizeof(struct s3c_hsudc_ep) * pd->epnum, +- GFP_KERNEL); +- if (!hsudc) { +- dev_err(dev, "cannot allocate memory\n"); +- return -ENOMEM; +- } +- +- the_controller = hsudc; +- platform_set_drvdata(pdev, dev); +- hsudc->dev = dev; +- hsudc->pd = pdev->dev.platform_data; +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(dev, "unable to obtain driver resource data\n"); +- ret = -ENODEV; +- goto err_res; +- } +- +- hsudc->mem_rsrc = request_mem_region(res->start, resource_size(res), +- dev_name(&pdev->dev)); +- if (!hsudc->mem_rsrc) { +- dev_err(dev, "failed to reserve register area\n"); +- ret = -ENODEV; +- goto err_res; +- } +- +- hsudc->regs = ioremap(res->start, resource_size(res)); +- if (!hsudc->regs) { +- dev_err(dev, "error mapping device register area\n"); +- ret = -EBUSY; +- goto err_remap; +- } +- +- ret = platform_get_irq(pdev, 0); +- if (ret < 0) { +- dev_err(dev, "unable to obtain IRQ number\n"); +- goto err_irq; +- } +- hsudc->irq = ret; +- +- ret = request_irq(hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc); +- if (ret < 0) { +- dev_err(dev, "irq request failed\n"); +- goto err_irq; +- } +- +- spin_lock_init(&hsudc->lock); +- +- device_initialize(&hsudc->gadget.dev); +- dev_set_name(&hsudc->gadget.dev, "gadget"); +- +- hsudc->gadget.is_dualspeed = 1; +- hsudc->gadget.ops = &s3c_hsudc_gadget_ops; +- hsudc->gadget.name = dev_name(dev); +- hsudc->gadget.dev.parent = dev; +- hsudc->gadget.dev.dma_mask = dev->dma_mask; +- hsudc->gadget.ep0 = &hsudc->ep[0].ep; +- +- hsudc->gadget.is_otg = 0; +- hsudc->gadget.is_a_peripheral = 0; +- +- s3c_hsudc_setup_ep(hsudc); +- +- hsudc->uclk = clk_get(&pdev->dev, "usb-device"); +- if (IS_ERR(hsudc->uclk)) { +- dev_err(dev, "failed to find usb-device clock source\n"); +- ret = PTR_ERR(hsudc->uclk); +- goto err_clk; +- } +- clk_enable(hsudc->uclk); +- +- local_irq_disable(); +- +- disable_irq(hsudc->irq); +- local_irq_enable(); +- return 0; +-err_clk: +- free_irq(hsudc->irq, hsudc); +-err_irq: +- iounmap(hsudc->regs); +- +-err_remap: +- release_resource(hsudc->mem_rsrc); +- kfree(hsudc->mem_rsrc); +- +-err_res: +- kfree(hsudc); +- return ret; +-} +- +-static struct platform_driver s3c_hsudc_driver = { +- .driver = { +- .owner = THIS_MODULE, +- .name = "s3c-hsudc", +- }, +- .probe = s3c_hsudc_probe, +-}; +- +-static int __init s3c_hsudc_modinit(void) +-{ +- return platform_driver_register(&s3c_hsudc_driver); +-} +- +-static void __exit s3c_hsudc_modexit(void) +-{ +- platform_driver_unregister(&s3c_hsudc_driver); +-} +- +-module_init(s3c_hsudc_modinit); +-module_exit(s3c_hsudc_modexit); +- +-MODULE_DESCRIPTION("Samsung S3C24XX USB high-speed controller driver"); +-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); +-MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c +deleted file mode 100644 +index 100f2635..00000000 +--- a/drivers/usb/gadget/s3c2410_udc.c ++++ /dev/null +@@ -1,2118 +0,0 @@ +-/* +- * linux/drivers/usb/gadget/s3c2410_udc.c +- * +- * Samsung S3C24xx series on-chip full speed USB device controllers +- * +- * Copyright (C) 2004-2007 Herbert P�tzl - Arnaud Patard +- * Additional cleanups by Ben Dooks <ben-linux@fluff.org> +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +- +-#include <linux/module.h> +-#include <linux/kernel.h> +-#include <linux/delay.h> +-#include <linux/ioport.h> +-#include <linux/sched.h> +-#include <linux/slab.h> +-#include <linux/errno.h> +-#include <linux/init.h> +-#include <linux/timer.h> +-#include <linux/list.h> +-#include <linux/interrupt.h> +-#include <linux/platform_device.h> +-#include <linux/clk.h> +-#include <linux/gpio.h> +-#include <linux/prefetch.h> +- +-#include <linux/debugfs.h> +-#include <linux/seq_file.h> +- +-#include <linux/usb.h> +-#include <linux/usb/gadget.h> +- +-#include <asm/byteorder.h> +-#include <asm/io.h> +-#include <asm/irq.h> +-#include <asm/system.h> +-#include <asm/unaligned.h> +-#include <mach/irqs.h> +- +-#include <mach/hardware.h> +- +-#include <plat/regs-udc.h> +-#include <plat/udc.h> +- +- +-#include "s3c2410_udc.h" +- +-#define DRIVER_DESC "S3C2410 USB Device Controller Gadget" +-#define DRIVER_VERSION "29 Apr 2007" +-#define DRIVER_AUTHOR "Herbert P�tzl <herbert@13thfloor.at>, " \ +- "Arnaud Patard <arnaud.patard@rtp-net.org>" +- +-static const char gadget_name[] = "s3c2410_udc"; +-static const char driver_desc[] = DRIVER_DESC; +- +-static struct s3c2410_udc *the_controller; +-static struct clk *udc_clock; +-static struct clk *usb_bus_clock; +-static void __iomem *base_addr; +-static u64 rsrc_start; +-static u64 rsrc_len; +-static struct dentry *s3c2410_udc_debugfs_root; +- +-static inline u32 udc_read(u32 reg) +-{ +- return readb(base_addr + reg); +-} +- +-static inline void udc_write(u32 value, u32 reg) +-{ +- writeb(value, base_addr + reg); +-} +- +-static inline void udc_writeb(void __iomem *base, u32 value, u32 reg) +-{ +- writeb(value, base + reg); +-} +- +-static struct s3c2410_udc_mach_info *udc_info; +- +-/*************************** DEBUG FUNCTION ***************************/ +-#define DEBUG_NORMAL 1 +-#define DEBUG_VERBOSE 2 +- +-#ifdef CONFIG_USB_S3C2410_DEBUG +-#define USB_S3C2410_DEBUG_LEVEL 0 +- +-static uint32_t s3c2410_ticks = 0; +- +-static int dprintk(int level, const char *fmt, ...) +-{ +- static char printk_buf[1024]; +- static long prevticks; +- static int invocation; +- va_list args; +- int len; +- +- if (level > USB_S3C2410_DEBUG_LEVEL) +- return 0; +- +- if (s3c2410_ticks != prevticks) { +- prevticks = s3c2410_ticks; +- invocation = 0; +- } +- +- len = scnprintf(printk_buf, +- sizeof(printk_buf), "%1lu.%02d USB: ", +- prevticks, invocation++); +- +- va_start(args, fmt); +- len = vscnprintf(printk_buf+len, +- sizeof(printk_buf)-len, fmt, args); +- va_end(args); +- +- return printk(KERN_DEBUG "%s", printk_buf); +-} +-#else +-static int dprintk(int level, const char *fmt, ...) +-{ +- return 0; +-} +-#endif +-static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) +-{ +- u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg; +- u32 ep_int_en_reg, usb_int_en_reg, ep0_csr; +- u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2; +- u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2; +- +- addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG); +- pwr_reg = udc_read(S3C2410_UDC_PWR_REG); +- ep_int_reg = udc_read(S3C2410_UDC_EP_INT_REG); +- usb_int_reg = udc_read(S3C2410_UDC_USB_INT_REG); +- ep_int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); +- usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG); +- udc_write(0, S3C2410_UDC_INDEX_REG); +- ep0_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- udc_write(1, S3C2410_UDC_INDEX_REG); +- ep1_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); +- ep1_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); +- ep1_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); +- ep1_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); +- udc_write(2, S3C2410_UDC_INDEX_REG); +- ep2_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); +- ep2_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); +- ep2_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); +- ep2_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); +- +- seq_printf(m, "FUNC_ADDR_REG : 0x%04X\n" +- "PWR_REG : 0x%04X\n" +- "EP_INT_REG : 0x%04X\n" +- "USB_INT_REG : 0x%04X\n" +- "EP_INT_EN_REG : 0x%04X\n" +- "USB_INT_EN_REG : 0x%04X\n" +- "EP0_CSR : 0x%04X\n" +- "EP1_I_CSR1 : 0x%04X\n" +- "EP1_I_CSR2 : 0x%04X\n" +- "EP1_O_CSR1 : 0x%04X\n" +- "EP1_O_CSR2 : 0x%04X\n" +- "EP2_I_CSR1 : 0x%04X\n" +- "EP2_I_CSR2 : 0x%04X\n" +- "EP2_O_CSR1 : 0x%04X\n" +- "EP2_O_CSR2 : 0x%04X\n", +- addr_reg,pwr_reg,ep_int_reg,usb_int_reg, +- ep_int_en_reg, usb_int_en_reg, ep0_csr, +- ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2, +- ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2 +- ); +- +- return 0; +-} +- +-static int s3c2410_udc_debugfs_fops_open(struct inode *inode, +- struct file *file) +-{ +- return single_open(file, s3c2410_udc_debugfs_seq_show, NULL); +-} +- +-static const struct file_operations s3c2410_udc_debugfs_fops = { +- .open = s3c2410_udc_debugfs_fops_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +- .owner = THIS_MODULE, +-}; +- +-/* io macros */ +- +-static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY, +- S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_clear_ep0_se(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_set_ep0_de(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG); +-} +- +-inline void s3c2410_udc_set_ep0_ss(void __iomem *b) +-{ +- udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- +- udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY +- | S3C2410_UDC_EP0_CSR_DE), +- S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY +- | S3C2410_UDC_EP0_CSR_SSE), +- S3C2410_UDC_EP0_CSR_REG); +-} +- +-static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base) +-{ +- udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY +- | S3C2410_UDC_EP0_CSR_DE), +- S3C2410_UDC_EP0_CSR_REG); +-} +- +-/*------------------------- I/O ----------------------------------*/ +- +-/* +- * s3c2410_udc_done +- */ +-static void s3c2410_udc_done(struct s3c2410_ep *ep, +- struct s3c2410_request *req, int status) +-{ +- unsigned halted = ep->halted; +- +- list_del_init(&req->queue); +- +- if (likely (req->req.status == -EINPROGRESS)) +- req->req.status = status; +- else +- status = req->req.status; +- +- ep->halted = 1; +- req->req.complete(&ep->ep, &req->req); +- ep->halted = halted; +-} +- +-static void s3c2410_udc_nuke(struct s3c2410_udc *udc, +- struct s3c2410_ep *ep, int status) +-{ +- /* Sanity check */ +- if (&ep->queue == NULL) +- return; +- +- while (!list_empty (&ep->queue)) { +- struct s3c2410_request *req; +- req = list_entry (ep->queue.next, struct s3c2410_request, +- queue); +- s3c2410_udc_done(ep, req, status); +- } +-} +- +-static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev) +-{ +- unsigned i; +- +- /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint +- * fifos, and pending transactions mustn't be continued in any case. +- */ +- +- for (i = 1; i < S3C2410_ENDPOINTS; i++) +- s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED); +-} +- +-static inline int s3c2410_udc_fifo_count_out(void) +-{ +- int tmp; +- +- tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8; +- tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG); +- return tmp; +-} +- +-/* +- * s3c2410_udc_write_packet +- */ +-static inline int s3c2410_udc_write_packet(int fifo, +- struct s3c2410_request *req, +- unsigned max) +-{ +- unsigned len = min(req->req.length - req->req.actual, max); +- u8 *buf = req->req.buf + req->req.actual; +- +- prefetch(buf); +- +- dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__, +- req->req.actual, req->req.length, len, req->req.actual + len); +- +- req->req.actual += len; +- +- udelay(5); +- writesb(base_addr + fifo, buf, len); +- return len; +-} +- +-/* +- * s3c2410_udc_write_fifo +- * +- * return: 0 = still running, 1 = completed, negative = errno +- */ +-static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, +- struct s3c2410_request *req) +-{ +- unsigned count; +- int is_last; +- u32 idx; +- int fifo_reg; +- u32 ep_csr; +- +- idx = ep->bEndpointAddress & 0x7F; +- switch (idx) { +- default: +- idx = 0; +- case 0: +- fifo_reg = S3C2410_UDC_EP0_FIFO_REG; +- break; +- case 1: +- fifo_reg = S3C2410_UDC_EP1_FIFO_REG; +- break; +- case 2: +- fifo_reg = S3C2410_UDC_EP2_FIFO_REG; +- break; +- case 3: +- fifo_reg = S3C2410_UDC_EP3_FIFO_REG; +- break; +- case 4: +- fifo_reg = S3C2410_UDC_EP4_FIFO_REG; +- break; +- } +- +- count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket); +- +- /* last packet is often short (sometimes a zlp) */ +- if (count != ep->ep.maxpacket) +- is_last = 1; +- else if (req->req.length != req->req.actual || req->req.zero) +- is_last = 0; +- else +- is_last = 2; +- +- /* Only ep0 debug messages are interesting */ +- if (idx == 0) +- dprintk(DEBUG_NORMAL, +- "Written ep%d %d.%d of %d b [last %d,z %d]\n", +- idx, count, req->req.actual, req->req.length, +- is_last, req->req.zero); +- +- if (is_last) { +- /* The order is important. It prevents sending 2 packets +- * at the same time */ +- +- if (idx == 0) { +- /* Reset signal => no need to say 'data sent' */ +- if (! (udc_read(S3C2410_UDC_USB_INT_REG) +- & S3C2410_UDC_USBINT_RESET)) +- s3c2410_udc_set_ep0_de_in(base_addr); +- ep->dev->ep0state=EP0_IDLE; +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY, +- S3C2410_UDC_IN_CSR1_REG); +- } +- +- s3c2410_udc_done(ep, req, 0); +- is_last = 1; +- } else { +- if (idx == 0) { +- /* Reset signal => no need to say 'data sent' */ +- if (! (udc_read(S3C2410_UDC_USB_INT_REG) +- & S3C2410_UDC_USBINT_RESET)) +- s3c2410_udc_set_ep0_ipr(base_addr); +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY, +- S3C2410_UDC_IN_CSR1_REG); +- } +- } +- +- return is_last; +-} +- +-static inline int s3c2410_udc_read_packet(int fifo, u8 *buf, +- struct s3c2410_request *req, unsigned avail) +-{ +- unsigned len; +- +- len = min(req->req.length - req->req.actual, avail); +- req->req.actual += len; +- +- readsb(fifo + base_addr, buf, len); +- return len; +-} +- +-/* +- * return: 0 = still running, 1 = queue empty, negative = errno +- */ +-static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, +- struct s3c2410_request *req) +-{ +- u8 *buf; +- u32 ep_csr; +- unsigned bufferspace; +- int is_last=1; +- unsigned avail; +- int fifo_count = 0; +- u32 idx; +- int fifo_reg; +- +- idx = ep->bEndpointAddress & 0x7F; +- +- switch (idx) { +- default: +- idx = 0; +- case 0: +- fifo_reg = S3C2410_UDC_EP0_FIFO_REG; +- break; +- case 1: +- fifo_reg = S3C2410_UDC_EP1_FIFO_REG; +- break; +- case 2: +- fifo_reg = S3C2410_UDC_EP2_FIFO_REG; +- break; +- case 3: +- fifo_reg = S3C2410_UDC_EP3_FIFO_REG; +- break; +- case 4: +- fifo_reg = S3C2410_UDC_EP4_FIFO_REG; +- break; +- } +- +- if (!req->req.length) +- return 1; +- +- buf = req->req.buf + req->req.actual; +- bufferspace = req->req.length - req->req.actual; +- if (!bufferspace) { +- dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__); +- return -1; +- } +- +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- +- fifo_count = s3c2410_udc_fifo_count_out(); +- dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count); +- +- if (fifo_count > ep->ep.maxpacket) +- avail = ep->ep.maxpacket; +- else +- avail = fifo_count; +- +- fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail); +- +- /* checking this with ep0 is not accurate as we already +- * read a control request +- **/ +- if (idx != 0 && fifo_count < ep->ep.maxpacket) { +- is_last = 1; +- /* overflowed this request? flush extra data */ +- if (fifo_count != avail) +- req->req.status = -EOVERFLOW; +- } else { +- is_last = (req->req.length <= req->req.actual) ? 1 : 0; +- } +- +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- fifo_count = s3c2410_udc_fifo_count_out(); +- +- /* Only ep0 debug messages are interesting */ +- if (idx == 0) +- dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n", +- __func__, fifo_count,is_last); +- +- if (is_last) { +- if (idx == 0) { +- s3c2410_udc_set_ep0_de_out(base_addr); +- ep->dev->ep0state = EP0_IDLE; +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, +- S3C2410_UDC_OUT_CSR1_REG); +- } +- +- s3c2410_udc_done(ep, req, 0); +- } else { +- if (idx == 0) { +- s3c2410_udc_clear_ep0_opr(base_addr); +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, +- S3C2410_UDC_OUT_CSR1_REG); +- } +- } +- +- return is_last; +-} +- +-static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq) +-{ +- unsigned char *outbuf = (unsigned char*)crq; +- int bytes_read = 0; +- +- udc_write(0, S3C2410_UDC_INDEX_REG); +- +- bytes_read = s3c2410_udc_fifo_count_out(); +- +- dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read); +- +- if (bytes_read > sizeof(struct usb_ctrlrequest)) +- bytes_read = sizeof(struct usb_ctrlrequest); +- +- readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read); +- +- dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__, +- bytes_read, crq->bRequest, crq->bRequestType, +- crq->wValue, crq->wIndex, crq->wLength); +- +- return bytes_read; +-} +- +-static int s3c2410_udc_get_status(struct s3c2410_udc *dev, +- struct usb_ctrlrequest *crq) +-{ +- u16 status = 0; +- u8 ep_num = crq->wIndex & 0x7F; +- u8 is_in = crq->wIndex & USB_DIR_IN; +- +- switch (crq->bRequestType & USB_RECIP_MASK) { +- case USB_RECIP_INTERFACE: +- break; +- +- case USB_RECIP_DEVICE: +- status = dev->devstatus; +- break; +- +- case USB_RECIP_ENDPOINT: +- if (ep_num > 4 || crq->wLength > 2) +- return 1; +- +- if (ep_num == 0) { +- udc_write(0, S3C2410_UDC_INDEX_REG); +- status = udc_read(S3C2410_UDC_IN_CSR1_REG); +- status = status & S3C2410_UDC_EP0_CSR_SENDSTL; +- } else { +- udc_write(ep_num, S3C2410_UDC_INDEX_REG); +- if (is_in) { +- status = udc_read(S3C2410_UDC_IN_CSR1_REG); +- status = status & S3C2410_UDC_ICSR1_SENDSTL; +- } else { +- status = udc_read(S3C2410_UDC_OUT_CSR1_REG); +- status = status & S3C2410_UDC_OCSR1_SENDSTL; +- } +- } +- +- status = status ? 1 : 0; +- break; +- +- default: +- return 1; +- } +- +- /* Seems to be needed to get it working. ouch :( */ +- udelay(5); +- udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG); +- udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG); +- s3c2410_udc_set_ep0_de_in(base_addr); +- +- return 0; +-} +-/*------------------------- usb state machine -------------------------------*/ +-static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value); +- +-static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, +- struct s3c2410_ep *ep, +- struct usb_ctrlrequest *crq, +- u32 ep0csr) +-{ +- int len, ret, tmp; +- +- /* start control request? */ +- if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY)) +- return; +- +- s3c2410_udc_nuke(dev, ep, -EPROTO); +- +- len = s3c2410_udc_read_fifo_crq(crq); +- if (len != sizeof(*crq)) { +- dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR" +- " wanted %d bytes got %d. Stalling out...\n", +- sizeof(*crq), len); +- s3c2410_udc_set_ep0_ss(base_addr); +- return; +- } +- +- dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n", +- crq->bRequest, crq->bRequestType, crq->wLength); +- +- /* cope with automagic for some standard requests. */ +- dev->req_std = (crq->bRequestType & USB_TYPE_MASK) +- == USB_TYPE_STANDARD; +- dev->req_config = 0; +- dev->req_pending = 1; +- +- switch (crq->bRequest) { +- case USB_REQ_SET_CONFIGURATION: +- dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n"); +- +- if (crq->bRequestType == USB_RECIP_DEVICE) { +- dev->req_config = 1; +- s3c2410_udc_set_ep0_de_out(base_addr); +- } +- break; +- +- case USB_REQ_SET_INTERFACE: +- dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n"); +- +- if (crq->bRequestType == USB_RECIP_INTERFACE) { +- dev->req_config = 1; +- s3c2410_udc_set_ep0_de_out(base_addr); +- } +- break; +- +- case USB_REQ_SET_ADDRESS: +- dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n"); +- +- if (crq->bRequestType == USB_RECIP_DEVICE) { +- tmp = crq->wValue & 0x7F; +- dev->address = tmp; +- udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE), +- S3C2410_UDC_FUNC_ADDR_REG); +- s3c2410_udc_set_ep0_de_out(base_addr); +- return; +- } +- break; +- +- case USB_REQ_GET_STATUS: +- dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n"); +- s3c2410_udc_clear_ep0_opr(base_addr); +- +- if (dev->req_std) { +- if (!s3c2410_udc_get_status(dev, crq)) { +- return; +- } +- } +- break; +- +- case USB_REQ_CLEAR_FEATURE: +- s3c2410_udc_clear_ep0_opr(base_addr); +- +- if (crq->bRequestType != USB_RECIP_ENDPOINT) +- break; +- +- if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0) +- break; +- +- s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0); +- s3c2410_udc_set_ep0_de_out(base_addr); +- return; +- +- case USB_REQ_SET_FEATURE: +- s3c2410_udc_clear_ep0_opr(base_addr); +- +- if (crq->bRequestType != USB_RECIP_ENDPOINT) +- break; +- +- if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0) +- break; +- +- s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1); +- s3c2410_udc_set_ep0_de_out(base_addr); +- return; +- +- default: +- s3c2410_udc_clear_ep0_opr(base_addr); +- break; +- } +- +- if (crq->bRequestType & USB_DIR_IN) +- dev->ep0state = EP0_IN_DATA_PHASE; +- else +- dev->ep0state = EP0_OUT_DATA_PHASE; +- +- if (!dev->driver) +- return; +- +- /* deliver the request to the gadget driver */ +- ret = dev->driver->setup(&dev->gadget, crq); +- if (ret < 0) { +- if (dev->req_config) { +- dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n", +- crq->bRequest, ret); +- return; +- } +- +- if (ret == -EOPNOTSUPP) +- dprintk(DEBUG_NORMAL, "Operation not supported\n"); +- else +- dprintk(DEBUG_NORMAL, +- "dev->driver->setup failed. (%d)\n", ret); +- +- udelay(5); +- s3c2410_udc_set_ep0_ss(base_addr); +- s3c2410_udc_set_ep0_de_out(base_addr); +- dev->ep0state = EP0_IDLE; +- /* deferred i/o == no response yet */ +- } else if (dev->req_pending) { +- dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n"); +- dev->req_pending=0; +- } +- +- dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]); +-} +- +-static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev) +-{ +- u32 ep0csr; +- struct s3c2410_ep *ep = &dev->ep[0]; +- struct s3c2410_request *req; +- struct usb_ctrlrequest crq; +- +- if (list_empty(&ep->queue)) +- req = NULL; +- else +- req = list_entry(ep->queue.next, struct s3c2410_request, queue); +- +- /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to +- * S3C2410_UDC_EP0_CSR_REG when index is zero */ +- +- udc_write(0, S3C2410_UDC_INDEX_REG); +- ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- +- dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n", +- ep0csr, ep0states[dev->ep0state]); +- +- /* clear stall status */ +- if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) { +- s3c2410_udc_nuke(dev, ep, -EPIPE); +- dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n"); +- s3c2410_udc_clear_ep0_sst(base_addr); +- dev->ep0state = EP0_IDLE; +- return; +- } +- +- /* clear setup end */ +- if (ep0csr & S3C2410_UDC_EP0_CSR_SE) { +- dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n"); +- s3c2410_udc_nuke(dev, ep, 0); +- s3c2410_udc_clear_ep0_se(base_addr); +- dev->ep0state = EP0_IDLE; +- } +- +- switch (dev->ep0state) { +- case EP0_IDLE: +- s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr); +- break; +- +- case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ +- dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n"); +- if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) { +- s3c2410_udc_write_fifo(ep, req); +- } +- break; +- +- case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ +- dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n"); +- if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) { +- s3c2410_udc_read_fifo(ep,req); +- } +- break; +- +- case EP0_END_XFER: +- dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n"); +- dev->ep0state = EP0_IDLE; +- break; +- +- case EP0_STALL: +- dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n"); +- dev->ep0state = EP0_IDLE; +- break; +- } +-} +- +-/* +- * handle_ep - Manage I/O endpoints +- */ +- +-static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) +-{ +- struct s3c2410_request *req; +- int is_in = ep->bEndpointAddress & USB_DIR_IN; +- u32 ep_csr1; +- u32 idx; +- +- if (likely (!list_empty(&ep->queue))) +- req = list_entry(ep->queue.next, +- struct s3c2410_request, queue); +- else +- req = NULL; +- +- idx = ep->bEndpointAddress & 0x7F; +- +- if (is_in) { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); +- dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n", +- idx, ep_csr1, req ? 1 : 0); +- +- if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) { +- dprintk(DEBUG_VERBOSE, "st\n"); +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL, +- S3C2410_UDC_IN_CSR1_REG); +- return; +- } +- +- if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) { +- s3c2410_udc_write_fifo(ep,req); +- } +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG); +- dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1); +- +- if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL, +- S3C2410_UDC_OUT_CSR1_REG); +- return; +- } +- +- if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) { +- s3c2410_udc_read_fifo(ep,req); +- } +- } +-} +- +-#include <mach/regs-irq.h> +- +-/* +- * s3c2410_udc_irq - interrupt handler +- */ +-static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev) +-{ +- struct s3c2410_udc *dev = _dev; +- int usb_status; +- int usbd_status; +- int pwr_reg; +- int ep0csr; +- int i; +- u32 idx, idx2; +- unsigned long flags; +- +- spin_lock_irqsave(&dev->lock, flags); +- +- /* Driver connected ? */ +- if (!dev->driver) { +- /* Clear interrupts */ +- udc_write(udc_read(S3C2410_UDC_USB_INT_REG), +- S3C2410_UDC_USB_INT_REG); +- udc_write(udc_read(S3C2410_UDC_EP_INT_REG), +- S3C2410_UDC_EP_INT_REG); +- } +- +- /* Save index */ +- idx = udc_read(S3C2410_UDC_INDEX_REG); +- +- /* Read status registers */ +- usb_status = udc_read(S3C2410_UDC_USB_INT_REG); +- usbd_status = udc_read(S3C2410_UDC_EP_INT_REG); +- pwr_reg = udc_read(S3C2410_UDC_PWR_REG); +- +- udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); +- ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- +- dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n", +- usb_status, usbd_status, pwr_reg, ep0csr); +- +- /* +- * Now, handle interrupts. There's two types : +- * - Reset, Resume, Suspend coming -> usb_int_reg +- * - EP -> ep_int_reg +- */ +- +- /* RESET */ +- if (usb_status & S3C2410_UDC_USBINT_RESET) { +- /* two kind of reset : +- * - reset start -> pwr reg = 8 +- * - reset end -> pwr reg = 0 +- **/ +- dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n", +- ep0csr, pwr_reg); +- +- dev->gadget.speed = USB_SPEED_UNKNOWN; +- udc_write(0x00, S3C2410_UDC_INDEX_REG); +- udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3, +- S3C2410_UDC_MAXP_REG); +- dev->address = 0; +- +- dev->ep0state = EP0_IDLE; +- dev->gadget.speed = USB_SPEED_FULL; +- +- /* clear interrupt */ +- udc_write(S3C2410_UDC_USBINT_RESET, +- S3C2410_UDC_USB_INT_REG); +- +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- spin_unlock_irqrestore(&dev->lock, flags); +- return IRQ_HANDLED; +- } +- +- /* RESUME */ +- if (usb_status & S3C2410_UDC_USBINT_RESUME) { +- dprintk(DEBUG_NORMAL, "USB resume\n"); +- +- /* clear interrupt */ +- udc_write(S3C2410_UDC_USBINT_RESUME, +- S3C2410_UDC_USB_INT_REG); +- +- if (dev->gadget.speed != USB_SPEED_UNKNOWN +- && dev->driver +- && dev->driver->resume) +- dev->driver->resume(&dev->gadget); +- } +- +- /* SUSPEND */ +- if (usb_status & S3C2410_UDC_USBINT_SUSPEND) { +- dprintk(DEBUG_NORMAL, "USB suspend\n"); +- +- /* clear interrupt */ +- udc_write(S3C2410_UDC_USBINT_SUSPEND, +- S3C2410_UDC_USB_INT_REG); +- +- if (dev->gadget.speed != USB_SPEED_UNKNOWN +- && dev->driver +- && dev->driver->suspend) +- dev->driver->suspend(&dev->gadget); +- +- dev->ep0state = EP0_IDLE; +- } +- +- /* EP */ +- /* control traffic */ +- /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready +- * generate an interrupt +- */ +- if (usbd_status & S3C2410_UDC_INT_EP0) { +- dprintk(DEBUG_VERBOSE, "USB ep0 irq\n"); +- /* Clear the interrupt bit by setting it to 1 */ +- udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG); +- s3c2410_udc_handle_ep0(dev); +- } +- +- /* endpoint data transfers */ +- for (i = 1; i < S3C2410_ENDPOINTS; i++) { +- u32 tmp = 1 << i; +- if (usbd_status & tmp) { +- dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i); +- +- /* Clear the interrupt bit by setting it to 1 */ +- udc_write(tmp, S3C2410_UDC_EP_INT_REG); +- s3c2410_udc_handle_ep(&dev->ep[i]); +- } +- } +- +- /* what else causes this interrupt? a receive! who is it? */ +- if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) { +- for (i = 1; i < S3C2410_ENDPOINTS; i++) { +- idx2 = udc_read(S3C2410_UDC_INDEX_REG); +- udc_write(i, S3C2410_UDC_INDEX_REG); +- +- if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1) +- s3c2410_udc_handle_ep(&dev->ep[i]); +- +- /* restore index */ +- udc_write(idx2, S3C2410_UDC_INDEX_REG); +- } +- } +- +- dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD); +- +- /* Restore old index */ +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- +- spin_unlock_irqrestore(&dev->lock, flags); +- +- return IRQ_HANDLED; +-} +-/*------------------------- s3c2410_ep_ops ----------------------------------*/ +- +-static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep) +-{ +- return container_of(ep, struct s3c2410_ep, ep); +-} +- +-static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget) +-{ +- return container_of(gadget, struct s3c2410_udc, gadget); +-} +- +-static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req) +-{ +- return container_of(req, struct s3c2410_request, req); +-} +- +-/* +- * s3c2410_udc_ep_enable +- */ +-static int s3c2410_udc_ep_enable(struct usb_ep *_ep, +- const struct usb_endpoint_descriptor *desc) +-{ +- struct s3c2410_udc *dev; +- struct s3c2410_ep *ep; +- u32 max, tmp; +- unsigned long flags; +- u32 csr1,csr2; +- u32 int_en_reg; +- +- ep = to_s3c2410_ep(_ep); +- +- if (!_ep || !desc || ep->desc +- || _ep->name == ep0name +- || desc->bDescriptorType != USB_DT_ENDPOINT) +- return -EINVAL; +- +- dev = ep->dev; +- if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) +- return -ESHUTDOWN; +- +- max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; +- +- local_irq_save (flags); +- _ep->maxpacket = max & 0x7ff; +- ep->desc = desc; +- ep->halted = 0; +- ep->bEndpointAddress = desc->bEndpointAddress; +- +- /* set max packet */ +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(max >> 3, S3C2410_UDC_MAXP_REG); +- +- /* set type, direction, address; reset fifo counters */ +- if (desc->bEndpointAddress & USB_DIR_IN) { +- csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT; +- csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN; +- +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr1, S3C2410_UDC_IN_CSR1_REG); +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr2, S3C2410_UDC_IN_CSR2_REG); +- } else { +- /* don't flush in fifo or it will cause endpoint interrupt */ +- csr1 = S3C2410_UDC_ICSR1_CLRDT; +- csr2 = S3C2410_UDC_ICSR2_DMAIEN; +- +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr1, S3C2410_UDC_IN_CSR1_REG); +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr2, S3C2410_UDC_IN_CSR2_REG); +- +- csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT; +- csr2 = S3C2410_UDC_OCSR2_DMAIEN; +- +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG); +- udc_write(ep->num, S3C2410_UDC_INDEX_REG); +- udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG); +- } +- +- /* enable irqs */ +- int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); +- udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG); +- +- /* print some debug message */ +- tmp = desc->bEndpointAddress; +- dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n", +- _ep->name,ep->num, tmp, +- desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max); +- +- local_irq_restore (flags); +- s3c2410_udc_set_halt(_ep, 0); +- +- return 0; +-} +- +-/* +- * s3c2410_udc_ep_disable +- */ +-static int s3c2410_udc_ep_disable(struct usb_ep *_ep) +-{ +- struct s3c2410_ep *ep = to_s3c2410_ep(_ep); +- unsigned long flags; +- u32 int_en_reg; +- +- if (!_ep || !ep->desc) { +- dprintk(DEBUG_NORMAL, "%s not enabled\n", +- _ep ? ep->ep.name : NULL); +- return -EINVAL; +- } +- +- local_irq_save(flags); +- +- dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); +- +- ep->desc = NULL; +- ep->halted = 1; +- +- s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN); +- +- /* disable irqs */ +- int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); +- udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG); +- +- local_irq_restore(flags); +- +- dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name); +- +- return 0; +-} +- +-/* +- * s3c2410_udc_alloc_request +- */ +-static struct usb_request * +-s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags) +-{ +- struct s3c2410_request *req; +- +- dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags); +- +- if (!_ep) +- return NULL; +- +- req = kzalloc (sizeof(struct s3c2410_request), mem_flags); +- if (!req) +- return NULL; +- +- INIT_LIST_HEAD (&req->queue); +- return &req->req; +-} +- +-/* +- * s3c2410_udc_free_request +- */ +-static void +-s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req) +-{ +- struct s3c2410_ep *ep = to_s3c2410_ep(_ep); +- struct s3c2410_request *req = to_s3c2410_req(_req); +- +- dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); +- +- if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) +- return; +- +- WARN_ON (!list_empty (&req->queue)); +- kfree(req); +-} +- +-/* +- * s3c2410_udc_queue +- */ +-static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, +- gfp_t gfp_flags) +-{ +- struct s3c2410_request *req = to_s3c2410_req(_req); +- struct s3c2410_ep *ep = to_s3c2410_ep(_ep); +- struct s3c2410_udc *dev; +- u32 ep_csr = 0; +- int fifo_count = 0; +- unsigned long flags; +- +- if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { +- dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__); +- return -EINVAL; +- } +- +- dev = ep->dev; +- if (unlikely (!dev->driver +- || dev->gadget.speed == USB_SPEED_UNKNOWN)) { +- return -ESHUTDOWN; +- } +- +- local_irq_save (flags); +- +- if (unlikely(!_req || !_req->complete +- || !_req->buf || !list_empty(&req->queue))) { +- if (!_req) +- dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__); +- else { +- dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n", +- __func__, !_req->complete,!_req->buf, +- !list_empty(&req->queue)); +- } +- +- local_irq_restore(flags); +- return -EINVAL; +- } +- +- _req->status = -EINPROGRESS; +- _req->actual = 0; +- +- dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n", +- __func__, ep->bEndpointAddress, _req->length); +- +- if (ep->bEndpointAddress) { +- udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG); +- +- ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN) +- ? S3C2410_UDC_IN_CSR1_REG +- : S3C2410_UDC_OUT_CSR1_REG); +- fifo_count = s3c2410_udc_fifo_count_out(); +- } else { +- udc_write(0, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); +- fifo_count = s3c2410_udc_fifo_count_out(); +- } +- +- /* kickstart this i/o queue? */ +- if (list_empty(&ep->queue) && !ep->halted) { +- if (ep->bEndpointAddress == 0 /* ep0 */) { +- switch (dev->ep0state) { +- case EP0_IN_DATA_PHASE: +- if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY) +- && s3c2410_udc_write_fifo(ep, +- req)) { +- dev->ep0state = EP0_IDLE; +- req = NULL; +- } +- break; +- +- case EP0_OUT_DATA_PHASE: +- if ((!_req->length) +- || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY) +- && s3c2410_udc_read_fifo(ep, +- req))) { +- dev->ep0state = EP0_IDLE; +- req = NULL; +- } +- break; +- +- default: +- local_irq_restore(flags); +- return -EL2HLT; +- } +- } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 +- && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY)) +- && s3c2410_udc_write_fifo(ep, req)) { +- req = NULL; +- } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY) +- && fifo_count +- && s3c2410_udc_read_fifo(ep, req)) { +- req = NULL; +- } +- } +- +- /* pio or dma irq handler advances the queue. */ +- if (likely (req != 0)) +- list_add_tail(&req->queue, &ep->queue); +- +- local_irq_restore(flags); +- +- dprintk(DEBUG_VERBOSE, "%s ok\n", __func__); +- return 0; +-} +- +-/* +- * s3c2410_udc_dequeue +- */ +-static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) +-{ +- struct s3c2410_ep *ep = to_s3c2410_ep(_ep); +- struct s3c2410_udc *udc; +- int retval = -EINVAL; +- unsigned long flags; +- struct s3c2410_request *req = NULL; +- +- dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); +- +- if (!the_controller->driver) +- return -ESHUTDOWN; +- +- if (!_ep || !_req) +- return retval; +- +- udc = to_s3c2410_udc(ep->gadget); +- +- local_irq_save (flags); +- +- list_for_each_entry (req, &ep->queue, queue) { +- if (&req->req == _req) { +- list_del_init (&req->queue); +- _req->status = -ECONNRESET; +- retval = 0; +- break; +- } +- } +- +- if (retval == 0) { +- dprintk(DEBUG_VERBOSE, +- "dequeued req %p from %s, len %d buf %p\n", +- req, _ep->name, _req->length, _req->buf); +- +- s3c2410_udc_done(ep, req, -ECONNRESET); +- } +- +- local_irq_restore (flags); +- return retval; +-} +- +-/* +- * s3c2410_udc_set_halt +- */ +-static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) +-{ +- struct s3c2410_ep *ep = to_s3c2410_ep(_ep); +- u32 ep_csr = 0; +- unsigned long flags; +- u32 idx; +- +- if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { +- dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__); +- return -EINVAL; +- } +- +- local_irq_save (flags); +- +- idx = ep->bEndpointAddress & 0x7F; +- +- if (idx == 0) { +- s3c2410_udc_set_ep0_ss(base_addr); +- s3c2410_udc_set_ep0_de_out(base_addr); +- } else { +- udc_write(idx, S3C2410_UDC_INDEX_REG); +- ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN) +- ? S3C2410_UDC_IN_CSR1_REG +- : S3C2410_UDC_OUT_CSR1_REG); +- +- if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { +- if (value) +- udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL, +- S3C2410_UDC_IN_CSR1_REG); +- else { +- ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL; +- udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG); +- ep_csr |= S3C2410_UDC_ICSR1_CLRDT; +- udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG); +- } +- } else { +- if (value) +- udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL, +- S3C2410_UDC_OUT_CSR1_REG); +- else { +- ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL; +- udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG); +- ep_csr |= S3C2410_UDC_OCSR1_CLRDT; +- udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG); +- } +- } +- } +- +- ep->halted = value ? 1 : 0; +- local_irq_restore (flags); +- +- return 0; +-} +- +-static const struct usb_ep_ops s3c2410_ep_ops = { +- .enable = s3c2410_udc_ep_enable, +- .disable = s3c2410_udc_ep_disable, +- +- .alloc_request = s3c2410_udc_alloc_request, +- .free_request = s3c2410_udc_free_request, +- +- .queue = s3c2410_udc_queue, +- .dequeue = s3c2410_udc_dequeue, +- +- .set_halt = s3c2410_udc_set_halt, +-}; +- +-/*------------------------- usb_gadget_ops ----------------------------------*/ +- +-/* +- * s3c2410_udc_get_frame +- */ +-static int s3c2410_udc_get_frame(struct usb_gadget *_gadget) +-{ +- int tmp; +- +- dprintk(DEBUG_VERBOSE, "%s()\n", __func__); +- +- tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8; +- tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG); +- return tmp; +-} +- +-/* +- * s3c2410_udc_wakeup +- */ +-static int s3c2410_udc_wakeup(struct usb_gadget *_gadget) +-{ +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- return 0; +-} +- +-/* +- * s3c2410_udc_set_selfpowered +- */ +-static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value) +-{ +- struct s3c2410_udc *udc = to_s3c2410_udc(gadget); +- +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- if (value) +- udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED); +- else +- udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); +- +- return 0; +-} +- +-static void s3c2410_udc_disable(struct s3c2410_udc *dev); +-static void s3c2410_udc_enable(struct s3c2410_udc *dev); +- +-static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on) +-{ +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- if (udc_info && (udc_info->udc_command || +- gpio_is_valid(udc_info->pullup_pin))) { +- +- if (is_on) +- s3c2410_udc_enable(udc); +- else { +- if (udc->gadget.speed != USB_SPEED_UNKNOWN) { +- if (udc->driver && udc->driver->disconnect) +- udc->driver->disconnect(&udc->gadget); +- +- } +- s3c2410_udc_disable(udc); +- } +- } +- else +- return -EOPNOTSUPP; +- +- return 0; +-} +- +-static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active) +-{ +- struct s3c2410_udc *udc = to_s3c2410_udc(gadget); +- +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- udc->vbus = (is_active != 0); +- s3c2410_udc_set_pullup(udc, is_active); +- return 0; +-} +- +-static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on) +-{ +- struct s3c2410_udc *udc = to_s3c2410_udc(gadget); +- +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- s3c2410_udc_set_pullup(udc, is_on ? 0 : 1); +- return 0; +-} +- +-static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) +-{ +- struct s3c2410_udc *dev = _dev; +- unsigned int value; +- +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- value = gpio_get_value(udc_info->vbus_pin) ? 1 : 0; +- if (udc_info->vbus_pin_inverted) +- value = !value; +- +- if (value != dev->vbus) +- s3c2410_udc_vbus_session(&dev->gadget, value); +- +- return IRQ_HANDLED; +-} +- +-static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma) +-{ +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- if (udc_info && udc_info->vbus_draw) { +- udc_info->vbus_draw(ma); +- return 0; +- } +- +- return -ENOTSUPP; +-} +- +-static const struct usb_gadget_ops s3c2410_ops = { +- .get_frame = s3c2410_udc_get_frame, +- .wakeup = s3c2410_udc_wakeup, +- .set_selfpowered = s3c2410_udc_set_selfpowered, +- .pullup = s3c2410_udc_pullup, +- .vbus_session = s3c2410_udc_vbus_session, +- .vbus_draw = s3c2410_vbus_draw, +-}; +- +-static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd) +-{ +- if (!udc_info) +- return; +- +- if (udc_info->udc_command) { +- udc_info->udc_command(S3C2410_UDC_P_DISABLE); +- } else if (gpio_is_valid(udc_info->pullup_pin)) { +- int value; +- +- switch (cmd) { +- case S3C2410_UDC_P_ENABLE: +- value = 1; +- break; +- case S3C2410_UDC_P_DISABLE: +- value = 0; +- break; +- default: +- return; +- } +- value ^= udc_info->pullup_pin_inverted; +- +- gpio_set_value(udc_info->pullup_pin, value); +- } +-} +- +-/*------------------------- gadget driver handling---------------------------*/ +-/* +- * s3c2410_udc_disable +- */ +-static void s3c2410_udc_disable(struct s3c2410_udc *dev) +-{ +- dprintk(DEBUG_NORMAL, "%s()\n", __func__); +- +- /* Disable all interrupts */ +- udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG); +- udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG); +- +- /* Clear the interrupt registers */ +- udc_write(S3C2410_UDC_USBINT_RESET +- | S3C2410_UDC_USBINT_RESUME +- | S3C2410_UDC_USBINT_SUSPEND, +- S3C2410_UDC_USB_INT_REG); +- +- udc_write(0x1F, S3C2410_UDC_EP_INT_REG); +- +- /* Good bye, cruel world */ +- s3c2410_udc_command(S3C2410_UDC_P_DISABLE); +- +- /* Set speed to unknown */ +- dev->gadget.speed = USB_SPEED_UNKNOWN; +-} +- +-/* +- * s3c2410_udc_reinit +- */ +-static void s3c2410_udc_reinit(struct s3c2410_udc *dev) +-{ +- u32 i; +- +- /* device/ep0 records init */ +- INIT_LIST_HEAD (&dev->gadget.ep_list); +- INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); +- dev->ep0state = EP0_IDLE; +- +- for (i = 0; i < S3C2410_ENDPOINTS; i++) { +- struct s3c2410_ep *ep = &dev->ep[i]; +- +- if (i != 0) +- list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); +- +- ep->dev = dev; +- ep->desc = NULL; +- ep->halted = 0; +- INIT_LIST_HEAD (&ep->queue); +- } +-} +- +-/* +- * s3c2410_udc_enable +- */ +-static void s3c2410_udc_enable(struct s3c2410_udc *dev) +-{ +- int i; +- +- dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n"); +- +- /* dev->gadget.speed = USB_SPEED_UNKNOWN; */ +- dev->gadget.speed = USB_SPEED_FULL; +- +- /* Set MAXP for all endpoints */ +- for (i = 0; i < S3C2410_ENDPOINTS; i++) { +- udc_write(i, S3C2410_UDC_INDEX_REG); +- udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3, +- S3C2410_UDC_MAXP_REG); +- } +- +- /* Set default power state */ +- udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG); +- +- /* Enable reset and suspend interrupt interrupts */ +- udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND, +- S3C2410_UDC_USB_INT_EN_REG); +- +- /* Enable ep0 interrupt */ +- udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG); +- +- /* time to say "hello, world" */ +- s3c2410_udc_command(S3C2410_UDC_P_ENABLE); +-} +- +-/* +- * usb_gadget_probe_driver +- */ +-int usb_gadget_probe_driver(struct usb_gadget_driver *driver, +- int (*bind)(struct usb_gadget *)) +-{ +- struct s3c2410_udc *udc = the_controller; +- int retval; +- +- dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name); +- +- /* Sanity checks */ +- if (!udc) +- return -ENODEV; +- +- if (udc->driver) +- return -EBUSY; +- +- if (!bind || !driver->setup || driver->speed < USB_SPEED_FULL) { +- printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", +- bind, driver->setup, driver->speed); +- return -EINVAL; +- } +-#if defined(MODULE) +- if (!driver->unbind) { +- printk(KERN_ERR "Invalid driver: no unbind method\n"); +- return -EINVAL; +- } +-#endif +- +- /* Hook the driver */ +- udc->driver = driver; +- udc->gadget.dev.driver = &driver->driver; +- +- /* Bind the driver */ +- if ((retval = device_add(&udc->gadget.dev)) != 0) { +- printk(KERN_ERR "Error in device_add() : %d\n",retval); +- goto register_error; +- } +- +- dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", +- driver->driver.name); +- +- if ((retval = bind(&udc->gadget)) != 0) { +- device_del(&udc->gadget.dev); +- goto register_error; +- } +- +- /* Enable udc */ +- s3c2410_udc_enable(udc); +- +- return 0; +- +-register_error: +- udc->driver = NULL; +- udc->gadget.dev.driver = NULL; +- return retval; +-} +-EXPORT_SYMBOL(usb_gadget_probe_driver); +- +-/* +- * usb_gadget_unregister_driver +- */ +-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +-{ +- struct s3c2410_udc *udc = the_controller; +- +- if (!udc) +- return -ENODEV; +- +- if (!driver || driver != udc->driver || !driver->unbind) +- return -EINVAL; +- +- dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n", +- driver->driver.name); +- +- /* report disconnect */ +- if (driver->disconnect) +- driver->disconnect(&udc->gadget); +- +- driver->unbind(&udc->gadget); +- +- device_del(&udc->gadget.dev); +- udc->driver = NULL; +- +- /* Disable udc */ +- s3c2410_udc_disable(udc); +- +- return 0; +-} +- +-/*---------------------------------------------------------------------------*/ +-static struct s3c2410_udc memory = { +- .gadget = { +- .ops = &s3c2410_ops, +- .ep0 = &memory.ep[0].ep, +- .name = gadget_name, +- .dev = { +- .init_name = "gadget", +- }, +- }, +- +- /* control endpoint */ +- .ep[0] = { +- .num = 0, +- .ep = { +- .name = ep0name, +- .ops = &s3c2410_ep_ops, +- .maxpacket = EP0_FIFO_SIZE, +- }, +- .dev = &memory, +- }, +- +- /* first group of endpoints */ +- .ep[1] = { +- .num = 1, +- .ep = { +- .name = "ep1-bulk", +- .ops = &s3c2410_ep_ops, +- .maxpacket = EP_FIFO_SIZE, +- }, +- .dev = &memory, +- .fifo_size = EP_FIFO_SIZE, +- .bEndpointAddress = 1, +- .bmAttributes = USB_ENDPOINT_XFER_BULK, +- }, +- .ep[2] = { +- .num = 2, +- .ep = { +- .name = "ep2-bulk", +- .ops = &s3c2410_ep_ops, +- .maxpacket = EP_FIFO_SIZE, +- }, +- .dev = &memory, +- .fifo_size = EP_FIFO_SIZE, +- .bEndpointAddress = 2, +- .bmAttributes = USB_ENDPOINT_XFER_BULK, +- }, +- .ep[3] = { +- .num = 3, +- .ep = { +- .name = "ep3-bulk", +- .ops = &s3c2410_ep_ops, +- .maxpacket = EP_FIFO_SIZE, +- }, +- .dev = &memory, +- .fifo_size = EP_FIFO_SIZE, +- .bEndpointAddress = 3, +- .bmAttributes = USB_ENDPOINT_XFER_BULK, +- }, +- .ep[4] = { +- .num = 4, +- .ep = { +- .name = "ep4-bulk", +- .ops = &s3c2410_ep_ops, +- .maxpacket = EP_FIFO_SIZE, +- }, +- .dev = &memory, +- .fifo_size = EP_FIFO_SIZE, +- .bEndpointAddress = 4, +- .bmAttributes = USB_ENDPOINT_XFER_BULK, +- } +- +-}; +- +-/* +- * probe - binds to the platform device +- */ +-static int s3c2410_udc_probe(struct platform_device *pdev) +-{ +- struct s3c2410_udc *udc = &memory; +- struct device *dev = &pdev->dev; +- int retval; +- int irq; +- +- dev_dbg(dev, "%s()\n", __func__); +- +- usb_bus_clock = clk_get(NULL, "usb-bus-gadget"); +- if (IS_ERR(usb_bus_clock)) { +- dev_err(dev, "failed to get usb bus clock source\n"); +- return PTR_ERR(usb_bus_clock); +- } +- +- clk_enable(usb_bus_clock); +- +- udc_clock = clk_get(NULL, "usb-device"); +- if (IS_ERR(udc_clock)) { +- dev_err(dev, "failed to get udc clock source\n"); +- return PTR_ERR(udc_clock); +- } +- +- clk_enable(udc_clock); +- +- mdelay(10); +- +- dev_dbg(dev, "got and enabled clocks\n"); +- +- if (strncmp(pdev->name, "s3c2440", 7) == 0) { +- dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n"); +- memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE; +- memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE; +- memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE; +- memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE; +- } +- +- spin_lock_init (&udc->lock); +- udc_info = pdev->dev.platform_data; +- +- rsrc_start = S3C2410_PA_USBDEV; +- rsrc_len = S3C24XX_SZ_USBDEV; +- +- if (!request_mem_region(rsrc_start, rsrc_len, gadget_name)) +- return -EBUSY; +- +- base_addr = ioremap(rsrc_start, rsrc_len); +- if (!base_addr) { +- retval = -ENOMEM; +- goto err_mem; +- } +- +- device_initialize(&udc->gadget.dev); +- udc->gadget.dev.parent = &pdev->dev; +- udc->gadget.dev.dma_mask = pdev->dev.dma_mask; +- +- the_controller = udc; +- platform_set_drvdata(pdev, udc); +- +- s3c2410_udc_disable(udc); +- s3c2410_udc_reinit(udc); +- +- /* irq setup after old hardware state is cleaned up */ +- retval = request_irq(IRQ_USBD, s3c2410_udc_irq, +- IRQF_DISABLED, gadget_name, udc); +- +- if (retval != 0) { +- dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval); +- retval = -EBUSY; +- goto err_map; +- } +- +- dev_dbg(dev, "got irq %i\n", IRQ_USBD); +- +- if (udc_info && udc_info->vbus_pin > 0) { +- retval = gpio_request(udc_info->vbus_pin, "udc vbus"); +- if (retval < 0) { +- dev_err(dev, "cannot claim vbus pin\n"); +- goto err_int; +- } +- +- irq = gpio_to_irq(udc_info->vbus_pin); +- if (irq < 0) { +- dev_err(dev, "no irq for gpio vbus pin\n"); +- goto err_gpio_claim; +- } +- +- retval = request_irq(irq, s3c2410_udc_vbus_irq, +- IRQF_DISABLED | IRQF_TRIGGER_RISING +- | IRQF_TRIGGER_FALLING | IRQF_SHARED, +- gadget_name, udc); +- +- if (retval != 0) { +- dev_err(dev, "can't get vbus irq %d, err %d\n", +- irq, retval); +- retval = -EBUSY; +- goto err_gpio_claim; +- } +- +- dev_dbg(dev, "got irq %i\n", irq); +- } else { +- udc->vbus = 1; +- } +- +- if (udc_info && !udc_info->udc_command && +- gpio_is_valid(udc_info->pullup_pin)) { +- +- retval = gpio_request_one(udc_info->pullup_pin, +- udc_info->vbus_pin_inverted ? +- GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, +- "udc pullup"); +- if (retval) +- goto err_vbus_irq; +- } +- +- if (s3c2410_udc_debugfs_root) { +- udc->regs_info = debugfs_create_file("registers", S_IRUGO, +- s3c2410_udc_debugfs_root, +- udc, &s3c2410_udc_debugfs_fops); +- if (!udc->regs_info) +- dev_warn(dev, "debugfs file creation failed\n"); +- } +- +- dev_dbg(dev, "probe ok\n"); +- +- return 0; +- +-err_vbus_irq: +- if (udc_info && udc_info->vbus_pin > 0) +- free_irq(gpio_to_irq(udc_info->vbus_pin), udc); +-err_gpio_claim: +- if (udc_info && udc_info->vbus_pin > 0) +- gpio_free(udc_info->vbus_pin); +-err_int: +- free_irq(IRQ_USBD, udc); +-err_map: +- iounmap(base_addr); +-err_mem: +- release_mem_region(rsrc_start, rsrc_len); +- +- return retval; +-} +- +-/* +- * s3c2410_udc_remove +- */ +-static int s3c2410_udc_remove(struct platform_device *pdev) +-{ +- struct s3c2410_udc *udc = platform_get_drvdata(pdev); +- unsigned int irq; +- +- dev_dbg(&pdev->dev, "%s()\n", __func__); +- if (udc->driver) +- return -EBUSY; +- +- debugfs_remove(udc->regs_info); +- +- if (udc_info && !udc_info->udc_command && +- gpio_is_valid(udc_info->pullup_pin)) +- gpio_free(udc_info->pullup_pin); +- +- if (udc_info && udc_info->vbus_pin > 0) { +- irq = gpio_to_irq(udc_info->vbus_pin); +- free_irq(irq, udc); +- } +- +- free_irq(IRQ_USBD, udc); +- +- iounmap(base_addr); +- release_mem_region(rsrc_start, rsrc_len); +- +- platform_set_drvdata(pdev, NULL); +- +- if (!IS_ERR(udc_clock) && udc_clock != NULL) { +- clk_disable(udc_clock); +- clk_put(udc_clock); +- udc_clock = NULL; +- } +- +- if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) { +- clk_disable(usb_bus_clock); +- clk_put(usb_bus_clock); +- usb_bus_clock = NULL; +- } +- +- dev_dbg(&pdev->dev, "%s: remove ok\n", __func__); +- return 0; +-} +- +-#ifdef CONFIG_PM +-static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message) +-{ +- s3c2410_udc_command(S3C2410_UDC_P_DISABLE); +- +- return 0; +-} +- +-static int s3c2410_udc_resume(struct platform_device *pdev) +-{ +- s3c2410_udc_command(S3C2410_UDC_P_ENABLE); +- +- return 0; +-} +-#else +-#define s3c2410_udc_suspend NULL +-#define s3c2410_udc_resume NULL +-#endif +- +-static struct platform_driver udc_driver_2410 = { +- .driver = { +- .name = "s3c2410-usbgadget", +- .owner = THIS_MODULE, +- }, +- .probe = s3c2410_udc_probe, +- .remove = s3c2410_udc_remove, +- .suspend = s3c2410_udc_suspend, +- .resume = s3c2410_udc_resume, +-}; +- +-static struct platform_driver udc_driver_2440 = { +- .driver = { +- .name = "s3c2440-usbgadget", +- .owner = THIS_MODULE, +- }, +- .probe = s3c2410_udc_probe, +- .remove = s3c2410_udc_remove, +- .suspend = s3c2410_udc_suspend, +- .resume = s3c2410_udc_resume, +-}; +- +-static int __init udc_init(void) +-{ +- int retval; +- +- dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION); +- +- s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL); +- if (IS_ERR(s3c2410_udc_debugfs_root)) { +- printk(KERN_ERR "%s: debugfs dir creation failed %ld\n", +- gadget_name, PTR_ERR(s3c2410_udc_debugfs_root)); +- s3c2410_udc_debugfs_root = NULL; +- } +- +- retval = platform_driver_register(&udc_driver_2410); +- if (retval) +- goto err; +- +- retval = platform_driver_register(&udc_driver_2440); +- if (retval) +- goto err; +- +- return 0; +- +-err: +- debugfs_remove(s3c2410_udc_debugfs_root); +- return retval; +-} +- +-static void __exit udc_exit(void) +-{ +- platform_driver_unregister(&udc_driver_2410); +- platform_driver_unregister(&udc_driver_2440); +- debugfs_remove(s3c2410_udc_debugfs_root); +-} +- +-EXPORT_SYMBOL(usb_gadget_unregister_driver); +- +-module_init(udc_init); +-module_exit(udc_exit); +- +-MODULE_AUTHOR(DRIVER_AUTHOR); +-MODULE_DESCRIPTION(DRIVER_DESC); +-MODULE_VERSION(DRIVER_VERSION); +-MODULE_LICENSE("GPL"); +-MODULE_ALIAS("platform:s3c2410-usbgadget"); +-MODULE_ALIAS("platform:s3c2440-usbgadget"); +diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h +deleted file mode 100644 +index 9e0bece4..00000000 +--- a/drivers/usb/gadget/s3c2410_udc.h ++++ /dev/null +@@ -1,110 +0,0 @@ +-/* +- * linux/drivers/usb/gadget/s3c2410_udc.h +- * Samsung on-chip full speed USB device controllers +- * +- * Copyright (C) 2004-2007 Herbert P�tzl - Arnaud Patard +- * Additional cleanups by Ben Dooks <ben-linux@fluff.org> +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- * +- */ +- +-#ifndef _S3C2410_UDC_H +-#define _S3C2410_UDC_H +- +-struct s3c2410_ep { +- struct list_head queue; +- unsigned long last_io; /* jiffies timestamp */ +- struct usb_gadget *gadget; +- struct s3c2410_udc *dev; +- const struct usb_endpoint_descriptor *desc; +- struct usb_ep ep; +- u8 num; +- +- unsigned short fifo_size; +- u8 bEndpointAddress; +- u8 bmAttributes; +- +- unsigned halted : 1; +- unsigned already_seen : 1; +- unsigned setup_stage : 1; +-}; +- +- +-/* Warning : ep0 has a fifo of 16 bytes */ +-/* Don't try to set 32 or 64 */ +-/* also testusb 14 fails wit 16 but is */ +-/* fine with 8 */ +-#define EP0_FIFO_SIZE 8 +-#define EP_FIFO_SIZE 64 +-#define DEFAULT_POWER_STATE 0x00 +- +-#define S3C2440_EP_FIFO_SIZE 128 +- +-static const char ep0name [] = "ep0"; +- +-static const char *const ep_name[] = { +- ep0name, /* everyone has ep0 */ +- /* s3c2410 four bidirectional bulk endpoints */ +- "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk", +-}; +- +-#define S3C2410_ENDPOINTS ARRAY_SIZE(ep_name) +- +-struct s3c2410_request { +- struct list_head queue; /* ep's requests */ +- struct usb_request req; +-}; +- +-enum ep0_state { +- EP0_IDLE, +- EP0_IN_DATA_PHASE, +- EP0_OUT_DATA_PHASE, +- EP0_END_XFER, +- EP0_STALL, +-}; +- +-static const char *ep0states[]= { +- "EP0_IDLE", +- "EP0_IN_DATA_PHASE", +- "EP0_OUT_DATA_PHASE", +- "EP0_END_XFER", +- "EP0_STALL", +-}; +- +-struct s3c2410_udc { +- spinlock_t lock; +- +- struct s3c2410_ep ep[S3C2410_ENDPOINTS]; +- int address; +- struct usb_gadget gadget; +- struct usb_gadget_driver *driver; +- struct s3c2410_request fifo_req; +- u8 fifo_buf[EP_FIFO_SIZE]; +- u16 devstatus; +- +- u32 port_status; +- int ep0state; +- +- unsigned got_irq : 1; +- +- unsigned req_std : 1; +- unsigned req_config : 1; +- unsigned req_pending : 1; +- u8 vbus; +- struct dentry *regs_info; +-}; +- +-#endif +diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h +index 5b791946..d5be8376 100644 +--- a/drivers/usb/gadget/uvc.h ++++ b/drivers/usb/gadget/uvc.h +@@ -27,14 +27,12 @@ + #define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5) + #define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5) + +-struct uvc_request_data +-{ ++struct uvc_request_data { + unsigned int length; + __u8 data[60]; + }; + +-struct uvc_event +-{ ++struct uvc_event { + union { + enum usb_device_speed speed; + struct usb_ctrlrequest req; +@@ -108,8 +106,7 @@ extern unsigned int uvc_gadget_trace_param; + * Structures + */ + +-struct uvc_video +-{ ++struct uvc_video { + struct usb_ep *ep; + + /* Frame parameters */ +@@ -137,25 +134,23 @@ struct uvc_video + unsigned int fid; + }; + +-enum uvc_state +-{ ++enum uvc_state { + UVC_STATE_DISCONNECTED, + UVC_STATE_CONNECTED, + UVC_STATE_STREAMING, + }; + +-struct uvc_device +-{ +- struct video_device *vdev; +- enum uvc_state state; +- struct usb_function func; +- struct uvc_video video; ++/*#define UVC_DOUBLE_STREAM*/ + +- /* Descriptors */ ++struct uvc_common { ++ struct usb_function func; + struct { +- const struct uvc_descriptor_header * const *control; +- const struct uvc_descriptor_header * const *fs_streaming; +- const struct uvc_descriptor_header * const *hs_streaming; ++ struct uvc_descriptor_header **control; ++ struct uvc_descriptor_header **fs_streaming; ++ struct uvc_descriptor_header **hs_streaming; ++ ++ struct uvc_descriptor_header **fs_streaming2; ++ struct uvc_descriptor_header **hs_streaming2; + } desc; + + unsigned int control_intf; +@@ -163,20 +158,33 @@ struct uvc_device + struct usb_request *control_req; + void *control_buf; + +- unsigned int streaming_intf; ++ struct uvc_device *uvc1; ++ struct uvc_device *uvc2; ++}; + ++struct uvc_device { ++ struct uvc_common *comm; ++ struct video_device *vdev; ++ enum uvc_state state; ++ struct uvc_video video; ++ unsigned int streaming_intf; + /* Events */ + unsigned int event_length; +- unsigned int event_setup_out : 1; ++ unsigned int event_setup_out:1; + }; + +-static inline struct uvc_device *to_uvc(struct usb_function *f) +-{ +- return container_of(f, struct uvc_device, func); ++static inline struct uvc_device *to_uvc(struct usb_function *f) { ++ struct uvc_common *comm = ++ (struct uvc_common *)container_of(f, struct uvc_common, func); ++ return comm->uvc1; ++} ++ ++ ++static inline struct uvc_common *to_common(struct usb_function *f) { ++ return (struct uvc_common *)container_of(f, struct uvc_common, func); + } + +-struct uvc_file_handle +-{ ++struct uvc_file_handle { + struct v4l2_fh vfh; + struct uvc_video *device; + }; +diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c +index f7395ac5..a0b472e6 100644 +--- a/drivers/usb/gadget/uvc_queue.c ++++ b/drivers/usb/gadget/uvc_queue.c +@@ -132,7 +132,8 @@ uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, + + mutex_lock(&queue->mutex); + +- if ((ret = uvc_free_buffers(queue)) < 0) ++ ret = uvc_free_buffers(queue); ++ if (ret < 0) + goto done; + + /* Bail out if no buffers should be allocated. */ +@@ -265,6 +266,7 @@ uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) + + spin_lock_irqsave(&queue->irqlock, flags); + if (queue->flags & UVC_QUEUE_DISCONNECTED) { ++ printk(KERN_EMERG "uvc_queue_buffer UVC_QUEUE_DISCONNECTED.\n"); + spin_unlock_irqrestore(&queue->irqlock, flags); + ret = -ENODEV; + goto done; +@@ -323,7 +325,8 @@ uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, + } + + buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); +- if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) ++ ret = uvc_queue_waiton(buf, nonblocking); ++ if (ret < 0) + goto done; + + uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", +@@ -445,7 +448,8 @@ uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + while (size > 0) { + page = vmalloc_to_page((void *)addr); +- if ((ret = vm_insert_page(vma, start, page)) < 0) ++ ret = vm_insert_page(vma, start, page); ++ if (ret < 0) + goto done; + + start += PAGE_SIZE; +diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c +index 5e807f08..02c65b6e 100644 +--- a/drivers/usb/gadget/uvc_v4l2.c ++++ b/drivers/usb/gadget/uvc_v4l2.c +@@ -33,10 +33,9 @@ + */ + + static int +-uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) +-{ +- struct usb_composite_dev *cdev = uvc->func.config->cdev; +- struct usb_request *req = uvc->control_req; ++uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) { ++ struct usb_composite_dev *cdev = uvc->comm->func.config->cdev; ++ struct usb_request *req = uvc->comm->control_req; + + if (data->length < 0) + return usb_ep_set_halt(cdev->gadget->ep0); +@@ -44,6 +43,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) + req->length = min(uvc->event_length, data->length); + req->zero = data->length < uvc->event_length; + req->dma = DMA_ADDR_INVALID; ++ req->context = uvc; + + memcpy(req->buf, data->data, data->length); + +@@ -54,20 +54,24 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) + * V4L2 + */ + +-struct uvc_format +-{ ++struct uvc_format { + u8 bpp; + u32 fcc; + }; + + static struct uvc_format uvc_formats[] = { +- { 16, V4L2_PIX_FMT_YUYV }, +- { 0, V4L2_PIX_FMT_MJPEG }, ++ { 12, V4L2_PIX_FMT_NV12 }, ++ { 0, V4L2_PIX_FMT_MJPEG }, ++ { 0, V4L2_PIX_FMT_H264 }, + }; + +-static int +-uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt) ++void set_yuv_bpp(int bpp) + { ++ uvc_formats[0].bpp = bpp; ++} ++ ++static int ++uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt) { + fmt->fmt.pix.pixelformat = video->fcc; + fmt->fmt.pix.width = video->width; + fmt->fmt.pix.height = video->height; +@@ -81,8 +85,7 @@ uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt) + } + + static int +-uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) +-{ ++uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) { + struct uvc_format *format; + unsigned int imagesize; + unsigned int bpl; +@@ -119,8 +122,7 @@ uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) + } + + static int +-uvc_v4l2_open(struct file *file) +-{ ++uvc_v4l2_open(struct file *file) { + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + struct uvc_file_handle *handle; +@@ -147,6 +149,8 @@ uvc_v4l2_open(struct file *file) + handle->device = &uvc->video; + file->private_data = &handle->vfh; + ++ return 0; ++ + uvc_function_connect(uvc); + return 0; + +@@ -156,8 +160,7 @@ error: + } + + static int +-uvc_v4l2_release(struct file *file) +-{ ++uvc_v4l2_release(struct file *file) { + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); +@@ -179,17 +182,41 @@ uvc_v4l2_release(struct file *file) + return 0; + } + ++ ++ ++#define VIDIOC_TEST_FMTS 0x12345678 ++#define VIDIOC_RESET_DESC 0x445566 ++#define VIDIOC_CONNECT_NOW 0x238956 ++ ++void change_usb_support_fmt(struct uvc_device *uvc, void *arg); + static long +-uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) +-{ ++uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); +- struct usb_composite_dev *cdev = uvc->func.config->cdev; ++ struct usb_composite_dev *cdev = uvc->comm->func.config->cdev; + struct uvc_video *video = &uvc->video; + int ret = 0; + + switch (cmd) { ++ case VIDIOC_TEST_FMTS: ++ /*enumFmts(arg);*/ ++ return 0; ++ ++ ++ case VIDIOC_RESET_DESC: ++ ++ change_usb_support_fmt(uvc, arg); ++ ++ break; ++ ++ case VIDIOC_CONNECT_NOW: ++ ++ uvc_function_connect(uvc); ++ ++ return 0; ++ break; ++ + /* Query capabilities */ + case VIDIOC_QUERYCAP: + { +@@ -204,7 +231,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + break; + } +- + /* Get & Set format */ + case VIDIOC_G_FMT: + { +@@ -215,7 +241,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + + return uvc_v4l2_get_format(video, fmt); + } +- + case VIDIOC_S_FMT: + { + struct v4l2_format *fmt = arg; +@@ -225,14 +250,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + + return uvc_v4l2_set_format(video, fmt); + } +- + /* Buffers & streaming */ + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *rb = arg; + + if (rb->type != video->queue.type || +- rb->memory != V4L2_MEMORY_MMAP) ++ rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + ret = uvc_alloc_buffers(&video->queue, rb->count, +@@ -244,7 +268,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + ret = 0; + break; + } +- + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *buf = arg; +@@ -254,7 +277,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + + return uvc_query_buffer(&video->queue, buf); + } +- + case VIDIOC_QBUF: + if ((ret = uvc_queue_buffer(&video->queue, arg)) < 0) + return ret; +@@ -274,7 +296,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + + return uvc_video_enable(video, 1); + } +- + case VIDIOC_STREAMOFF: + { + int *type = arg; +@@ -286,27 +307,26 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + } + + /* Events */ +- case VIDIOC_DQEVENT: ++ case VIDIOC_DQEVENT: + { +- struct v4l2_event *event = arg; +- +- ret = v4l2_event_dequeue(&handle->vfh, event, +- file->f_flags & O_NONBLOCK); +- if (ret == 0 && event->type == UVC_EVENT_SETUP) { +- struct uvc_event *uvc_event = (void *)&event->u.data; +- +- /* Tell the complete callback to generate an event for +- * the next request that will be enqueued by +- * uvc_event_write. +- */ +- uvc->event_setup_out = +- !(uvc_event->req.bRequestType & USB_DIR_IN); +- uvc->event_length = uvc_event->req.wLength; +- } +- +- return ret; ++ struct v4l2_event *event = arg; ++ ++ ret = v4l2_event_dequeue(&handle->vfh, event, ++ file->f_flags & O_NONBLOCK); ++ if (ret == 0 && event->type == UVC_EVENT_SETUP) { ++ struct uvc_event *uvc_event = (void *)&event->u.data; ++ ++ /* Tell the complete callback to generate an event for ++ * the next request that will be enqueued by ++ * uvc_event_write. ++ */ ++ uvc->event_setup_out = ++ !(uvc_event->req.bRequestType & USB_DIR_IN); ++ uvc->event_length = uvc_event->req.wLength; + } + ++ return ret; ++ } + case VIDIOC_SUBSCRIBE_EVENT: + { + struct v4l2_event_subscription *sub = arg; +@@ -316,7 +336,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + + return v4l2_event_subscribe(&handle->vfh, arg); + } +- + case VIDIOC_UNSUBSCRIBE_EVENT: + return v4l2_event_unsubscribe(&handle->vfh, arg); + +@@ -332,14 +351,12 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) + } + + static long +-uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +-{ ++uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { + return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); + } + + static int +-uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) +-{ ++uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + +@@ -347,8 +364,7 @@ uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) + } + + static unsigned int +-uvc_v4l2_poll(struct file *file, poll_table *wait) +-{ ++uvc_v4l2_poll(struct file *file, poll_table *wait) { + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); +diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c +index b08f3543..10c02ffb 100644 +--- a/drivers/usb/gadget/uvc_video.c ++++ b/drivers/usb/gadget/uvc_video.c +@@ -26,6 +26,19 @@ + * Video codecs + */ + ++unsigned char header[] = { ++ 0x0c, 0x8d, 0x51, 0x0e, 0xac, 0x1d, 0x37, 0xd1, 0xaf, 0x1d, 0x78, 0x02, ++ 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, ++ 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, ++ 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, ++ 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, ++ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, ++ 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, ++ 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, ++ 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xdd, 0x00, 0x04, 0x00, ++ 0x28, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, ++}; ++ + static int + uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf, + u8 *data, int len) +@@ -93,7 +106,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, + } + + if (video->payload_size == video->max_payload_size || +- buf->buf.bytesused == video->queue.buf_used) ++ buf->buf.bytesused == video->queue.buf_used) + video->payload_size = 0; + } + +@@ -171,12 +184,13 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) + break; + + case -ESHUTDOWN: +- printk(KERN_INFO "VS request cancelled.\n"); ++ uvc_queue_cancel(&video->queue, 1); + goto requeue; + + default: + printk(KERN_INFO "VS request completed with status %d.\n", + req->status); ++ uvc_queue_cancel(&video->queue, 0); + goto requeue; + } + +@@ -188,8 +202,8 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) + } + + video->encode(req, video, buf); +- +- if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) { ++ ret = usb_ep_queue(ep, req, GFP_ATOMIC); ++ if (ret < 0) { + printk(KERN_INFO "Failed to queue request (%d).\n", ret); + usb_ep_set_halt(ep); + spin_unlock_irqrestore(&video->queue.irqlock, flags); +@@ -236,7 +250,8 @@ uvc_video_alloc_requests(struct uvc_video *video) + BUG_ON(video->req_size); + + for (i = 0; i < UVC_NUM_REQUESTS; ++i) { +- video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL); ++ video->req_buffer[i] = \ ++ kmalloc(video->ep->maxpacket, GFP_KERNEL); + if (video->req_buffer[i] == NULL) + goto error; + +@@ -310,7 +325,8 @@ uvc_video_pump(struct uvc_video *video) + video->encode(req, video, buf); + + /* Queue the USB request */ +- if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) { ++ ret = usb_ep_queue(video->ep, req, GFP_KERNEL); ++ if (ret < 0) { + printk(KERN_INFO "Failed to queue request (%d)\n", ret); + usb_ep_set_halt(video->ep); + spin_unlock_irqrestore(&video->queue.irqlock, flags); +@@ -346,13 +362,15 @@ uvc_video_enable(struct uvc_video *video, int enable) + + uvc_video_free_requests(video); + uvc_queue_enable(&video->queue, 0); ++ ++ usb_ep_disable(video->ep); + return 0; + } +- +- if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) ++ ret = uvc_queue_enable(&video->queue, 1); ++ if (ret < 0) + return ret; +- +- if ((ret = uvc_video_alloc_requests(video)) < 0) ++ ret = uvc_video_alloc_requests(video); ++ if (ret < 0) + return ret; + + if (video->max_payload_size) { +diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c +index a5a0fdb8..cc319678 100644 +--- a/drivers/usb/gadget/webcam.c ++++ b/drivers/usb/gadget/webcam.c +@@ -10,6 +10,17 @@ + * (at your option) any later version. + * + */ ++ ++ ++ ++ ++#ifdef TEST_AUDIO ++#include "audio.c" ++#else ++ ++#define ENABLE_UVC ++#define ENABLE_UAC ++ + #include <linux/kernel.h> + #include <linux/device.h> + #include <linux/usb/video.h> +@@ -32,18 +43,34 @@ + #include "uvc_video.c" + #include "uvc_v4l2.c" + #include "f_uvc.c" +- ++#include "f_uac.c" ++#include "audio_poll.c" ++#include "uvc.h" + /* -------------------------------------------------------------------------- + * Device descriptor + */ + ++#define YUV_NV12 0 ++#define YUV_YUY2 1 ++ ++ ++#ifdef ENABLE_UVC ++ + #define WEBCAM_VENDOR_ID 0x1d6b /* Linux Foundation */ + #define WEBCAM_PRODUCT_ID 0x0102 /* Webcam A/V gadget */ ++ ++#else ++ ++#define WEBCAM_VENDOR_ID 0x3d9c /* Linux Foundation */ ++#define WEBCAM_PRODUCT_ID 0x0806 /* Webcam A/V gadget */ ++ ++#endif ++ + #define WEBCAM_DEVICE_BCD 0x0010 /* 0.10 */ + +-static char webcam_vendor_label[] = "Linux Foundation"; +-static char webcam_product_label[] = "Webcam gadget"; +-static char webcam_config_label[] = "Video"; ++static const char webcam_vendor_label[] = "FULLHAN webcam"; ++static const char webcam_product_label[] = "Webcam gadget"; ++static const char webcam_config_label[] = "Video"; + + /* string IDs are assigned dynamically */ + +@@ -51,6 +78,16 @@ static char webcam_config_label[] = "Video"; + #define STRING_PRODUCT_IDX 1 + #define STRING_DESCRIPTION_IDX 2 + ++/* identification number of Unit or Terminal */ ++#define UVC_INTERFACE_ID 0 ++#define UVC_CAMERAL_TERMINAL_ID 1 ++#define UVC_PROCESSING_UNIT_ID 2 ++#define UVC_H264_EXTENSION_UNIT_ID 3 ++#define UVC_OUTPUT_TERMINAL_ID 4 ++#define UVC_OUTPUT_TERMINAL2_ID 5 ++ ++ ++ + static struct usb_string webcam_strings[] = { + [STRING_MANUFACTURER_IDX].s = webcam_vendor_label, + [STRING_PRODUCT_IDX].s = webcam_product_label, +@@ -85,9 +122,9 @@ static struct usb_device_descriptor webcam_device_descriptor = { + .bNumConfigurations = 0, /* dynamic */ + }; + +-DECLARE_UVC_HEADER_DESCRIPTOR(1); ++DECLARE_UVC_HEADER_DESCRIPTOR(2); + +-static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { ++static struct UVC_HEADER_DESCRIPTOR(2) uvc_control_header = { + .bLength = UVC_DT_HEADER_SIZE(1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_HEADER, +@@ -102,7 +139,7 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = { + .bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_INPUT_TERMINAL, +- .bTerminalID = 1, ++ .bTerminalID = UVC_CAMERAL_TERMINAL_ID, + .wTerminalType = cpu_to_le16(0x0201), + .bAssocTerminal = 0, + .iTerminal = 0, +@@ -110,64 +147,117 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = { + .wObjectiveFocalLengthMax = cpu_to_le16(0), + .wOcularFocalLength = cpu_to_le16(0), + .bControlSize = 3, +- .bmControls[0] = 2, +- .bmControls[1] = 0, +- .bmControls[2] = 0, ++ .bmControls[0] = 0x0e, /* 0xff*/ ++ .bmControls[1] = 0x00, /* 0xff*/ ++ .bmControls[2] = 0x07, + }; + + static const struct uvc_processing_unit_descriptor uvc_processing = { + .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, +- .bUnitID = 2, +- .bSourceID = 1, ++ .bUnitID = UVC_PROCESSING_UNIT_ID, ++ .bSourceID = UVC_CAMERAL_TERMINAL_ID, + .wMaxMultiplier = cpu_to_le16(16*1024), + .bControlSize = 2, +- .bmControls[0] = 1, +- .bmControls[1] = 0, ++ .bmControls[0] = 0x0b, /*0xff*/ ++ .bmControls[1] = 0x00, /*0xff*/ + .iProcessing = 0, + }; + ++ ++DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 18); ++ ++static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 18) h264_extension_unit = { ++ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 18), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, ++ .bUnitID = UVC_H264_EXTENSION_UNIT_ID, ++ .guidExtensionCode = { 0x41, 0x76, 0x9e, 0xa2, 0x04,\ ++ 0xde, 0xe3, 0x47, 0x8b, 0x2b, 0xf4, 0x34, 0x1a,\ ++ 0xff, 0x00, 0x3b}, ++ .bNumControls = 17, ++ .bNrInPins = 1, ++ .baSourceID[0] = UVC_PROCESSING_UNIT_ID, ++ .bControlSize = 18, ++ .bmControls[0] = 0xff, ++ .bmControls[1] = 0xff, ++ .bmControls[2] = 0xff, ++ .bmControls[3] = 0xff, ++ .bmControls[4] = 0xff, ++ .bmControls[5] = 0xff, ++ .bmControls[6] = 0xff, ++ .bmControls[7] = 0xff, ++ .bmControls[8] = 0xff, ++ .bmControls[9] = 0xff, ++ .bmControls[10] = 0xff, ++ .bmControls[11] = 0xff, ++ .bmControls[12] = 0xff, ++ .bmControls[13] = 0xff, ++ .bmControls[14] = 0xff, ++ .bmControls[15] = 0xff, ++ .bmControls[16] = 0xff, ++ .iExtension = 0, ++}; ++ ++ + static const struct uvc_output_terminal_descriptor uvc_output_terminal = { + .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, +- .bTerminalID = 3, ++ .bTerminalID = UVC_OUTPUT_TERMINAL_ID, + .wTerminalType = cpu_to_le16(0x0101), + .bAssocTerminal = 0, +- .bSourceID = 2, ++ .bSourceID = UVC_H264_EXTENSION_UNIT_ID, + .iTerminal = 0, + }; + +-DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); + +-static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = { +- .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2), ++ ++static const struct uvc_output_terminal_descriptor uvc_output_terminal2 = { ++ .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, ++ .bTerminalID = UVC_OUTPUT_TERMINAL2_ID, ++ .wTerminalType = cpu_to_le16(0x0101), ++ .bAssocTerminal = 0, ++ .bSourceID = UVC_H264_EXTENSION_UNIT_ID, ++ .iTerminal = 0, ++}; ++ ++ ++ ++ ++DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 1); ++ ++static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 1) uvc_input_header = { ++ .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 1), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_INPUT_HEADER, +- .bNumFormats = 2, ++ .bNumFormats = 1, + .wTotalLength = 0, /* dynamic */ + .bEndpointAddress = 0, /* dynamic */ + .bmInfo = 0, +- .bTerminalLink = 3, ++ .bTerminalLink = UVC_OUTPUT_TERMINAL_ID, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls[0][0] = 0, +- .bmaControls[1][0] = 4, ++ /*.bmaControls[1][0] = 4,*/ ++ /*.bmaControls[2][0] = 4,*/ + }; + +-static const struct uvc_format_uncompressed uvc_format_yuv = { ++static /*const*/ struct uvc_format_uncompressed uvc_format_nv12 = { + .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, +- .bNumFrameDescriptors = 2, +- .guidFormat = +- { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, +- 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}, +- .bBitsPerPixel = 16, ++ .bNumFrameDescriptors = 3, ++ .guidFormat = { 'N', 'V', '1', '2',\ ++ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00,\ ++ 0xaa, 0x00, 0x38, 0x9b, 0x71}, ++ .bBitsPerPixel = 12, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, +@@ -175,29 +265,31 @@ static const struct uvc_format_uncompressed uvc_format_yuv = { + .bCopyProtect = 0, + }; + +-DECLARE_UVC_FRAME_UNCOMPRESSED(1); + DECLARE_UVC_FRAME_UNCOMPRESSED(3); ++DECLARE_UVC_FRAME_UNCOMPRESSED(5); + +-static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = { +- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3), ++static const struct UVC_FRAME_UNCOMPRESSED(5) uvc_frame_nv12_360p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(5), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, + .bFrameIndex = 1, + .bmCapabilities = 0, + .wWidth = cpu_to_le16(640), +- .wHeight = cpu_to_le16(360), ++ .wHeight = cpu_to_le16(368), + .dwMinBitRate = cpu_to_le32(18432000), + .dwMaxBitRate = cpu_to_le32(55296000), +- .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), +- .dwDefaultFrameInterval = cpu_to_le32(666666), +- .bFrameIntervalType = 3, +- .dwFrameInterval[0] = cpu_to_le32(666666), +- .dwFrameInterval[1] = cpu_to_le32(1000000), +- .dwFrameInterval[2] = cpu_to_le32(5000000), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(471040), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ + }; + +-static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = { +- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), ++static const struct UVC_FRAME_UNCOMPRESSED(5) uvc_frame_nv12_720p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(5), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, + .bFrameIndex = 2, +@@ -207,17 +299,54 @@ static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = { + .dwMinBitRate = cpu_to_le32(29491200), + .dwMaxBitRate = cpu_to_le32(29491200), + .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), +- .dwDefaultFrameInterval = cpu_to_le32(5000000), +- .bFrameIntervalType = 1, +- .dwFrameInterval[0] = cpu_to_le32(5000000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ ++}; ++ ++static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_nv12_1080p = { ++ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1088), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), ++ .dwDefaultFrameInterval = cpu_to_le32(666666), ++ .bFrameIntervalType = 3, ++ .dwFrameInterval[0] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(5000000), /*2fps*/ ++}; ++ ++static /*const*/ struct uvc_format_mjpeg uvc_format_mjpg = { ++ .bLength = UVC_DT_FORMAT_MJPEG_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_MJPEG, ++ .bFormatIndex = 1, ++ .bNumFrameDescriptors = 3, ++ .bmFlags = 0, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, + }; + +-static const struct uvc_format_mjpeg uvc_format_mjpg = { ++ ++static const struct uvc_format_mjpeg uvc_format_mjpg_fm1 = { + .bLength = UVC_DT_FORMAT_MJPEG_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FORMAT_MJPEG, +- .bFormatIndex = 2, +- .bNumFrameDescriptors = 2, ++ .bFormatIndex = 1, ++ .bNumFrameDescriptors = 1, + .bmFlags = 0, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, +@@ -226,29 +355,30 @@ static const struct uvc_format_mjpeg uvc_format_mjpg = { + .bCopyProtect = 0, + }; + +-DECLARE_UVC_FRAME_MJPEG(1); +-DECLARE_UVC_FRAME_MJPEG(3); ++DECLARE_UVC_FRAME_MJPEG(5); + +-static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { +- .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), ++static const struct UVC_FRAME_MJPEG(5) uvc_frame_mjpg_360p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(5), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, + .bFrameIndex = 1, + .bmCapabilities = 0, + .wWidth = cpu_to_le16(640), +- .wHeight = cpu_to_le16(360), ++ .wHeight = cpu_to_le16(368), + .dwMinBitRate = cpu_to_le32(18432000), + .dwMaxBitRate = cpu_to_le32(55296000), + .dwMaxVideoFrameBufferSize = cpu_to_le32(460800), +- .dwDefaultFrameInterval = cpu_to_le32(666666), +- .bFrameIntervalType = 3, +- .dwFrameInterval[0] = cpu_to_le32(666666), +- .dwFrameInterval[1] = cpu_to_le32(1000000), +- .dwFrameInterval[2] = cpu_to_le32(5000000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ + }; + +-static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { +- .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), ++static const struct UVC_FRAME_MJPEG(5) uvc_frame_mjpg_720p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(5), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, + .bFrameIndex = 2, +@@ -258,11 +388,138 @@ static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { + .dwMinBitRate = cpu_to_le32(29491200), + .dwMaxBitRate = cpu_to_le32(29491200), + .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200), +- .dwDefaultFrameInterval = cpu_to_le32(5000000), +- .bFrameIntervalType = 1, +- .dwFrameInterval[0] = cpu_to_le32(5000000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ + }; + ++static const struct UVC_FRAME_MJPEG(5) uvc_frame_mjpg_1080p = { ++ .bLength = UVC_DT_FRAME_MJPEG_SIZE(5), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_MJPEG, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1088), ++ .dwMinBitRate = cpu_to_le32(29491200), ++ .dwMaxBitRate = cpu_to_le32(29491200), ++ .dwMaxVideoFrameBufferSize = cpu_to_le32(4147200), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ ++}; ++ ++static /*const*/ struct uvc_format_frameBased uvc_format_h264 = { ++ .bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE, ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED, ++ .bFormatIndex = 1, ++ .bNumFrameDescriptors = 1, ++ .guidFormat = { 'H', '2', '6', '4',\ ++ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,\ ++ 0x00, 0x38, 0x9b, 0x71}, ++ .bBitsPerPixel = 0, ++ .bDefaultFrameIndex = 1, ++ .bAspectRatioX = 0, ++ .bAspectRatioY = 0, ++ .bmInterfaceFlags = 0, ++ .bCopyProtect = 0, ++ .bVariableSize = 1, ++}; ++ ++DECLARE_UVC_FRAME_FRAMEBASED(5); ++ ++static const struct UVC_FRAME_FRAMEBASED(5) uvc_frame_h264_360p = { ++ .bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(5), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 1, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(640), ++ .wHeight = cpu_to_le16(368), ++ .dwMinBitRate = cpu_to_le32(18432000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwBytesPerLine = 0, ++ /*when bFrameIntervalType = 0 which means continuous frame interval ++ //.dwMinFrameInterval = 0, ++ //.dwMaxFrameInterval = 0, ++ //.dwFrameIntervalStep= 0,*/ ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ ++}; ++ ++static const struct UVC_FRAME_FRAMEBASED(5) uvc_frame_h264_720p = { ++ .bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(5), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 2, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1280), ++ .wHeight = cpu_to_le16(720), ++ .dwMinBitRate = cpu_to_le32(18432000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwBytesPerLine = 0, ++ /*when bFrameIntervalType = 0 which means continuous frame interval ++ //.dwMinFrameInterval = 0, ++ //.dwMaxFrameInterval = 0, ++ //.dwFrameIntervalStep= 0,*/ ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ ++}; ++ ++static const struct UVC_FRAME_FRAMEBASED(5) uvc_frame_h264_1080p = { ++ .bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(5), ++ .bDescriptorType = USB_DT_CS_INTERFACE, ++ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, ++ .bFrameIndex = 3, ++ .bmCapabilities = 0, ++ .wWidth = cpu_to_le16(1920), ++ .wHeight = cpu_to_le16(1088), ++ .dwMinBitRate = cpu_to_le32(18432000), ++ .dwMaxBitRate = cpu_to_le32(55296000), ++ .dwDefaultFrameInterval = cpu_to_le32(333333), ++ .bFrameIntervalType = 5, ++ .dwBytesPerLine = 0, ++ /*when bFrameIntervalType = 0 which means continuous frame interval ++ //.dwMinFrameInterval = 0, ++ //.dwMaxFrameInterval = 0, ++ //.dwFrameIntervalStep= 0,*/ ++ .dwFrameInterval[0] = cpu_to_le32(166666), /*60fps*/ ++ .dwFrameInterval[1] = cpu_to_le32(333333), /*30fps*/ ++ .dwFrameInterval[2] = cpu_to_le32(666666), /*15fps*/ ++ .dwFrameInterval[3] = cpu_to_le32(1000000), /*10fps*/ ++ .dwFrameInterval[4] = cpu_to_le32(5000000), /*2fps*/ ++}; ++#if 0 ++static const struct uvc_still_image_descriptor uvc_still_image = { ++ .bLength = UVC_DT_STILL_IMAGE_SIZE, ++ .bDescriptorType = 0x24, ++ .bDescriptorSubType = 0x03, ++ .bEndpointAddress = 0, ++ .bNumImageSizePatterns = 1, ++ .wSizePatterns[0] = 640, ++ .wSizePatterns[1] = 480, ++ .bNumCompressionPattern = 0, ++}; ++#endif + static const struct uvc_color_matching_descriptor uvc_color_matching = { + .bLength = UVC_DT_COLOR_MATCHING_SIZE, + .bDescriptorType = USB_DT_CS_INTERFACE, +@@ -276,43 +533,474 @@ static const struct uvc_descriptor_header * const uvc_control_cls[] = { + (const struct uvc_descriptor_header *) &uvc_control_header, + (const struct uvc_descriptor_header *) &uvc_camera_terminal, + (const struct uvc_descriptor_header *) &uvc_processing, ++ (const struct uvc_descriptor_header *) &h264_extension_unit, + (const struct uvc_descriptor_header *) &uvc_output_terminal, ++#ifdef UVC_DOUBLE_STREAM ++ (const struct uvc_descriptor_header *) &uvc_output_terminal2, ++#endif + NULL, + }; + + static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = { + (const struct uvc_descriptor_header *) &uvc_input_header, +- (const struct uvc_descriptor_header *) &uvc_format_yuv, +- (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, +- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, ++ /*(const struct uvc_descriptor_header *) &uvc_format_nv12, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_360p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_720p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_1080p,*/ + (const struct uvc_descriptor_header *) &uvc_format_mjpg, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, + (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p, ++ /*(const struct uvc_descriptor_header *) &uvc_format_h264, ++ //(const struct uvc_descriptor_header *) &uvc_frame_h264_360p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_h264_1080p,*/ + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, + }; + + static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { + (const struct uvc_descriptor_header *) &uvc_input_header, +- (const struct uvc_descriptor_header *) &uvc_format_yuv, +- (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p, +- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p, +- (const struct uvc_descriptor_header *) &uvc_format_mjpg, +- (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, +- (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ /*(const struct uvc_descriptor_header *) &uvc_format_nv12, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_360p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_720p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_nv12_1080p, ++ //(const struct uvc_descriptor_header *) &uvc_format_mjpg, ++ //(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p,*/ ++ (const struct uvc_descriptor_header *) &uvc_format_h264, ++ (const struct uvc_descriptor_header *) &uvc_frame_h264_360p, ++ /*(const struct uvc_descriptor_header *) &uvc_frame_h264_720p, ++ //(const struct uvc_descriptor_header *) &uvc_frame_h264_1080p,*/ + (const struct uvc_descriptor_header *) &uvc_color_matching, + NULL, + }; + ++#define MAX_FRAME_DESCRIPTORS_NUM 10 ++#define MAX_FRAME_INTERVAL_NUM 5 ++struct uvc_frm_mjpg_info { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ __u8 bFrameIndex; ++ __u8 bmCapabilities; ++ __u16 wWidth; ++ __u16 wHeight; ++ __u32 dwMinBitRate; ++ __u32 dwMaxBitRate; ++ __u32 dwMaxVideoFrameBufferSize; ++ __u32 dwDefaultFrameInterval; ++ __u8 bFrameIntervalType; ++ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM]; ++} __packed; ++ ++ ++struct uvc_frm_yuv_info { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ __u8 bFrameIndex; ++ __u8 bmCapabilities; ++ __u16 wWidth; ++ __u16 wHeight; ++ __u32 dwMinBitRate; ++ __u32 dwMaxBitRate; ++ __u32 dwMaxVideoFrameBufferSize; ++ __u32 dwDefaultFrameInterval; ++ __u8 bFrameIntervalType; ++ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM]; ++} __packed; ++ ++ ++ ++struct uvc_frm_h264_info { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ __u8 bFrameIndex; ++ __u8 bmCapabilities; ++ __u16 wWidth; ++ __u16 wHeight; ++ __u32 dwMinBitRate; ++ __u32 dwMaxBitRate; ++ __u32 dwDefaultFrameInterval; ++ __u8 bFrameIntervalType; ++ __u32 dwBytesPerLine; ++ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM]; ++} __packed; ++ ++ ++struct uvc_frame_info { ++ unsigned int width; ++ unsigned int height; ++ unsigned int intervals[8]; ++}; ++ ++struct uvc_format_info { ++ unsigned int fcc; ++ const struct uvc_frame_info *frames; ++}; ++ ++ ++struct uvc_fmt_array_info { ++ unsigned int yuv_type; ++ ++ unsigned int fmt_num; ++ struct uvc_format_info *pFmts; ++ ++ unsigned int fmt2_num; ++ struct uvc_format_info *pFmts2; ++ ++}; ++ ++ ++ ++ ++struct uvc_fmt_array_data { ++ struct UVC_INPUT_HEADER_DESCRIPTOR(1, 1) uvc_input_header; ++ struct uvc_format_uncompressed uvc_format_nv12; ++ struct uvc_format_mjpeg uvc_format_mjpg; ++ struct uvc_format_frameBased uvc_format_h264; ++ ++ struct uvc_frm_yuv_info yuv_frames[MAX_FRAME_DESCRIPTORS_NUM]; ++ struct uvc_frm_mjpg_info mjpg_frames[MAX_FRAME_DESCRIPTORS_NUM]; ++ struct uvc_frm_h264_info h264_frames[MAX_FRAME_DESCRIPTORS_NUM]; ++ struct uvc_descriptor_header *uvc_streaming_data[MAX_FRAME_DESCRIPTORS_NUM*4]; ++ ++ int fmt_num; ++}; ++ ++static struct uvc_fmt_array_data uvc_fmt_array[2]; ++static struct uvc_fmt_array_data *pCurFmtArray; ++ ++ ++static int uvc_stream_idx; ++static int uvc_fmt_idx = 1; ++ ++ ++int get_frame_array_num(const struct uvc_frame_info *pFrms) ++{ ++ const struct uvc_frame_info *pFrmData = pFrms; ++ int num = 0; ++ while (1) { ++ if (pFrmData->width == 0) ++ break; ++ num++; ++ pFrmData++; ++ } ++ ++ if (num > MAX_FRAME_DESCRIPTORS_NUM) ++ num = MAX_FRAME_DESCRIPTORS_NUM; ++ ++ return num; ++} ++ ++ ++int get_frame_intervals_num(const struct uvc_frame_info *pFrms) ++{ ++ const struct uvc_frame_info *pFrmData = pFrms; ++ int num = 0; ++ ++ while (1) { ++ if (pFrmData->intervals[num] == 0) ++ break; ++ num++; ++ } ++ ++ if (num > MAX_FRAME_INTERVAL_NUM) ++ num = MAX_FRAME_INTERVAL_NUM; ++ ++ return num; ++} ++ ++ ++static void ++gen_yuv_frame_data(struct uvc_frm_yuv_info *pYuv, ++ int idx, ++ const struct uvc_frame_info *pFrm) ++{ ++ int i; ++ int num = get_frame_intervals_num(pFrm); ++ ++ pYuv->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(num); ++ pYuv->bDescriptorType = USB_DT_CS_INTERFACE; ++ pYuv->bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED; ++ pYuv->bFrameIndex = idx; ++ pYuv->bmCapabilities = 0; ++ pYuv->wWidth = cpu_to_le16(pFrm->width); ++ pYuv->wHeight = cpu_to_le16(pFrm->height); ++ pYuv->dwMinBitRate = cpu_to_le32(18432000); ++ pYuv->dwMaxBitRate = cpu_to_le32(55296000); ++ pYuv->dwMaxVideoFrameBufferSize = cpu_to_le32(471040); ++ pYuv->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]); ++ ++ pYuv->bFrameIntervalType = num; ++ for (i = 0; i < num; i++) ++ pYuv->dwFrameInterval[i] = ++ cpu_to_le32(pFrm->intervals[i]); ++ ++} ++ ++ ++static void ++gen_mjpg_frame_data(struct uvc_frm_mjpg_info *pMjpg, ++ int idx, ++ const struct uvc_frame_info *pFrm) ++{ ++ int i; ++ int num = get_frame_intervals_num(pFrm); ++ ++ pMjpg->bLength = UVC_DT_FRAME_MJPEG_SIZE(num); ++ pMjpg->bDescriptorType = USB_DT_CS_INTERFACE; ++ pMjpg->bDescriptorSubType = UVC_VS_FRAME_MJPEG; ++ pMjpg->bFrameIndex = idx; ++ pMjpg->bmCapabilities = 0; ++ pMjpg->wWidth = cpu_to_le16(pFrm->width); ++ pMjpg->wHeight = cpu_to_le16(pFrm->height); ++ pMjpg->dwMinBitRate = cpu_to_le32(18432000); ++ pMjpg->dwMaxBitRate = cpu_to_le32(55296000); ++ pMjpg->dwMaxVideoFrameBufferSize = cpu_to_le32(460800); ++ pMjpg->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]); ++ ++ ++ pMjpg->bFrameIntervalType = num; ++ for (i = 0; i < num; i++) ++ pMjpg->dwFrameInterval[i] = ++ cpu_to_le32(pFrm->intervals[i]); ++ ++} ++ ++static void gen_h264_frame_data(struct uvc_frm_h264_info *pH264, ++ int idx, ++ const struct uvc_frame_info *pFrm) ++{ ++ int i; ++ int num = get_frame_intervals_num(pFrm); ++ ++ pH264->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(num); ++ pH264->bDescriptorType = USB_DT_CS_INTERFACE; ++ pH264->bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED; ++ pH264->bFrameIndex = idx; ++ pH264->bmCapabilities = 0; ++ pH264->wWidth = cpu_to_le16(pFrm->width); ++ pH264->wHeight = cpu_to_le16(pFrm->height); ++ pH264->dwMinBitRate = cpu_to_le32(18432000); ++ pH264->dwMaxBitRate = cpu_to_le32(55296000); ++ pH264->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]); ++ pH264->dwBytesPerLine = 0; ++ ++ pH264->bFrameIntervalType = num; ++ for (i = 0; i < num; i++) ++ pH264->dwFrameInterval[i] = cpu_to_le32(pFrm->intervals[i]); ++ ++} ++ ++ ++void uvc_stream_append_data(void *data) ++{ ++ pCurFmtArray->uvc_streaming_data[uvc_stream_idx++] = ++ (struct uvc_descriptor_header *)data; ++} ++ ++void deal_frms_array(unsigned int fcc, const struct uvc_frame_info *pFrms) ++{ ++ ++ int frm_num = get_frame_array_num(pFrms); ++ const struct uvc_frame_info *pFrmData = pFrms; ++ int i; ++ ++ if (frm_num <= 0) ++ return; ++ ++ ++ switch (fcc) { ++ case V4L2_PIX_FMT_NV12: ++ uvc_stream_append_data(&pCurFmtArray->uvc_format_nv12); ++ pCurFmtArray->uvc_format_nv12.bFormatIndex = uvc_fmt_idx++; ++ pCurFmtArray->uvc_format_nv12.bNumFrameDescriptors = frm_num; ++ for (i = 0; i < frm_num; i++) { ++ gen_yuv_frame_data(&pCurFmtArray->yuv_frames[i], ++ i+1, pFrmData); ++ uvc_stream_append_data(&pCurFmtArray->yuv_frames[i]); ++ pFrmData++; ++ } ++ break; ++ ++ case V4L2_PIX_FMT_MJPEG: ++ uvc_stream_append_data(&pCurFmtArray->uvc_format_mjpg); ++ pCurFmtArray->uvc_format_mjpg.bFormatIndex = uvc_fmt_idx++; ++ pCurFmtArray->uvc_format_mjpg.bNumFrameDescriptors = frm_num; ++ for (i = 0; i < frm_num; i++) { ++ gen_mjpg_frame_data(&pCurFmtArray->mjpg_frames[i], ++ i+1, pFrmData); ++ uvc_stream_append_data(&pCurFmtArray->mjpg_frames[i]); ++ pFrmData++; ++ } ++ break; ++ ++ case V4L2_PIX_FMT_H264: ++ uvc_stream_append_data(&pCurFmtArray->uvc_format_h264); ++ pCurFmtArray->uvc_format_h264.bFormatIndex = uvc_fmt_idx++; ++ pCurFmtArray->uvc_format_h264.bNumFrameDescriptors = frm_num; ++ for (i = 0; i < frm_num; i++) { ++ gen_h264_frame_data(&pCurFmtArray->h264_frames[i], ++ i+1, pFrmData); ++ uvc_stream_append_data(&pCurFmtArray->h264_frames[i]); ++ pFrmData++; ++ } ++ break; ++ } ++} ++ ++ ++/*void set_yuv_bpp(int bpp);*/ ++static __u8 nv12Format[16] = { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, ++ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; ++ ++static __u8 yuy2Format[16] = { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, ++ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}; ++ ++ ++ ++void gen_uvc_fmt_array(int id, struct uvc_format_info *fmt, int fmt_num) ++{ ++ struct uvc_format_info *pFmtData = fmt; ++ unsigned int i; ++ ++ uvc_stream_idx = 0; ++ uvc_fmt_idx = 1; ++ ++ pCurFmtArray = &uvc_fmt_array[id&0x01]; ++ pCurFmtArray->fmt_num = fmt_num; ++ memcpy(&pCurFmtArray->uvc_input_header, &uvc_input_header, ++ sizeof(uvc_input_header)); ++ memcpy(&pCurFmtArray->uvc_format_nv12, &uvc_format_nv12, ++ sizeof(uvc_format_nv12)); ++ memcpy(&pCurFmtArray->uvc_format_mjpg, &uvc_format_mjpg, ++ sizeof(uvc_format_mjpg)); ++ memcpy(&pCurFmtArray->uvc_format_h264, &uvc_format_h264, ++ sizeof(uvc_format_h264)); ++ ++ uvc_stream_append_data((void *)&pCurFmtArray->uvc_input_header); ++ ++ ++ for (i = 0; i < fmt_num; i++) { ++ deal_frms_array(pFmtData->fcc, pFmtData->frames); ++ pFmtData++; ++ } ++ /*uvc_stream_append_data((void*)&uvc_still_image);*/ ++ uvc_stream_append_data((void *)&uvc_color_matching); ++ uvc_stream_append_data(NULL); ++} ++ ++void gen_stream_descriptor_array(struct uvc_fmt_array_info *pFai) ++{ ++ switch (pFai->yuv_type) { ++ case YUV_YUY2: ++ set_yuv_bpp(16); ++ memcpy(uvc_format_nv12.guidFormat, yuy2Format, ++ sizeof(yuy2Format)); ++ ++ uvc_format_nv12.bBitsPerPixel = 16; ++ break; ++ ++ case YUV_NV12: ++ default: ++ set_yuv_bpp(12); ++ memcpy(uvc_format_nv12.guidFormat, ++ nv12Format, ++ sizeof(nv12Format)); ++ uvc_format_nv12.bBitsPerPixel = 12; ++ break; ++ } ++ ++ gen_uvc_fmt_array(0, pFai->pFmts, pFai->fmt_num); ++ gen_uvc_fmt_array(1, pFai->pFmts2, pFai->fmt2_num); ++} ++ ++static struct uvc_descriptor_header *uvc_streaming_test[] = { ++ (struct uvc_descriptor_header *) &uvc_input_header, ++ /*(const struct uvc_descriptor_header *) &uvc_format_mjpg_fm1, ++ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,*/ ++ (struct uvc_descriptor_header *) &uvc_format_h264, ++ (struct uvc_descriptor_header *) &uvc_frame_h264_360p, ++ (struct uvc_descriptor_header *) &uvc_color_matching, ++ NULL, ++}; ++ ++ ++void change_usb_support_fmt(struct uvc_device *uvc, void *arg) ++{ ++ struct usb_function *f; ++ if (NULL != arg) { ++ gen_stream_descriptor_array(arg); ++ uvc->comm->desc.fs_streaming = ++ uvc_fmt_array[0].uvc_streaming_data; ++ uvc->comm->desc.hs_streaming = ++ uvc_fmt_array[0].uvc_streaming_data; ++ ++#ifdef UVC_DOUBLE_STREAM ++ ++ if (uvc_fmt_array[1].fmt_num > 0) { ++ uvc->comm->desc.fs_streaming2 = ++ uvc_fmt_array[1].uvc_streaming_data; ++ uvc->comm->desc.hs_streaming2 = ++ uvc_fmt_array[1].uvc_streaming_data; ++ uvc_control_header.bLength = UVC_DT_HEADER_SIZE(2); ++ } else { ++ uvc->comm->desc.fs_streaming2 = NULL; ++ uvc->comm->desc.hs_streaming2 = NULL; ++ } ++#else ++ ++ uvc->comm->desc.fs_streaming2 = NULL; ++ uvc->comm->desc.hs_streaming2 = NULL; ++ ++ ++#endif ++ } else { ++ return; ++ uvc->comm->desc.fs_streaming = uvc_streaming_test; ++ uvc->comm->desc.hs_streaming = uvc_streaming_test; ++ ++ uvc->comm->desc.fs_streaming2 = uvc_streaming_test; ++ uvc->comm->desc.hs_streaming2 = uvc_streaming_test; ++ } ++ ++ ++ f = &uvc->comm->func; ++ ++ ++ kfree(f->descriptors); ++ kfree(f->hs_descriptors); ++ ++ /* Copy descriptors. */ ++ f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); ++ ++ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); ++} ++ + /* -------------------------------------------------------------------------- + * USB configuration + */ + ++ ++/*extern int uac_bind_config(struct usb_configuration *c);*/ ++ + static int __init + webcam_config_bind(struct usb_configuration *c) + { +- return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, +- uvc_hs_streaming_cls); ++ int ret; ++#ifdef ENABLE_UVC ++ ret = uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, ++ uvc_hs_streaming_cls); ++#endif ++ ++#ifdef ENABLE_UAC ++ ret = uac_bind_config(c); ++#endif ++ return ret; + } + + static struct usb_configuration webcam_config_driver = { +@@ -337,24 +1025,26 @@ webcam_bind(struct usb_composite_dev *cdev) + /* Allocate string descriptor numbers ... note that string contents + * can be overridden by the composite_dev glue. + */ +- if ((ret = usb_string_id(cdev)) < 0) ++ ret = usb_string_id(cdev); ++ if (ret < 0) + goto error; + webcam_strings[STRING_MANUFACTURER_IDX].id = ret; + webcam_device_descriptor.iManufacturer = ret; +- +- if ((ret = usb_string_id(cdev)) < 0) ++ ret = usb_string_id(cdev); ++ if (ret < 0) + goto error; + webcam_strings[STRING_PRODUCT_IDX].id = ret; + webcam_device_descriptor.iProduct = ret; +- +- if ((ret = usb_string_id(cdev)) < 0) ++ ret = usb_string_id(cdev); ++ if (ret < 0) + goto error; + webcam_strings[STRING_DESCRIPTION_IDX].id = ret; + webcam_config_driver.iConfiguration = ret; + + /* Register our configuration. */ +- if ((ret = usb_add_config(cdev, &webcam_config_driver, +- webcam_config_bind)) < 0) ++ ret = usb_add_config(cdev, &webcam_config_driver, \ ++ webcam_config_bind); ++ if (ret < 0) + goto error; + + INFO(cdev, "Webcam Video Gadget\n"); +@@ -396,3 +1086,5 @@ MODULE_DESCRIPTION("Webcam Video Gadget"); + MODULE_LICENSE("GPL"); + MODULE_VERSION("0.1.0"); + ++#endif ++ +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index ab085f12..bc58e0db 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -574,7 +574,48 @@ config USB_OCTEON_OHCI + Enable support for the Octeon II SOC's on-chip OHCI + controller. It is needed for low-speed USB 1.0 device + support. All CN6XXX based chips with USB are supported. ++ ++config USB_FH_OTG ++ tristate "FH OTG support" ++ depends on USB ++ default y ++ help ++ FULLHAN USB SUPPORT ++ Be the OTG, host or device mode + ++choice ++ prompt "Choose mode" ++ depends on USB_FH_OTG ++ default FH_HOST_ONLY ++ help ++ Select one ++config FH_OTG ++ depends on USB_FH_OTG && MACH_FH8856 ++ bool "OTG mode" ++ ++config FH_HOST_ONLY ++ bool "Host only mode" ++ ++config FH_DEVICE_ONLY ++ bool "Device only mode" ++endchoice ++ + config USB_OCTEON2_COMMON + bool + default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI ++ ++config USB_S3C_OTG_HOST ++ tristate "S3C USB OTG Host support" ++ depends on USB ++ help ++ Samsung's S3C64XX processors include high speed USB OTG2.0 ++ controller. It has 15 configurable endpoints, as well as ++ endpoint zero (for control transfers). ++ ++ This driver support only OTG Host role. If you want to use ++ OTG Device role, select USB Gadget support and S3C OTG Device. ++ ++ Say "y" to link the driver statically, or "m" to build a ++ dynamically linked module called "s3c_otg_hcd" and force all ++ drivers to also be dynamically linked. ++ +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index 624a362f..afc1f79e 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -17,7 +17,7 @@ xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o + obj-$(CONFIG_USB_WHCI_HCD) += whci/ + + obj-$(CONFIG_PCI) += pci-quirks.o +- ++obj-$(CONFIG_USB_FH_OTG) += fh_otg/ + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o + obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o + obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o +diff --git a/drivers/usb/host/fh_otg/Kconfig b/drivers/usb/host/fh_otg/Kconfig +new file mode 100644 +index 00000000..e9285782 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/Kconfig +@@ -0,0 +1 @@ ++source "drivers/usb/host/fh_otg/fh_otg/Kconfig" +diff --git a/drivers/usb/host/fh_otg/Makefile b/drivers/usb/host/fh_otg/Makefile +new file mode 100644 +index 00000000..11ecd15e +--- /dev/null ++++ b/drivers/usb/host/fh_otg/Makefile +@@ -0,0 +1,7 @@ ++# ++#Makefile for the kernel USB host drivers. ++# ++ ++# Object files in subdirectories ++ ++obj-$(CONFIG_USB_FH_OTG) += fh_common_port/ fh_otg/ +\ No newline at end of file +diff --git a/drivers/usb/host/fh_otg/fh_common_port/Makefile b/drivers/usb/host/fh_otg/fh_common_port/Makefile +new file mode 100644 +index 00000000..a4b0accd +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/Makefile +@@ -0,0 +1,49 @@ ++# ++# Makefile for FH_common library ++# ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DFH_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DFH_DEBUG_REGS ++#EXTRA_CFLAGS += -DFH_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DFH_LIBMODULE ++EXTRA_CFLAGS += -DFH_CCLIB ++EXTRA_CFLAGS += -DFH_CRYPTOLIB ++EXTRA_CFLAGS += -DFH_NOTIFYLIB ++EXTRA_CFLAGS += -DFH_UTFLIB ++ ++obj-$(CONFIG_USB_FH_OTG) := fh_common_port_lib.o ++fh_common_port_lib-objs := fh_cc.o fh_modpow.o fh_dh.o \ ++ fh_crypto.o fh_notifier.o \ ++ fh_common_linux.o fh_mem.o ++ ++else ++ ++ifeq ($(KDIR),) ++$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/Makefile.fbsd b/drivers/usb/host/fh_otg/fh_common_port/Makefile.fbsd +new file mode 100644 +index 00000000..c78002c4 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/Makefile.fbsd +@@ -0,0 +1,17 @@ ++CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include ++CFLAGS += -DFH_FREEBSD ++CFLAGS += -DDEBUG ++#CFLAGS += -DFH_DEBUG_REGS ++#CFLAGS += -DFH_DEBUG_MEMORY ++ ++#CFLAGS += -DFH_LIBMODULE ++#CFLAGS += -DFH_CCLIB ++#CFLAGS += -DFH_CRYPTOLIB ++#CFLAGS += -DFH_NOTIFYLIB ++#CFLAGS += -DFH_UTFLIB ++ ++KMOD = fh_common_port_lib ++SRCS = fh_cc.c fh_modpow.c fh_dh.c fh_crypto.c fh_notifier.c \ ++ fh_common_fbsd.c fh_mem.c ++ ++.include <bsd.kmod.mk> +diff --git a/drivers/usb/host/fh_otg/fh_common_port/Makefile.linux b/drivers/usb/host/fh_otg/fh_common_port/Makefile.linux +new file mode 100644 +index 00000000..4dc490cd +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/Makefile.linux +@@ -0,0 +1,49 @@ ++# ++# Makefile for FH_common library ++# ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DFH_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DFH_DEBUG_REGS ++#EXTRA_CFLAGS += -DFH_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DFH_LIBMODULE ++EXTRA_CFLAGS += -DFH_CCLIB ++EXTRA_CFLAGS += -DFH_CRYPTOLIB ++EXTRA_CFLAGS += -DFH_NOTIFYLIB ++EXTRA_CFLAGS += -DFH_UTFLIB ++ ++obj-m := fh_common_port_lib.o ++fh_common_port_lib-objs := fh_cc.o fh_modpow.o fh_dh.o \ ++ fh_crypto.o fh_notifier.o \ ++ fh_common_linux.o fh_mem.o ++ ++else ++ ++ifeq ($(KDIR),) ++$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/changes.txt b/drivers/usb/host/fh_otg/fh_common_port/changes.txt +new file mode 100644 +index 00000000..f6839f92 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/changes.txt +@@ -0,0 +1,174 @@ ++ ++dwc_read_reg32() and friends now take an additional parameter, a pointer to an ++IO context struct. The IO context struct should live in an os-dependent struct ++in your driver. As an example, the dwc_usb3 driver has an os-dependent struct ++named 'os_dep' embedded in the main device struct. So there these calls look ++like this: ++ ++ dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); ++ ++ dwc_write_reg32(&usb3_dev->os_dep.ioctx, ++ &pcd->dev_global_regs->dcfg, 0); ++ ++Note that for the existing Linux driver ports, it is not necessary to actually ++define the 'ioctx' member in the os-dependent struct. Since Linux does not ++require an IO context, its macros for dwc_read_reg32() and friends do not ++use the context pointer, so it is optimized away by the compiler. But it is ++necessary to add the pointer parameter to all of the call sites, to be ready ++for any future ports (such as FreeBSD) which do require an IO context. ++ ++ ++Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now ++take an additional parameter, a pointer to a memory context. Examples: ++ ++ addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); ++ ++ dwc_free(&usb3_dev->os_dep.memctx, addr); ++ ++Again, for the Linux ports, it is not necessary to actually define the memctx ++member, but it is necessary to add the pointer parameter to all of the call ++sites. ++ ++ ++Same for dwc_dma_alloc() and dwc_dma_free(). Examples: ++ ++ virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); ++ ++ dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); ++ ++ ++Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: ++ ++ mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); ++ ++ dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); ++ ++ ++Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: ++ ++ lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); ++ ++ dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); ++ ++ ++Same for dwc_timer_alloc(). Example: ++ ++ timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", ++ cb_func, cb_data); ++ ++ ++Same for dwc_waitq_alloc(). Example: ++ ++ waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); ++ ++ ++Same for dwc_thread_run(). Example: ++ ++ thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, ++ "dwc_usb3_thd1", data); ++ ++ ++Same for dwc_workq_alloc(). Example: ++ ++ workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); ++ ++ ++Same for dwc_task_alloc(). Example: ++ ++ task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", ++ cb_func, cb_data); ++ ++ ++In addition to the context pointer additions, a few core functions have had ++other changes made to their parameters: ++ ++The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() ++has been changed from a uint64_t to a dwc_irqflags_t. ++ ++dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the ++FreeBSD equivalent of that function requires it. ++ ++And, in addition to the context pointer, dwc_task_alloc() also adds a ++'char *name' parameter, to be consistent with dwc_thread_run() and ++dwc_workq_alloc(), and because the FreeBSD equivalent of that function ++requires a unique name. ++ ++ ++Here is a complete list of the core functions that now take a pointer to a ++context as their first parameter: ++ ++ dwc_read_reg32 ++ dwc_read_reg64 ++ dwc_write_reg32 ++ dwc_write_reg64 ++ dwc_modify_reg32 ++ dwc_modify_reg64 ++ dwc_alloc ++ dwc_alloc_atomic ++ dwc_strdup ++ dwc_free ++ dwc_dma_alloc ++ dwc_dma_free ++ dwc_mutex_alloc ++ dwc_mutex_free ++ dwc_spinlock_alloc ++ dwc_spinlock_free ++ dwc_timer_alloc ++ dwc_waitq_alloc ++ dwc_thread_run ++ dwc_workq_alloc ++ dwc_task_alloc Also adds a 'char *name' as its 2nd parameter ++ ++And here are the core functions that have other changes to their parameters: ++ ++ dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' ++ dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' ++ dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter ++ ++ ++ ++The changes to the core functions also require some of the other library ++functions to change: ++ ++ dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' ++ (for memory allocation) as the 1st param and a 'void *mtxctx' ++ (for mutex allocation) as the 2nd param. ++ ++ dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), ++ dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_modpow() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_alloc_notification_manager() now takes a 'void *memctx' as the ++ 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures or work queue fails. ++ ++ dwc_register_notifier() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures fails. ++ ++ ++ ++Other miscellaneous changes: ++ ++The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to ++DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. ++ ++The following #define's have been added to allow selectively compiling library ++features: ++ ++ DWC_CCLIB ++ DWC_CRYPTOLIB ++ DWC_NOTIFYLIB ++ DWC_UTFLIB ++ ++A DWC_LIBMODULE #define has also been added. If this is not defined, then the ++module code in dwc_common_linux.c is not compiled in. This allows linking the ++library code directly into a driver module, instead of as a standalone module. +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_cc.c b/drivers/usb/host/fh_otg/fh_common_port/fh_cc.c +new file mode 100644 +index 00000000..ca1dc878 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_cc.c +@@ -0,0 +1,532 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_cc.c $ ++ * $Revision: #4 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621692 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifdef FH_CCLIB ++ ++#include "fh_cc.h" ++ ++typedef struct fh_cc ++{ ++ uint32_t uid; ++ uint8_t chid[16]; ++ uint8_t cdid[16]; ++ uint8_t ck[16]; ++ uint8_t *name; ++ uint8_t length; ++ FH_CIRCLEQ_ENTRY(fh_cc) list_entry; ++} fh_cc_t; ++ ++FH_CIRCLEQ_HEAD(context_list, fh_cc); ++ ++/** The main structure for CC management. */ ++struct fh_cc_if ++{ ++ fh_mutex_t *mutex; ++ char *filename; ++ ++ unsigned is_host:1; ++ ++ fh_notifier_t *notifier; ++ ++ struct context_list list; ++}; ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ FH_PRINTF("%s: ", name); ++ for (i=0; i<len; i++) { ++ FH_PRINTF("%02x ", bytes[i]); ++ } ++ FH_PRINTF("\n"); ++} ++#else ++#define dump_bytes(x...) ++#endif ++ ++static fh_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length) ++{ ++ fh_cc_t *cc = fh_alloc(mem_ctx, sizeof(fh_cc_t)); ++ if (!cc) { ++ return NULL; ++ } ++ FH_MEMSET(cc, 0, sizeof(fh_cc_t)); ++ ++ if (name) { ++ cc->length = length; ++ cc->name = fh_alloc(mem_ctx, length); ++ if (!cc->name) { ++ fh_free(mem_ctx, cc); ++ return NULL; ++ } ++ ++ FH_MEMCPY(cc->name, name, length); ++ } ++ ++ return cc; ++} ++ ++static void free_cc(void *mem_ctx, fh_cc_t *cc) ++{ ++ if (cc->name) { ++ fh_free(mem_ctx, cc->name); ++ } ++ fh_free(mem_ctx, cc); ++} ++ ++static uint32_t next_uid(fh_cc_if_t *cc_if) ++{ ++ uint32_t uid = 0; ++ fh_cc_t *cc; ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid > uid) { ++ uid = cc->uid; ++ } ++ } ++ ++ if (uid == 0) { ++ uid = 255; ++ } ++ ++ return uid + 1; ++} ++ ++static fh_cc_t *cc_find(fh_cc_if_t *cc_if, uint32_t uid) ++{ ++ fh_cc_t *cc; ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid == uid) { ++ return cc; ++ } ++ } ++ return NULL; ++} ++ ++static unsigned int cc_data_size(fh_cc_if_t *cc_if) ++{ ++ unsigned int size = 0; ++ fh_cc_t *cc; ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ size += (48 + 1); ++ if (cc->name) { ++ size += cc->length; ++ } ++ } ++ return size; ++} ++ ++static uint32_t cc_match_chid(fh_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ fh_cc_t *cc; ++ ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (FH_MEMCMP(cc->chid, chid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++static uint32_t cc_match_cdid(fh_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ fh_cc_t *cc; ++ ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (FH_MEMCMP(cc->cdid, cdid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++ ++/* Internal cc_add */ ++static int32_t cc_add(void *mem_ctx, fh_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ fh_cc_t *cc; ++ uint32_t uid; ++ ++ if (cc_if->is_host) { ++ uid = cc_match_cdid(cc_if, cdid); ++ } ++ else { ++ uid = cc_match_chid(cc_if, chid); ++ } ++ ++ if (uid) { ++ FH_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); ++ cc = cc_find(cc_if, uid); ++ } ++ else { ++ cc = alloc_cc(mem_ctx, name, length); ++ cc->uid = next_uid(cc_if); ++ FH_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); ++ } ++ ++ FH_MEMCPY(&(cc->chid[0]), chid, 16); ++ FH_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ FH_MEMCPY(&(cc->ck[0]), ck, 16); ++ ++ FH_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); ++ dump_bytes("CHID", cc->chid, 16); ++ dump_bytes("CDID", cc->cdid, 16); ++ dump_bytes("CK", cc->ck, 16); ++ return cc->uid; ++} ++ ++/* Internal cc_clear */ ++static void cc_clear(void *mem_ctx, fh_cc_if_t *cc_if) ++{ ++ while (!FH_CIRCLEQ_EMPTY(&cc_if->list)) { ++ fh_cc_t *cc = FH_CIRCLEQ_FIRST(&cc_if->list); ++ FH_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ free_cc(mem_ctx, cc); ++ } ++} ++ ++fh_cc_if_t *fh_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ fh_notifier_t *notifier, unsigned is_host) ++{ ++ fh_cc_if_t *cc_if = NULL; ++ ++ /* Allocate a common_cc_if structure */ ++ cc_if = fh_alloc(mem_ctx, sizeof(fh_cc_if_t)); ++ ++ if (!cc_if) ++ return NULL; ++ ++#if (defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ FH_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); ++#else ++ cc_if->mutex = fh_mutex_alloc(mtx_ctx); ++#endif ++ if (!cc_if->mutex) { ++ fh_free(mem_ctx, cc_if); ++ return NULL; ++ } ++ ++ FH_CIRCLEQ_INIT(&cc_if->list); ++ cc_if->is_host = is_host; ++ cc_if->notifier = notifier; ++ return cc_if; ++} ++ ++void fh_cc_if_free(void *mem_ctx, void *mtx_ctx, fh_cc_if_t *cc_if) ++{ ++#if (defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ FH_MUTEX_FREE(cc_if->mutex); ++#else ++ fh_mutex_free(mtx_ctx, cc_if->mutex); ++#endif ++ cc_clear(mem_ctx, cc_if); ++ fh_free(mem_ctx, cc_if); ++} ++ ++static void cc_changed(fh_cc_if_t *cc_if) ++{ ++ if (cc_if->notifier) { ++ fh_notify(cc_if->notifier, FH_CC_LIST_CHANGED_NOTIFICATION, cc_if); ++ } ++} ++ ++void fh_cc_clear(void *mem_ctx, fh_cc_if_t *cc_if) ++{ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++} ++ ++int32_t fh_cc_add(void *mem_ctx, fh_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ uint32_t uid; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++ ++ return uid; ++} ++ ++void fh_cc_change(void *mem_ctx, fh_cc_if_t *cc_if, int32_t id, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ fh_cc_t* cc; ++ ++ FH_DEBUG("Change connection context %d", id); ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ FH_ERROR("Uid %d not found in cc list\n", id); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ if (chid) { ++ FH_MEMCPY(&(cc->chid[0]), chid, 16); ++ } ++ if (cdid) { ++ FH_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ } ++ if (ck) { ++ FH_MEMCPY(&(cc->ck[0]), ck, 16); ++ } ++ ++ if (name) { ++ if (cc->name) { ++ fh_free(mem_ctx, cc->name); ++ } ++ cc->name = fh_alloc(mem_ctx, length); ++ if (!cc->name) { ++ FH_ERROR("Out of memory in fh_cc_change()\n"); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ cc->length = length; ++ FH_MEMCPY(cc->name, name, length); ++ } ++ ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++ ++ FH_DEBUG("Changed connection context id=%d\n", id); ++ dump_bytes("New CHID", cc->chid, 16); ++ dump_bytes("New CDID", cc->cdid, 16); ++ dump_bytes("New CK", cc->ck, 16); ++} ++ ++void fh_cc_remove(void *mem_ctx, fh_cc_if_t *cc_if, int32_t id) ++{ ++ fh_cc_t *cc; ++ ++ FH_DEBUG("Removing connection context %d", id); ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ FH_ERROR("Uid %d not found in cc list\n", id); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ FH_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ free_cc(mem_ctx, cc); ++ ++ cc_changed(cc_if); ++} ++ ++uint8_t *fh_cc_data_for_save(void *mem_ctx, fh_cc_if_t *cc_if, unsigned int *length) ++{ ++ uint8_t *buf, *x; ++ uint8_t zero = 0; ++ fh_cc_t *cc; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ *length = cc_data_size(cc_if); ++ if (!(*length)) { ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ FH_DEBUG("Creating data for saving (length=%d)", *length); ++ ++ buf = fh_alloc(mem_ctx, *length); ++ if (!buf) { ++ *length = 0; ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ x = buf; ++ FH_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ FH_MEMCPY(x, cc->chid, 16); ++ x += 16; ++ FH_MEMCPY(x, cc->cdid, 16); ++ x += 16; ++ FH_MEMCPY(x, cc->ck, 16); ++ x += 16; ++ if (cc->name) { ++ FH_MEMCPY(x, &cc->length, 1); ++ x += 1; ++ FH_MEMCPY(x, cc->name, cc->length); ++ x += cc->length; ++ } ++ else { ++ FH_MEMCPY(x, &zero, 1); ++ x += 1; ++ } ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return buf; ++} ++ ++void fh_cc_restore_from_data(void *mem_ctx, fh_cc_if_t *cc_if, uint8_t *data, uint32_t length) ++{ ++ uint8_t name_length; ++ uint8_t *name; ++ uint8_t *chid; ++ uint8_t *cdid; ++ uint8_t *ck; ++ uint32_t i = 0; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ ++ while (i < length) { ++ chid = &data[i]; ++ i += 16; ++ cdid = &data[i]; ++ i += 16; ++ ck = &data[i]; ++ i += 16; ++ ++ name_length = data[i]; ++ i ++; ++ ++ if (name_length) { ++ name = &data[i]; ++ i += name_length; ++ } ++ else { ++ name = NULL; ++ } ++ ++ /* check to see if we haven't overflown the buffer */ ++ if (i > length) { ++ FH_ERROR("Data format error while attempting to load CCs " ++ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); ++ break; ++ } ++ ++ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++} ++ ++uint32_t fh_cc_match_chid(fh_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_chid(cc_if, chid); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++uint32_t fh_cc_match_cdid(fh_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_cdid(cc_if, cdid); ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++ ++uint8_t *fh_cc_ck(fh_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *ck = NULL; ++ fh_cc_t *cc; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ ck = cc->ck; ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return ck; ++ ++} ++ ++uint8_t *fh_cc_chid(fh_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ fh_cc_t *cc; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->chid; ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *fh_cc_cdid(fh_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ fh_cc_t *cc; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->cdid; ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *fh_cc_name(fh_cc_if_t *cc_if, int32_t id, uint8_t *length) ++{ ++ uint8_t *retval = NULL; ++ fh_cc_t *cc; ++ ++ FH_MUTEX_LOCK(cc_if->mutex); ++ *length = 0; ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ *length = cc->length; ++ retval = cc->name; ++ } ++ FH_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++#endif /* FH_CCLIB */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_cc.h b/drivers/usb/host/fh_otg/fh_common_port/fh_cc.h +new file mode 100644 +index 00000000..926229e9 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_cc.h +@@ -0,0 +1,225 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_cc.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifndef _FH_CC_H_ ++#define _FH_CC_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines the Context Context library. ++ * ++ * The main data structure is fh_cc_if_t which is returned by either the ++ * fh_cc_if_alloc function or returned by the module to the user via a provided ++ * function. The data structure is opaque and should only be manipulated via the ++ * functions provied in this API. ++ * ++ * It manages a list of connection contexts and operations can be performed to ++ * add, remove, query, search, and change, those contexts. Additionally, ++ * a fh_notifier_t object can be requested from the manager so that ++ * the user can be notified whenever the context list has changed. ++ */ ++ ++#include "fh_os.h" ++#include "fh_list.h" ++#include "fh_notifier.h" ++ ++ ++/* Notifications */ ++#define FH_CC_LIST_CHANGED_NOTIFICATION "FH_CC_LIST_CHANGED_NOTIFICATION" ++ ++struct fh_cc_if; ++typedef struct fh_cc_if fh_cc_if_t; ++ ++ ++/** @name Connection Context Operations */ ++/** @{ */ ++ ++/** This function allocates memory for a fh_cc_if_t structure, initializes ++ * fields to default values, and returns a pointer to the structure or NULL on ++ * error. */ ++extern fh_cc_if_t *fh_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ fh_notifier_t *notifier, unsigned is_host); ++ ++/** Frees the memory for the specified CC structure allocated from ++ * fh_cc_if_alloc(). */ ++extern void fh_cc_if_free(void *mem_ctx, void *mtx_ctx, fh_cc_if_t *cc_if); ++ ++/** Removes all contexts from the connection context list */ ++extern void fh_cc_clear(void *mem_ctx, fh_cc_if_t *cc_if); ++ ++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. ++ * If a CHID already exists, the CK and name are overwritten. Statistics are ++ * not overwritten. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. ++ * @param name An optional host friendly name as defined in the association model ++ * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name. ++ * @param length The length othe unicode string. ++ * @return A unique identifier used to refer to this context that is valid for ++ * as long as this context is still in the list. */ ++extern int32_t fh_cc_add(void *mem_ctx, fh_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, ++ uint8_t length); ++ ++/** Changes the CHID, CK, CDID, or Name values of a connection context in the ++ * list, preserving any accumulated statistics. This would typically be called ++ * if the host decideds to change the context with a SET_CONNECTION request. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL ++ * indicates no change. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL ++ * indicates no change. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. NULL ++ * indicates no change. ++ * @param name Host friendly name UTF16-LE. NULL indicates no change. ++ * @param length Length of name. */ ++extern void fh_cc_change(void *mem_ctx, fh_cc_if_t *cc_if, int32_t id, ++ uint8_t *chid, uint8_t *cdid, uint8_t *ck, ++ uint8_t *name, uint8_t length); ++ ++/** Remove the specified connection context. ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context to remove. */ ++extern void fh_cc_remove(void *mem_ctx, fh_cc_if_t *cc_if, int32_t id); ++ ++/** Get a binary block of data for the connection context list and attributes. ++ * This data can be used by the OS specific driver to save the connection ++ * context list into non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param length Return the length of the data buffer. ++ * @return A pointer to the data buffer. The memory for this buffer should be ++ * freed with FH_FREE() after use. */ ++extern uint8_t *fh_cc_data_for_save(void *mem_ctx, fh_cc_if_t *cc_if, ++ unsigned int *length); ++ ++/** Restore the connection context list from the binary data that was previously ++ * returned from a call to fh_cc_data_for_save. This can be used by the OS specific ++ * driver to load a connection context list from non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param data The data bytes as returned from fh_cc_data_for_save. ++ * @param length The length of the data. */ ++extern void fh_cc_restore_from_data(void *mem_ctx, fh_cc_if_t *cc_if, ++ uint8_t *data, unsigned int length); ++ ++/** Find the connection context from the specified CHID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the CHID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t fh_cc_match_chid(fh_cc_if_t *cc_if, uint8_t *chid); ++ ++/** Find the connection context from the specified CDID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param cdid A pointer to the CDID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t fh_cc_match_cdid(fh_cc_if_t *cc_if, uint8_t *cdid); ++ ++/** Retrieve the CK from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CK data. The memory does not need to be freed. */ ++extern uint8_t *fh_cc_ck(fh_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CHID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CHID data. The memory does not need to be freed. */ ++extern uint8_t *fh_cc_chid(fh_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CDID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CDID data. The memory does not need to be freed. */ ++extern uint8_t *fh_cc_cdid(fh_cc_if_t *cc_if, int32_t id); ++ ++extern uint8_t *fh_cc_name(fh_cc_if_t *cc_if, int32_t id, uint8_t *length); ++ ++/** Checks a buffer for non-zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is non-zero. */ ++static inline unsigned fh_assoc_is_not_zero_id(uint8_t *id) { ++ int i; ++ for (i=0; i<16; i++) { ++ if (id[i]) return 1; ++ } ++ return 0; ++} ++ ++/** Checks a buffer for zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is zero. */ ++static inline unsigned fh_assoc_is_zero_id(uint8_t *id) { ++ return !fh_assoc_is_not_zero_id(id); ++} ++ ++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into ++ * buffer. */ ++static inline int fh_print_id_string(char *buffer, uint8_t *id) { ++ char *ptr = buffer; ++ int i; ++ for (i=0; i<16; i++) { ++ ptr += FH_SPRINTF(ptr, "%02x", id[i]); ++ if (i < 15) { ++ ptr += FH_SPRINTF(ptr, " "); ++ } ++ } ++ return ptr - buffer; ++} ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_CC_H_ */ ++ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_common_fbsd.c b/drivers/usb/host/fh_otg/fh_common_port/fh_common_fbsd.c +new file mode 100644 +index 00000000..ef4b67bb +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_common_fbsd.c +@@ -0,0 +1,1308 @@ ++#include "fh_os.h" ++#include "fh_list.h" ++ ++#ifdef FH_CCLIB ++# include "fh_cc.h" ++#endif ++ ++#ifdef FH_CRYPTOLIB ++# include "fh_modpow.h" ++# include "fh_dh.h" ++# include "fh_crypto.h" ++#endif ++ ++#ifdef FH_NOTIFYLIB ++# include "fh_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the FreeBSD 7.0 kernel implementation of the FH platform library. */ ++ ++ ++/* MISC */ ++ ++void *FH_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *FH_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *FH_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ bcopy(src, dest, size); ++ return dest; ++} ++ ++int FH_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int FH_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int FH_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int FH_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *FH_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *FH_STRDUP(char const *str) ++{ ++ int len = FH_STRLEN(str) + 1; ++ char *new = FH_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ FH_MEMCPY(new, str, len); ++ return new; ++} ++ ++int FH_ATOI(char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int FH_ATOUI(char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef FH_UTFLIB ++/* From usbstring.c */ ++ ++int FH_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++#endif /* FH_UTFLIB */ ++ ++ ++/* fh_debug.h */ ++ ++fh_bool_t FH_IN_IRQ(void) ++{ ++// return in_irq(); ++ return 0; ++} ++ ++fh_bool_t FH_IN_BH(void) ++{ ++// return in_softirq(); ++ return 0; ++} ++ ++void FH_VPRINTF(char *format, va_list args) ++{ ++ vprintf(format, args); ++} ++ ++int FH_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void FH_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int FH_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int FH_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __FH_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __FH_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void FH_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++// BUG_ON(1); ??? ++} ++ ++#ifdef DEBUG ++void __FH_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* fh_mem.h */ ++ ++#if 0 ++fh_pool_t *FH_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (fh_pool_t *)pool; ++} ++ ++void FH_DMA_POOL_DESTROY(fh_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *FH_DMA_POOL_ALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); ++} ++ ++void *FH_DMA_POOL_ZALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = FH_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void FH_DMA_POOL_FREE(fh_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) ++{ ++ if (error) ++ return; ++ *(bus_addr_t *)arg = segs[0].ds_addr; ++} ++ ++void *__FH_DMA_ALLOC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr) ++{ ++ fh_dmactx_t *dma = (fh_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dma_tag_create( ++#if __FreeBSD_version >= 700000 ++ bus_get_dma_tag(dma->dev), /* parent */ ++#else ++ NULL, /* parent */ ++#endif ++ 4, 0, /* alignment, bounds */ ++ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ ++ BUS_SPACE_MAXADDR, /* highaddr */ ++ NULL, NULL, /* filter, filterarg */ ++ size, /* maxsize */ ++ 1, /* nsegments */ ++ size, /* maxsegsize */ ++ 0, /* flags */ ++ NULL, /* lockfunc */ ++ NULL, /* lockarg */ ++ &dma->dma_tag); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n", ++ __func__, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n", ++ __func__, (uintmax_t)size, error); ++ goto fail_1; ++ } ++ ++ dma->dma_paddr = 0; ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size, ++ dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT); ++ if (error || dma->dma_paddr == 0) { ++ device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n", ++ __func__, error); ++ goto fail_2; ++ } ++ ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_2: ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ bus_dma_tag_destroy(dma->dma_tag); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_tag = NULL; ++ ++ return NULL; ++} ++ ++void __FH_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, fh_dma_t dma_addr) ++{ ++ fh_dmactx_t *dma = (fh_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_tag == NULL) ++ return; ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ dma->dma_map = NULL; ++ } ++ ++ bus_dma_tag_destroy(dma->dma_tag); ++ dma->dma_tag = NULL; ++} ++ ++void *__FH_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__FH_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __FH_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef FH_CRYPTOLIB ++/* fh_crypto.h */ ++ ++void FH_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int FH_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ FH_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int FH_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int FH_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* FH_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t FH_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t FH_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t FH_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void FH_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void FH_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void FH_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void FH_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++fh_spinlock_t *FH_SPINLOCK_ALLOC(void) ++{ ++ struct mtx *sl = FH_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ FH_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ mtx_init(sl, "dw3spn", NULL, MTX_SPIN); ++ return (fh_spinlock_t *)sl; ++} ++ ++void FH_SPINLOCK_FREE(fh_spinlock_t *lock) ++{ ++ struct mtx *sl = (struct mtx *)lock; ++ ++ mtx_destroy(sl); ++ FH_FREE(sl); ++} ++ ++void FH_SPINLOCK(fh_spinlock_t *lock) ++{ ++ mtx_lock_spin((struct mtx *)lock); // ??? ++} ++ ++void FH_SPINUNLOCK(fh_spinlock_t *lock) ++{ ++ mtx_unlock_spin((struct mtx *)lock); // ??? ++} ++ ++void FH_SPINLOCK_IRQSAVE(fh_spinlock_t *lock, fh_irqflags_t *flags) ++{ ++ mtx_lock_spin((struct mtx *)lock); ++} ++ ++void FH_SPINUNLOCK_IRQRESTORE(fh_spinlock_t *lock, fh_irqflags_t flags) ++{ ++ mtx_unlock_spin((struct mtx *)lock); ++} ++ ++fh_mutex_t *FH_MUTEX_ALLOC(void) ++{ ++ struct mtx *m; ++ fh_mutex_t *mutex = (fh_mutex_t *)FH_ALLOC(sizeof(struct mtx)); ++ ++ if (!mutex) { ++ FH_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ m = (struct mtx *)mutex; ++ mtx_init(m, "dw3mtx", NULL, MTX_DEF); ++ return mutex; ++} ++ ++#if (defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void FH_MUTEX_FREE(fh_mutex_t *mutex) ++{ ++ mtx_destroy((struct mtx *)mutex); ++ FH_FREE(mutex); ++} ++#endif ++ ++void FH_MUTEX_LOCK(fh_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_lock(m); ++} ++ ++int FH_MUTEX_TRYLOCK(fh_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ return mtx_trylock(m); ++} ++ ++void FH_MUTEX_UNLOCK(fh_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void FH_UDELAY(uint32_t usecs) ++{ ++ DELAY(usecs); ++} ++ ++void FH_MDELAY(uint32_t msecs) ++{ ++ do { ++ DELAY(1000); ++ } while (--msecs); ++} ++ ++void FH_MSLEEP(uint32_t msecs) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ pause("dw3slp", tvtohz(&tv)); ++} ++ ++uint32_t FH_TIME(void) ++{ ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct fh_timer { ++ struct callout t; ++ char *name; ++ fh_spinlock_t *lock; ++ fh_timer_callback_t cb; ++ void *data; ++}; ++ ++fh_timer_t *FH_TIMER_ALLOC(char *name, fh_timer_callback_t cb, void *data) ++{ ++ fh_timer_t *t = FH_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ FH_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t, 1); ++ ++ t->name = FH_STRDUP(name); ++ if (!t->name) { ++ FH_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = FH_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ FH_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ FH_FREE(t->name); ++ no_name: ++ FH_FREE(t); ++ ++ return NULL; ++} ++ ++void FH_TIMER_FREE(fh_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ FH_SPINLOCK_FREE(timer->lock); ++ FH_FREE(timer->name); ++ FH_FREE(timer); ++} ++ ++void FH_TIMER_SCHEDULE(fh_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void FH_TIMER_CANCEL(fh_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct fh_waitq { ++ struct mtx lock; ++ int abort; ++}; ++ ++fh_waitq_t *FH_WAITQ_ALLOC(void) ++{ ++ fh_waitq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ FH_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF); ++ wq->abort = 0; ++ ++ return wq; ++} ++ ++void FH_WAITQ_FREE(fh_waitq_t *wq) ++{ ++ mtx_destroy(&wq->lock); ++ FH_FREE(wq); ++} ++ ++int32_t FH_WAITQ_WAIT(fh_waitq_t *wq, fh_waitq_condition_t cond, void *data) ++{ ++// intrmask_t ipl; ++ int result = 0; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout ++// ipl = splbio(); ++ } ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -FH_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -FH_E_ABORT; ++ ++ } else if (wq->abort) { ++ result = -FH_E_ABORT; ++ ++ } else { ++ result = 0; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++int32_t FH_WAITQ_WAIT_TIMEOUT(fh_waitq_t *wq, fh_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++// intrmask_t ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ getmicrouptime(&tv1); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv)); ++ getmicrouptime(&tv2); ++// ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ result = -FH_E_ABORT; ++ } else { ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else if (result == ERESTART) { // signaled - restart ++ result = -FH_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -FH_E_ABORT; ++ ++ } else { // timed out ++ result = -FH_E_TIMEOUT; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++void FH_WAITQ_TRIGGER(fh_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void FH_WAITQ_ABORT(fh_waitq_t *wq) ++{ ++// intrmask_t ipl; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct fh_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++fh_thread_t *FH_THREAD_RUN(fh_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ fh_thread_t *thread = FH_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create((void (*)(void *))func, data, &thread->proc, ++ RFPROC | RFNOWAIT, 0, "%s", name); ++ if (retval) { ++ FH_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int FH_THREAD_STOP(fh_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* FH_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { ++ return -FH_E_TIMEOUT; ++ } ++ ++ return -FH_E_UNKNOWN; ++} ++ ++fh_bool_t FH_THREAD_SHOULD_STOP(fh_thread_t *thread) ++{ ++ return thread->abort; ++} ++ ++void FH_THREAD_EXIT(fh_thread_t *thread) ++{ ++ wakeup(&thread->abort); ++ FH_FREE(thread); ++ kthread_exit(0); ++} ++ ++ ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ] ++ - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ] ++ */ ++struct fh_tasklet { ++ struct task t; ++ fh_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(void *data, int pending) // what to do with pending ??? ++{ ++ fh_tasklet_t *task = (fh_tasklet_t *)data; ++ ++ task->cb(task->data); ++} ++ ++fh_tasklet_t *FH_TASK_ALLOC(char *name, fh_tasklet_callback_t cb, void *data) ++{ ++ fh_tasklet_t *task = FH_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ TASK_INIT(&task->t, 0, tasklet_callback, task); ++ } else { ++ FH_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void FH_TASK_FREE(fh_tasklet_t *task) ++{ ++ taskqueue_drain(taskqueue_fast, &task->t); // ??? ++ FH_FREE(task); ++} ++ ++void FH_TASK_SCHEDULE(fh_tasklet_t *task) ++{ ++ /* Uses predefined system queue */ ++ taskqueue_enqueue_fast(taskqueue_fast, &task->t); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ fh_work_callback_t cb; ++ void *data; ++ fh_workq_t *wq; ++ char *name; ++ int hz; ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct task task; ++} work_container_t; ++ ++#ifdef DEBUG ++FH_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct fh_workq { ++ struct taskqueue *taskq; ++ fh_spinlock_t *lock; ++ fh_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(void *data, int pending) // what to do with pending ??? ++{ ++ work_container_t *container = (work_container_t *)data; ++ fh_workq_t *wq = container->wq; ++ fh_irqflags_t flags; ++ ++ if (container->hz) { ++ pause("dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ FH_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ if (container->name) ++ FH_FREE(container->name); ++ FH_FREE(container); ++ wq->pending--; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ fh_workq_t *workq = (fh_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int FH_WORKQ_WAIT_WORK_DONE(fh_workq_t *workq, int timeout) ++{ ++ return FH_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++fh_workq_t *FH_WORKQ_ALLOC(char *name) ++{ ++ fh_workq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ FH_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq); ++ if (!wq->taskq) { ++ FH_ERROR("Cannot allocate memory for taskqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = FH_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ FH_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = FH_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ FH_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk"); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ FH_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ taskqueue_free(wq->taskq); ++ no_taskq: ++ FH_FREE(wq); ++ ++ return NULL; ++} ++ ++void FH_WORKQ_FREE(fh_workq_t *wq) ++{ ++#ifdef DEBUG ++ fh_irqflags_t flags; ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container; ++ ++ FH_ERROR("Destroying work queue with pending work"); ++ ++ FH_CIRCLEQ_FOREACH(container, &wq->entries, entry) { ++ FH_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ FH_WAITQ_FREE(wq->waitq); ++ FH_SPINLOCK_FREE(wq->lock); ++ taskqueue_free(wq->taskq); ++ FH_FREE(wq); ++} ++ ++void FH_WORKQ_SCHEDULE(fh_workq_t *wq, fh_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++void FH_WORKQ_SCHEDULE_DELAYED(fh_workq_t *wq, fh_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++int FH_WORKQ_PENDING(fh_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_common_linux.c b/drivers/usb/host/fh_otg/fh_common_port/fh_common_linux.c +new file mode 100644 +index 00000000..da70b191 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_common_linux.c +@@ -0,0 +1,1426 @@ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kthread.h> ++ ++#ifdef FH_CCLIB ++# include "fh_cc.h" ++#endif ++ ++#ifdef FH_CRYPTOLIB ++# include "fh_modpow.h" ++# include "fh_dh.h" ++# include "fh_crypto.h" ++#endif ++ ++#ifdef FH_NOTIFYLIB ++# include "fh_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the Linux kernel implementation of the FH platform library. */ ++#include <linux/moduleparam.h> ++#include <linux/ctype.h> ++#include <linux/crypto.h> ++#include <linux/delay.h> ++#include <linux/device.h> ++#include <linux/dma-mapping.h> ++#include <linux/cdev.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/jiffies.h> ++#include <linux/list.h> ++#include <linux/pci.h> ++#include <linux/random.h> ++#include <linux/scatterlist.h> ++#include <linux/slab.h> ++#include <linux/stat.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/usb.h> ++ ++#include <linux/version.h> ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include <linux/usb/gadget.h> ++#else ++# include <linux/usb_gadget.h> ++#endif ++ ++#include <asm/io.h> ++#include <asm/page.h> ++#include <asm/uaccess.h> ++#include <asm/unaligned.h> ++ ++#include "fh_os.h" ++#include "fh_list.h" ++ ++ ++/* MISC */ ++ ++void *FH_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *FH_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *FH_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ return memmove(dest, src, size); ++} ++ ++int FH_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int FH_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int FH_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int FH_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *FH_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *FH_STRDUP(char const *str) ++{ ++ int len = FH_STRLEN(str) + 1; ++ char *new = FH_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ FH_MEMCPY(new, str, len); ++ return new; ++} ++ ++int FH_ATOI(const char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int FH_ATOUI(const char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef FH_UTFLIB ++/* From usbstring.c */ ++ ++int FH_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++#endif /* FH_UTFLIB */ ++ ++ ++/* fh_debug.h */ ++ ++fh_bool_t FH_IN_IRQ(void) ++{ ++ return in_irq(); ++} ++ ++fh_bool_t FH_IN_BH(void) ++{ ++ return in_softirq(); ++} ++ ++void FH_VPRINTF(char *format, va_list args) ++{ ++ vprintk(format, args); ++} ++ ++int FH_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void FH_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int FH_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int FH_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __FH_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_PRINTF(KERN_WARNING); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __FH_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_PRINTF(KERN_ERR); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void FH_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_PRINTF(KERN_ERR); ++ FH_VPRINTF(format, args); ++ va_end(args); ++ BUG_ON(1); ++} ++ ++#ifdef DEBUG ++void __FH_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_PRINTF(KERN_DEBUG); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* fh_mem.h */ ++ ++#if 0 ++fh_pool_t *FH_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (fh_pool_t *)pool; ++} ++ ++void FH_DMA_POOL_DESTROY(fh_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *FH_DMA_POOL_ALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++} ++ ++void *FH_DMA_POOL_ZALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = FH_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void FH_DMA_POOL_FREE(fh_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__FH_DMA_ALLOC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr) ++{ ++#ifdef xxCOSIM /* Only works for 32-bit cosim */ ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); ++#else ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_ATOMIC); ++#endif ++ if (!buf) { ++ return NULL; ++ } ++ ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void *__FH_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr) ++{ ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++ if (!buf) { ++ return NULL; ++ } ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void __FH_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, fh_dma_t dma_addr) ++{ ++ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++void *__FH_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_KERNEL); ++} ++ ++void *__FH_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_ATOMIC); ++} ++ ++void __FH_FREE(void *mem_ctx, void *addr) ++{ ++ kfree(addr); ++} ++ ++ ++#ifdef FH_CRYPTOLIB ++/* fh_crypto.h */ ++ ++void FH_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int FH_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ FH_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int FH_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int FH_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++#endif /* FH_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t FH_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t FH_READ_REG32(uint32_t volatile *reg) ++{ ++ return readl(reg); ++} ++ ++#if 0 ++uint64_t FH_READ_REG64(uint64_t volatile *reg) ++{ ++} ++#endif ++ ++void FH_WRITE_REG32(uint32_t volatile *reg, uint32_t value) ++{ ++ writel(value, reg); ++} ++ ++#if 0 ++void FH_WRITE_REG64(uint64_t volatile *reg, uint64_t value) ++{ ++} ++#endif ++ ++void FH_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) ++{ ++ writel((readl(reg) & ~clear_mask) | set_mask, reg); ++} ++ ++#if 0 ++void FH_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask) ++{ ++} ++#endif ++ ++ ++/* Locking */ ++ ++fh_spinlock_t *FH_SPINLOCK_ALLOC(void) ++{ ++ spinlock_t *sl = (spinlock_t *)1; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ sl = FH_ALLOC(sizeof(*sl)); ++ if (!sl) { ++ FH_ERROR("Cannot allocate memory for spinlock\n"); ++ return NULL; ++ } ++ ++ spin_lock_init(sl); ++#endif ++ return (fh_spinlock_t *)sl; ++} ++ ++void FH_SPINLOCK_FREE(fh_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ FH_FREE(lock); ++#endif ++} ++ ++void FH_SPINLOCK(fh_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock((spinlock_t *)lock); ++#endif ++} ++ ++void FH_SPINUNLOCK(fh_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock((spinlock_t *)lock); ++#endif ++} ++ ++void FH_SPINLOCK_IRQSAVE(fh_spinlock_t *lock, fh_irqflags_t *flags) ++{ ++ fh_irqflags_t f; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock_irqsave((spinlock_t *)lock, f); ++#else ++ local_irq_save(f); ++#endif ++ *flags = f; ++} ++ ++void FH_SPINUNLOCK_IRQRESTORE(fh_spinlock_t *lock, fh_irqflags_t flags) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock_irqrestore((spinlock_t *)lock, flags); ++#else ++ local_irq_restore(flags); ++#endif ++} ++ ++fh_mutex_t *FH_MUTEX_ALLOC(void) ++{ ++ struct mutex *m; ++ fh_mutex_t *mutex = (fh_mutex_t *)FH_ALLOC(sizeof(struct mutex)); ++ ++ if (!mutex) { ++ FH_ERROR("Cannot allocate memory for mutex\n"); ++ return NULL; ++ } ++ ++ m = (struct mutex *)mutex; ++ mutex_init(m); ++ return mutex; ++} ++ ++#if (defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void FH_MUTEX_FREE(fh_mutex_t *mutex) ++{ ++ mutex_destroy((struct mutex *)mutex); ++ FH_FREE(mutex); ++} ++#endif ++ ++void FH_MUTEX_LOCK(fh_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_lock(m); ++} ++ ++int FH_MUTEX_TRYLOCK(fh_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ return mutex_trylock(m); ++} ++ ++void FH_MUTEX_UNLOCK(fh_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void FH_UDELAY(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++void FH_MDELAY(uint32_t msecs) ++{ ++ mdelay(msecs); ++} ++ ++void FH_MSLEEP(uint32_t msecs) ++{ ++ msleep(msecs); ++} ++ ++uint32_t FH_TIME(void) ++{ ++ return jiffies_to_msecs(jiffies); ++} ++ ++ ++/* Timers */ ++ ++struct fh_timer { ++ struct timer_list *t; ++ char *name; ++ fh_timer_callback_t cb; ++ void *data; ++ uint8_t scheduled; ++ fh_spinlock_t *lock; ++}; ++ ++static void timer_callback(unsigned long data) ++{ ++ fh_timer_t *timer = (fh_timer_t *)data; ++ fh_irqflags_t flags; ++ ++ FH_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ timer->scheduled = 0; ++ FH_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ FH_DEBUG("Timer %s callback", timer->name); ++ timer->cb(timer->data); ++} ++ ++fh_timer_t *FH_TIMER_ALLOC(char *name, fh_timer_callback_t cb, void *data) ++{ ++ fh_timer_t *t = FH_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ FH_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ t->t = FH_ALLOC(sizeof(*t->t)); ++ if (!t->t) { ++ FH_ERROR("Cannot allocate memory for timer->t"); ++ goto no_timer; ++ } ++ ++ t->name = FH_STRDUP(name); ++ if (!t->name) { ++ FH_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = FH_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ FH_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->scheduled = 0; ++ t->t->base = &boot_tvec_bases; ++ t->t->expires = jiffies; ++ setup_timer(t->t, timer_callback, (unsigned long)t); ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ FH_FREE(t->name); ++ no_name: ++ FH_FREE(t->t); ++ no_timer: ++ FH_FREE(t); ++ return NULL; ++} ++ ++void FH_TIMER_FREE(fh_timer_t *timer) ++{ ++ fh_irqflags_t flags; ++ ++ FH_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (timer->scheduled) { ++ del_timer(timer->t); ++ timer->scheduled = 0; ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ FH_SPINLOCK_FREE(timer->lock); ++ FH_FREE(timer->t); ++ FH_FREE(timer->name); ++ FH_FREE(timer); ++} ++ ++void FH_TIMER_SCHEDULE(fh_timer_t *timer, uint32_t time) ++{ ++ fh_irqflags_t flags; ++ ++ FH_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (!timer->scheduled) { ++ timer->scheduled = 1; ++ FH_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); ++ timer->t->expires = jiffies + msecs_to_jiffies(time); ++ add_timer(timer->t); ++ } else { ++ FH_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); ++ mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++} ++ ++void FH_TIMER_CANCEL(fh_timer_t *timer) ++{ ++ del_timer(timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct fh_waitq { ++ wait_queue_head_t queue; ++ int abort; ++}; ++ ++fh_waitq_t *FH_WAITQ_ALLOC(void) ++{ ++ fh_waitq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ FH_ERROR("Cannot allocate memory for waitqueue\n"); ++ return NULL; ++ } ++ ++ init_waitqueue_head(&wq->queue); ++ wq->abort = 0; ++ return wq; ++} ++ ++void FH_WAITQ_FREE(fh_waitq_t *wq) ++{ ++ FH_FREE(wq); ++} ++ ++int32_t FH_WAITQ_WAIT(fh_waitq_t *wq, fh_waitq_condition_t cond, void *data) ++{ ++ int result = wait_event_interruptible(wq->queue, ++ cond(data) || wq->abort); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -FH_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -FH_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result == 0) { ++ return 0; ++ } ++ ++ return -FH_E_UNKNOWN; ++} ++ ++int32_t FH_WAITQ_WAIT_TIMEOUT(fh_waitq_t *wq, fh_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ int32_t tmsecs; ++ int result = wait_event_interruptible_timeout(wq->queue, ++ cond(data) || wq->abort, ++ msecs_to_jiffies(msecs)); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -FH_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -FH_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result > 0) { ++ tmsecs = jiffies_to_msecs(result); ++ if (!tmsecs) { ++ return 1; ++ } ++ ++ return tmsecs; ++ } ++ ++ if (result == 0) { ++ return -FH_E_TIMEOUT; ++ } ++ ++ return -FH_E_UNKNOWN; ++} ++ ++void FH_WAITQ_TRIGGER(fh_waitq_t *wq) ++{ ++ wq->abort = 0; ++ wake_up_interruptible(&wq->queue); ++} ++ ++void FH_WAITQ_ABORT(fh_waitq_t *wq) ++{ ++ wq->abort = 1; ++ wake_up_interruptible(&wq->queue); ++} ++ ++ ++/* Threading */ ++ ++fh_thread_t *FH_THREAD_RUN(fh_thread_function_t func, char *name, void *data) ++{ ++ struct task_struct *thread = kthread_run(func, data, name); ++ ++ if (thread == ERR_PTR(-ENOMEM)) { ++ return NULL; ++ } ++ ++ return (fh_thread_t *)thread; ++} ++ ++int FH_THREAD_STOP(fh_thread_t *thread) ++{ ++ return kthread_stop((struct task_struct *)thread); ++} ++ ++fh_bool_t FH_THREAD_SHOULD_STOP(void) ++{ ++ return kthread_should_stop(); ++} ++ ++ ++/* tasklets ++ - run in interrupt context (cannot sleep) ++ - each tasklet runs on a single CPU ++ - different tasklets can be running simultaneously on different CPUs ++ */ ++struct fh_tasklet { ++ struct tasklet_struct t; ++ fh_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(unsigned long data) ++{ ++ fh_tasklet_t *t = (fh_tasklet_t *)data; ++ t->cb(t->data); ++} ++ ++fh_tasklet_t *FH_TASK_ALLOC(char *name, fh_tasklet_callback_t cb, void *data) ++{ ++ fh_tasklet_t *t = FH_ALLOC(sizeof(*t)); ++ ++ if (t) { ++ t->cb = cb; ++ t->data = data; ++ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); ++ } else { ++ FH_ERROR("Cannot allocate memory for tasklet\n"); ++ } ++ ++ return t; ++} ++ ++void FH_TASK_FREE(fh_tasklet_t *task) ++{ ++ FH_FREE(task); ++} ++ ++void FH_TASK_SCHEDULE(fh_tasklet_t *task) ++{ ++ tasklet_schedule(&task->t); ++} ++ ++ ++/* workqueues ++ - run in process context (can sleep) ++ */ ++typedef struct work_container { ++ fh_work_callback_t cb; ++ void *data; ++ fh_workq_t *wq; ++ char *name; ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct delayed_work work; ++} work_container_t; ++ ++#ifdef DEBUG ++FH_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct fh_workq { ++ struct workqueue_struct *wq; ++ fh_spinlock_t *lock; ++ fh_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(struct work_struct *work) ++{ ++ fh_irqflags_t flags; ++ struct delayed_work *dw = container_of(work, struct delayed_work, work); ++ work_container_t *container = container_of(dw, struct work_container, work); ++ fh_workq_t *wq = container->wq; ++ ++ container->cb(container->data); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ FH_DEBUG("Work done: %s, container=%p", container->name, container); ++ if (container->name) { ++ FH_FREE(container->name); ++ } ++ FH_FREE(container); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending--; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ fh_workq_t *workq = (fh_workq_t *)data; ++ return workq->pending == 0; ++} ++ ++int FH_WORKQ_WAIT_WORK_DONE(fh_workq_t *workq, int timeout) ++{ ++ return FH_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++fh_workq_t *FH_WORKQ_ALLOC(char *name) ++{ ++ fh_workq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ return NULL; ++ } ++ ++ wq->wq = create_singlethread_workqueue(name); ++ if (!wq->wq) { ++ goto no_wq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = FH_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ goto no_lock; ++ } ++ ++ wq->waitq = FH_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ goto no_waitq; ++ } ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ FH_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ destroy_workqueue(wq->wq); ++ no_wq: ++ FH_FREE(wq); ++ ++ return NULL; ++} ++ ++void FH_WORKQ_FREE(fh_workq_t *wq) ++{ ++#ifdef DEBUG ++ if (wq->pending != 0) { ++ struct work_container *wc; ++ FH_ERROR("Destroying work queue with pending work"); ++ FH_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { ++ FH_ERROR("Work %s still pending", wc->name); ++ } ++ } ++#endif ++ destroy_workqueue(wq->wq); ++ FH_SPINLOCK_FREE(wq->lock); ++ FH_WAITQ_FREE(wq->waitq); ++ FH_FREE(wq); ++} ++bool FH_SCHEDULE_SYSTEM_WORK(struct work_struct *work){ ++ ++ return queue_work(system_wq, work); ++} ++ ++void FH_WORKQ_SCHEDULE(fh_workq_t *wq, fh_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name\n"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_WORK(&container->work.work, do_work); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_work(wq->wq, &container->work.work); ++} ++ ++void FH_WORKQ_SCHEDULE_DELAYED(fh_workq_t *wq, fh_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name\n"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ INIT_DELAYED_WORK(&container->work, do_work); ++ ++#ifdef DEBUG ++ FH_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); ++} ++ ++int FH_WORKQ_PENDING(fh_workq_t *wq) ++{ ++ return wq->pending; ++} ++ ++ ++#ifdef FH_LIBMODULE ++ ++#ifdef FH_CCLIB ++/* CC */ ++EXPORT_SYMBOL(fh_cc_if_alloc); ++EXPORT_SYMBOL(fh_cc_if_free); ++EXPORT_SYMBOL(fh_cc_clear); ++EXPORT_SYMBOL(fh_cc_add); ++EXPORT_SYMBOL(fh_cc_remove); ++EXPORT_SYMBOL(fh_cc_change); ++EXPORT_SYMBOL(fh_cc_data_for_save); ++EXPORT_SYMBOL(fh_cc_restore_from_data); ++EXPORT_SYMBOL(fh_cc_match_chid); ++EXPORT_SYMBOL(fh_cc_match_cdid); ++EXPORT_SYMBOL(fh_cc_ck); ++EXPORT_SYMBOL(fh_cc_chid); ++EXPORT_SYMBOL(fh_cc_cdid); ++EXPORT_SYMBOL(fh_cc_name); ++#endif /* FH_CCLIB */ ++ ++#ifdef FH_CRYPTOLIB ++# ifndef CONFIG_MACH_IPMATE ++/* Modpow */ ++EXPORT_SYMBOL(fh_modpow); ++ ++/* DH */ ++EXPORT_SYMBOL(fh_dh_modpow); ++EXPORT_SYMBOL(fh_dh_derive_keys); ++EXPORT_SYMBOL(fh_dh_pk); ++# endif /* CONFIG_MACH_IPMATE */ ++ ++/* Crypto */ ++EXPORT_SYMBOL(fh_wusb_aes_encrypt); ++EXPORT_SYMBOL(fh_wusb_cmf); ++EXPORT_SYMBOL(fh_wusb_prf); ++EXPORT_SYMBOL(fh_wusb_fill_ccm_nonce); ++EXPORT_SYMBOL(fh_wusb_gen_nonce); ++EXPORT_SYMBOL(fh_wusb_gen_key); ++EXPORT_SYMBOL(fh_wusb_gen_mic); ++#endif /* FH_CRYPTOLIB */ ++ ++/* Notification */ ++#ifdef FH_NOTIFYLIB ++EXPORT_SYMBOL(fh_alloc_notification_manager); ++EXPORT_SYMBOL(fh_free_notification_manager); ++EXPORT_SYMBOL(fh_register_notifier); ++EXPORT_SYMBOL(fh_unregister_notifier); ++EXPORT_SYMBOL(fh_add_observer); ++EXPORT_SYMBOL(fh_remove_observer); ++EXPORT_SYMBOL(fh_notify); ++#endif ++ ++/* Memory Debugging Routines */ ++#ifdef FH_DEBUG_MEMORY ++EXPORT_SYMBOL(fh_alloc_debug); ++EXPORT_SYMBOL(fh_alloc_atomic_debug); ++EXPORT_SYMBOL(fh_free_debug); ++EXPORT_SYMBOL(fh_dma_alloc_debug); ++EXPORT_SYMBOL(fh_dma_free_debug); ++#endif ++ ++EXPORT_SYMBOL(FH_MEMSET); ++EXPORT_SYMBOL(FH_MEMCPY); ++EXPORT_SYMBOL(FH_MEMMOVE); ++EXPORT_SYMBOL(FH_MEMCMP); ++EXPORT_SYMBOL(FH_STRNCMP); ++EXPORT_SYMBOL(FH_STRCMP); ++EXPORT_SYMBOL(FH_STRLEN); ++EXPORT_SYMBOL(FH_STRCPY); ++EXPORT_SYMBOL(FH_STRDUP); ++EXPORT_SYMBOL(FH_ATOI); ++EXPORT_SYMBOL(FH_ATOUI); ++ ++#ifdef FH_UTFLIB ++EXPORT_SYMBOL(FH_UTF8_TO_UTF16LE); ++#endif /* FH_UTFLIB */ ++ ++EXPORT_SYMBOL(FH_IN_IRQ); ++EXPORT_SYMBOL(FH_IN_BH); ++EXPORT_SYMBOL(FH_VPRINTF); ++EXPORT_SYMBOL(FH_VSNPRINTF); ++EXPORT_SYMBOL(FH_PRINTF); ++EXPORT_SYMBOL(FH_SPRINTF); ++EXPORT_SYMBOL(FH_SNPRINTF); ++EXPORT_SYMBOL(__FH_WARN); ++EXPORT_SYMBOL(__FH_ERROR); ++EXPORT_SYMBOL(FH_EXCEPTION); ++ ++#ifdef DEBUG ++EXPORT_SYMBOL(__FH_DEBUG); ++#endif ++ ++EXPORT_SYMBOL(__FH_DMA_ALLOC); ++EXPORT_SYMBOL(__FH_DMA_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__FH_DMA_FREE); ++EXPORT_SYMBOL(__FH_ALLOC); ++EXPORT_SYMBOL(__FH_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__FH_FREE); ++ ++#ifdef FH_CRYPTOLIB ++EXPORT_SYMBOL(FH_RANDOM_BYTES); ++EXPORT_SYMBOL(FH_AES_CBC); ++EXPORT_SYMBOL(FH_SHA256); ++EXPORT_SYMBOL(FH_HMAC_SHA256); ++#endif ++ ++EXPORT_SYMBOL(FH_CPU_TO_LE32); ++EXPORT_SYMBOL(FH_CPU_TO_BE32); ++EXPORT_SYMBOL(FH_LE32_TO_CPU); ++EXPORT_SYMBOL(FH_BE32_TO_CPU); ++EXPORT_SYMBOL(FH_CPU_TO_LE16); ++EXPORT_SYMBOL(FH_CPU_TO_BE16); ++EXPORT_SYMBOL(FH_LE16_TO_CPU); ++EXPORT_SYMBOL(FH_BE16_TO_CPU); ++EXPORT_SYMBOL(FH_READ_REG32); ++EXPORT_SYMBOL(FH_WRITE_REG32); ++EXPORT_SYMBOL(FH_MODIFY_REG32); ++ ++#if 0 ++EXPORT_SYMBOL(FH_READ_REG64); ++EXPORT_SYMBOL(FH_WRITE_REG64); ++EXPORT_SYMBOL(FH_MODIFY_REG64); ++#endif ++ ++EXPORT_SYMBOL(FH_SPINLOCK_ALLOC); ++EXPORT_SYMBOL(FH_SPINLOCK_FREE); ++EXPORT_SYMBOL(FH_SPINLOCK); ++EXPORT_SYMBOL(FH_SPINUNLOCK); ++EXPORT_SYMBOL(FH_SPINLOCK_IRQSAVE); ++EXPORT_SYMBOL(FH_SPINUNLOCK_IRQRESTORE); ++EXPORT_SYMBOL(FH_MUTEX_ALLOC); ++ ++#if (!defined(FH_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) ++EXPORT_SYMBOL(FH_MUTEX_FREE); ++#endif ++ ++EXPORT_SYMBOL(FH_MUTEX_LOCK); ++EXPORT_SYMBOL(FH_MUTEX_TRYLOCK); ++EXPORT_SYMBOL(FH_MUTEX_UNLOCK); ++EXPORT_SYMBOL(FH_UDELAY); ++EXPORT_SYMBOL(FH_MDELAY); ++EXPORT_SYMBOL(FH_MSLEEP); ++EXPORT_SYMBOL(FH_TIME); ++EXPORT_SYMBOL(FH_TIMER_ALLOC); ++EXPORT_SYMBOL(FH_TIMER_FREE); ++EXPORT_SYMBOL(FH_TIMER_SCHEDULE); ++EXPORT_SYMBOL(FH_TIMER_CANCEL); ++EXPORT_SYMBOL(FH_WAITQ_ALLOC); ++EXPORT_SYMBOL(FH_WAITQ_FREE); ++EXPORT_SYMBOL(FH_WAITQ_WAIT); ++EXPORT_SYMBOL(FH_WAITQ_WAIT_TIMEOUT); ++EXPORT_SYMBOL(FH_WAITQ_TRIGGER); ++EXPORT_SYMBOL(FH_WAITQ_ABORT); ++EXPORT_SYMBOL(FH_THREAD_RUN); ++EXPORT_SYMBOL(FH_THREAD_STOP); ++EXPORT_SYMBOL(FH_THREAD_SHOULD_STOP); ++EXPORT_SYMBOL(FH_TASK_ALLOC); ++EXPORT_SYMBOL(FH_TASK_FREE); ++EXPORT_SYMBOL(FH_TASK_SCHEDULE); ++EXPORT_SYMBOL(FH_WORKQ_WAIT_WORK_DONE); ++EXPORT_SYMBOL(FH_WORKQ_ALLOC); ++EXPORT_SYMBOL(FH_WORKQ_FREE); ++EXPORT_SYMBOL(FH_SCHEDULE_SYSTEM_WORK); ++EXPORT_SYMBOL(FH_WORKQ_SCHEDULE); ++EXPORT_SYMBOL(FH_WORKQ_SCHEDULE_DELAYED); ++EXPORT_SYMBOL(FH_WORKQ_PENDING); ++ ++static int fh_common_port_init_module(void) ++{ ++ int result = 0; ++ ++ printk(KERN_DEBUG "Module fh_common_port init\n" ); ++ ++#ifdef FH_DEBUG_MEMORY ++ result = fh_memory_debug_start(NULL); ++ if (result) { ++ printk(KERN_ERR ++ "fh_memory_debug_start() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ ++#ifdef FH_NOTIFYLIB ++ result = fh_alloc_notification_manager(NULL, NULL); ++ if (result) { ++ printk(KERN_ERR ++ "fh_alloc_notification_manager() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ return result; ++} ++ ++static void fh_common_port_exit_module(void) ++{ ++ printk(KERN_DEBUG "Module fh_common_port exit\n" ); ++ ++#ifdef FH_NOTIFYLIB ++ fh_free_notification_manager(); ++#endif ++ ++#ifdef FH_DEBUG_MEMORY ++ fh_memory_debug_stop(); ++#endif ++} ++ ++module_init(fh_common_port_init_module); ++module_exit(fh_common_port_exit_module); ++ ++MODULE_DESCRIPTION("FH Common Library - Portable version"); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE ("GPL"); ++ ++#endif /* FH_LIBMODULE */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_common_nbsd.c b/drivers/usb/host/fh_otg/fh_common_port/fh_common_nbsd.c +new file mode 100644 +index 00000000..188eabc5 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_common_nbsd.c +@@ -0,0 +1,1275 @@ ++#include "fh_os.h" ++#include "fh_list.h" ++ ++#ifdef FH_CCLIB ++# include "fh_cc.h" ++#endif ++ ++#ifdef FH_CRYPTOLIB ++# include "fh_modpow.h" ++# include "fh_dh.h" ++# include "fh_crypto.h" ++#endif ++ ++#ifdef FH_NOTIFYLIB ++# include "fh_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the NetBSD 4.0.1 kernel implementation of the FH platform library. */ ++ ++ ++/* MISC */ ++ ++void *FH_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *FH_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *FH_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ bcopy(src, dest, size); ++ return dest; ++} ++ ++int FH_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int FH_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int FH_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int FH_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *FH_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *FH_STRDUP(char const *str) ++{ ++ int len = FH_STRLEN(str) + 1; ++ char *new = FH_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ FH_MEMCPY(new, str, len); ++ return new; ++} ++ ++int FH_ATOI(char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul' ++ * should be equivalent on 2's complement machines ++ */ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int FH_ATOUI(char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef FH_UTFLIB ++/* From usbstring.c */ ++ ++int FH_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++#endif /* FH_UTFLIB */ ++ ++ ++/* fh_debug.h */ ++ ++fh_bool_t FH_IN_IRQ(void) ++{ ++// return in_irq(); ++ return 0; ++} ++ ++fh_bool_t FH_IN_BH(void) ++{ ++// return in_softirq(); ++ return 0; ++} ++ ++void FH_VPRINTF(char *format, va_list args) ++{ ++ vprintf(format, args); ++} ++ ++int FH_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void FH_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int FH_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int FH_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __FH_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __FH_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void FH_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++// BUG_ON(1); ??? ++} ++ ++#ifdef DEBUG ++void __FH_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ FH_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* fh_mem.h */ ++ ++#if 0 ++fh_pool_t *FH_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (fh_pool_t *)pool; ++} ++ ++void FH_DMA_POOL_DESTROY(fh_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *FH_DMA_POOL_ALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); ++} ++ ++void *FH_DMA_POOL_ZALLOC(fh_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = FH_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void FH_DMA_POOL_FREE(fh_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__FH_DMA_ALLOC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr) ++{ ++ fh_dmactx_t *dma = (fh_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs, ++ sizeof(dma->segs) / sizeof(dma->segs[0]), ++ &dma->nsegs, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__, ++ (uintmax_t)size, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size, ++ (caddr_t *)&dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT); ++ if (error) { ++ printf("%s: bus_dmamem_map failed: %d\n", __func__, error); ++ goto fail_1; ++ } ++ ++ error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0, ++ BUS_DMA_NOWAIT, &dma->dma_map); ++ if (error) { ++ printf("%s: bus_dmamap_create failed: %d\n", __func__, error); ++ goto fail_2; ++ } ++ ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, ++ size, NULL, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamap_load failed: %d\n", __func__, error); ++ goto fail_3; ++ } ++ ++ dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr; ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_3: ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++fail_2: ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ ++ return NULL; ++} ++ ++void __FH_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, fh_dma_t dma_addr) ++{ ++ fh_dmactx_t *dma = (fh_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++ dma->dma_paddr = 0; ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ } ++} ++ ++void *__FH_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__FH_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __FH_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef FH_CRYPTOLIB ++/* fh_crypto.h */ ++ ++void FH_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int FH_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ FH_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int FH_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int FH_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ FH_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* FH_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t FH_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t FH_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t FH_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t FH_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t FH_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void FH_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void FH_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void FH_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void FH_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ fh_ioctx_t *io = (fh_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++fh_spinlock_t *FH_SPINLOCK_ALLOC(void) ++{ ++ struct simplelock *sl = FH_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ FH_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ simple_lock_init(sl); ++ return (fh_spinlock_t *)sl; ++} ++ ++void FH_SPINLOCK_FREE(fh_spinlock_t *lock) ++{ ++ struct simplelock *sl = (struct simplelock *)lock; ++ ++ FH_FREE(sl); ++} ++ ++void FH_SPINLOCK(fh_spinlock_t *lock) ++{ ++ simple_lock((struct simplelock *)lock); ++} ++ ++void FH_SPINUNLOCK(fh_spinlock_t *lock) ++{ ++ simple_unlock((struct simplelock *)lock); ++} ++ ++void FH_SPINLOCK_IRQSAVE(fh_spinlock_t *lock, fh_irqflags_t *flags) ++{ ++ simple_lock((struct simplelock *)lock); ++ *flags = splbio(); ++} ++ ++void FH_SPINUNLOCK_IRQRESTORE(fh_spinlock_t *lock, fh_irqflags_t flags) ++{ ++ splx(flags); ++ simple_unlock((struct simplelock *)lock); ++} ++ ++fh_mutex_t *FH_MUTEX_ALLOC(void) ++{ ++ fh_mutex_t *mutex = FH_ALLOC(sizeof(struct lock)); ++ ++ if (!mutex) { ++ FH_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0); ++ return mutex; ++} ++ ++#if (defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void FH_MUTEX_FREE(fh_mutex_t *mutex) ++{ ++ FH_FREE(mutex); ++} ++#endif ++ ++void FH_MUTEX_LOCK(fh_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL); ++} ++ ++int FH_MUTEX_TRYLOCK(fh_mutex_t *mutex) ++{ ++ int status; ++ ++ status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL); ++ return status == 0; ++} ++ ++void FH_MUTEX_UNLOCK(fh_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_RELEASE, NULL); ++} ++ ++ ++/* Timing */ ++ ++void FH_UDELAY(uint32_t usecs) ++{ ++ DELAY(usecs); ++} ++ ++void FH_MDELAY(uint32_t msecs) ++{ ++ do { ++ DELAY(1000); ++ } while (--msecs); ++} ++ ++void FH_MSLEEP(uint32_t msecs) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ tsleep(&tv, 0, "dw3slp", tvtohz(&tv)); ++} ++ ++uint32_t FH_TIME(void) ++{ ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct fh_timer { ++ struct callout t; ++ char *name; ++ fh_spinlock_t *lock; ++ fh_timer_callback_t cb; ++ void *data; ++}; ++ ++fh_timer_t *FH_TIMER_ALLOC(char *name, fh_timer_callback_t cb, void *data) ++{ ++ fh_timer_t *t = FH_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ FH_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t); ++ ++ t->name = FH_STRDUP(name); ++ if (!t->name) { ++ FH_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = FH_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ FH_ERROR("Cannot allocate memory for timer->lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ FH_FREE(t->name); ++ no_name: ++ FH_FREE(t); ++ ++ return NULL; ++} ++ ++void FH_TIMER_FREE(fh_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ FH_SPINLOCK_FREE(timer->lock); ++ FH_FREE(timer->name); ++ FH_FREE(timer); ++} ++ ++void FH_TIMER_SCHEDULE(fh_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void FH_TIMER_CANCEL(fh_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct fh_waitq { ++ struct simplelock lock; ++ int abort; ++}; ++ ++fh_waitq_t *FH_WAITQ_ALLOC(void) ++{ ++ fh_waitq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ FH_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ simple_lock_init(&wq->lock); ++ wq->abort = 0; ++ ++ return wq; ++} ++ ++void FH_WAITQ_FREE(fh_waitq_t *wq) ++{ ++ FH_FREE(wq); ++} ++ ++int32_t FH_WAITQ_WAIT(fh_waitq_t *wq, fh_waitq_condition_t cond, void *data) ++{ ++ int ipl; ++ int result = 0; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ result = -FH_E_ABORT; ++ } else { ++ result = 0; ++ } ++ ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -FH_E_RESTART; ++ } else { // signaled - must be EINTR ++ result = -FH_E_ABORT; ++ } ++ } ++ ++ return result; ++} ++ ++int32_t FH_WAITQ_WAIT_TIMEOUT(fh_waitq_t *wq, fh_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++ int ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ getmicrouptime(&tv1); ++ result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock); ++ getmicrouptime(&tv2); ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ result = -FH_E_ABORT; ++ } else { ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -FH_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -FH_E_ABORT; ++ ++ } else { // timed out ++ result = -FH_E_TIMEOUT; ++ } ++ } ++ ++ return result; ++} ++ ++void FH_WAITQ_TRIGGER(fh_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void FH_WAITQ_ABORT(fh_waitq_t *wq) ++{ ++ int ipl; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++ splx(ipl); ++ simple_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct fh_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++fh_thread_t *FH_THREAD_RUN(fh_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ fh_thread_t *thread = FH_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create1((void (*)(void *))func, data, &thread->proc, ++ "%s", name); ++ if (retval) { ++ FH_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int FH_THREAD_STOP(fh_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* FH_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { ++ return -FH_E_TIMEOUT; ++ } ++ ++ return -FH_E_UNKNOWN; ++} ++ ++fh_bool_t FH_THREAD_SHOULD_STOP(fh_thread_t *thread) ++{ ++ return thread->abort; ++} ++ ++void FH_THREAD_EXIT(fh_thread_t *thread) ++{ ++ wakeup(&thread->abort); ++ FH_FREE(thread); ++ kthread_exit(0); ++} ++ ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU ++ - Different tasklets can be running simultaneously on different CPUs ++ [ On NetBSD there is no corresponding mechanism, drivers don't have bottom- ++ halves. So we just call the callback directly from FH_TASK_SCHEDULE() ] ++ */ ++struct fh_tasklet { ++ fh_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(void *data) ++{ ++ fh_tasklet_t *task = (fh_tasklet_t *)data; ++ ++ task->cb(task->data); ++} ++ ++fh_tasklet_t *FH_TASK_ALLOC(char *name, fh_tasklet_callback_t cb, void *data) ++{ ++ fh_tasklet_t *task = FH_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ } else { ++ FH_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void FH_TASK_FREE(fh_tasklet_t *task) ++{ ++ FH_FREE(task); ++} ++ ++void FH_TASK_SCHEDULE(fh_tasklet_t *task) ++{ ++ tasklet_callback(task); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ fh_work_callback_t cb; ++ void *data; ++ fh_workq_t *wq; ++ char *name; ++ int hz; ++ struct work task; ++} work_container_t; ++ ++struct fh_workq { ++ struct workqueue *taskq; ++ fh_spinlock_t *lock; ++ fh_waitq_t *waitq; ++ int pending; ++ struct work_container *container; ++}; ++ ++static void do_work(struct work *task, void *data) ++{ ++ fh_workq_t *wq = (fh_workq_t *)data; ++ work_container_t *container = wq->container; ++ fh_irqflags_t flags; ++ ++ if (container->hz) { ++ tsleep(container, 0, "dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ FH_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ if (container->name) ++ FH_FREE(container->name); ++ FH_FREE(container); ++ wq->pending--; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ fh_workq_t *workq = (fh_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int FH_WORKQ_WAIT_WORK_DONE(fh_workq_t *workq, int timeout) ++{ ++ return FH_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++fh_workq_t *FH_WORKQ_ALLOC(char *name) ++{ ++ int result; ++ fh_workq_t *wq = FH_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ FH_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/, ++ IPL_BIO, 0); ++ if (result) { ++ FH_ERROR("Cannot create workqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = FH_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ FH_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = FH_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ FH_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ return wq; ++ ++ no_waitq: ++ FH_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ workqueue_destroy(wq->taskq); ++ no_taskq: ++ FH_FREE(wq); ++ ++ return NULL; ++} ++ ++void FH_WORKQ_FREE(fh_workq_t *wq) ++{ ++#ifdef DEBUG ++ fh_irqflags_t flags; ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container = wq->container; ++ ++ FH_ERROR("Destroying work queue with pending work"); ++ ++ if (container && container->name) { ++ FH_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ FH_WAITQ_FREE(wq->waitq); ++ FH_SPINLOCK_FREE(wq->lock); ++ workqueue_destroy(wq->taskq); ++ FH_FREE(wq); ++} ++ ++void FH_WORKQ_SCHEDULE(fh_workq_t *wq, fh_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ wq->container = container; ++ ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++void FH_WORKQ_SCHEDULE_DELAYED(fh_workq_t *wq, fh_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ fh_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ FH_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ FH_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ FH_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ FH_WAITQ_TRIGGER(wq->waitq); ++ ++ container = FH_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ FH_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = FH_STRDUP(name); ++ if (!container->name) { ++ FH_ERROR("Cannot allocate memory for container->name"); ++ FH_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ wq->container = container; ++ ++ FH_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++int FH_WORKQ_PENDING(fh_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.c b/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.c +new file mode 100644 +index 00000000..c63fd24e +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.c +@@ -0,0 +1,308 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_crypto.c $ ++ * $Revision: #5 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++ ++/** @file ++ * This file contains the WUSB cryptographic routines. ++ */ ++ ++#ifdef FH_CRYPTOLIB ++ ++#include "fh_crypto.h" ++#include "usb.h" ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ FH_PRINTF("%s: ", name); ++ for (i=0; i<len; i++) { ++ FH_PRINTF("%02x ", bytes[i]); ++ } ++ FH_PRINTF("\n"); ++} ++#else ++#define dump_bytes(x...) ++#endif ++ ++/* Display a block */ ++void show_block(const u8 *blk, const char *prefix, const char *suffix, int a) ++{ ++#ifdef FH_DEBUG_CRYPTO ++ int i, blksize = 16; ++ ++ FH_DEBUG("%s", prefix); ++ ++ if (suffix == NULL) { ++ suffix = "\n"; ++ blksize = a; ++ } ++ ++ for (i = 0; i < blksize; i++) ++ FH_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? " " : " "); ++ FH_PRINT(suffix); ++#endif ++} ++ ++/** ++ * Encrypts an array of bytes using the AES encryption engine. ++ * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted ++ * in-place. ++ * ++ * @return 0 on success, negative error code on error. ++ */ ++int fh_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) ++{ ++ u8 block_t[16]; ++ FH_MEMSET(block_t, 0, 16); ++ ++ return FH_AES_CBC(src, 16, key, 16, block_t, dst); ++} ++ ++/** ++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. ++ * This function takes a data string and returns the encrypted CBC ++ * Counter-mode MIC. ++ * ++ * @param key The 128-bit symmetric key. ++ * @param nonce The CCM nonce. ++ * @param label The unique 14-byte ASCII text label. ++ * @param bytes The byte array to be encrypted. ++ * @param len Length of the byte array. ++ * @param result Byte array to receive the 8-byte encrypted MIC. ++ */ ++void fh_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ u8 block_m[16]; ++ u8 block_x[16]; ++ u8 block_t[8]; ++ int idx, blkNum; ++ u16 la = (u16)(len + 14); ++ ++ /* Set the AES-128 key */ ++ //fh_aes_setkey(tfm, key, 16); ++ ++ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ ++ block_m[0] = 0x59; ++ for (idx = 0; idx < 13; idx++) ++ block_m[idx + 1] = nonce[idx]; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Produce the CBC IV */ ++ fh_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_m, "CBC IV in: ", "\n", 0); ++ show_block(block_x, "CBC IV out:", "\n", 0); ++ ++ /* Fill block B1 from l(a) = Blen + 14, and A */ ++ block_x[0] ^= (u8)(la >> 8); ++ block_x[1] ^= (u8)la; ++ for (idx = 0; idx < 14; idx++) ++ block_x[idx + 2] ^= label[idx]; ++ show_block(block_x, "After xor: ", "b1\n", 16); ++ ++ fh_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "b1\n", 16); ++ ++ idx = 0; ++ blkNum = 0; ++ ++ /* Fill remaining blocks with B */ ++ while (len-- > 0) { ++ block_x[idx] ^= *bytes++; ++ if (++idx >= 16) { ++ idx = 0; ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ fh_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ blkNum++; ++ } ++ } ++ ++ /* Handle partial last block */ ++ if (idx > 0) { ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ fh_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ } ++ ++ /* Save the MIC tag */ ++ FH_MEMCPY(block_t, block_x, 8); ++ show_block(block_t, "MIC tag : ", NULL, 8); ++ ++ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ ++ block_m[0] = 0x01; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Encrypt the counter */ ++ fh_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_x, "CTR[MIC] : ", NULL, 8); ++ ++ /* XOR with MIC tag */ ++ for (idx = 0; idx < 8; idx++) { ++ block_t[idx] ^= block_x[idx]; ++ } ++ ++ /* Return result to caller */ ++ FH_MEMCPY(result, block_t, 8); ++ show_block(result, "CCM-MIC : ", NULL, 8); ++ ++} ++ ++/** ++ * The PRF function described in section 6.5 of the WUSB spec. This function ++ * concatenates MIC values returned from fh_cmf() to create a value of ++ * the requested length. ++ * ++ * @param prf_len Length of the PRF function in bits (64, 128, or 256). ++ * @param key, nonce, label, bytes, len Same as for fh_cmf(). ++ * @param result Byte array to receive the result. ++ */ ++void fh_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) ++{ ++ int i; ++ ++ nonce[0] = 0; ++ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { ++ fh_wusb_cmf(key, nonce, label, bytes, len, result); ++ result += 8; ++ } ++} ++ ++/** ++ * Fills in CCM Nonce per the WUSB spec. ++ * ++ * @param[in] haddr Host address. ++ * @param[in] daddr Device address. ++ * @param[in] tkid Session Key(PTK) identifier. ++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. ++ */ ++void fh_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce) ++{ ++ ++ FH_DEBUG("%s %x %x\n", __func__, daddr, haddr); ++ ++ FH_MEMSET(&nonce[0], 0, 16); ++ ++ FH_MEMCPY(&nonce[6], tkid, 3); ++ nonce[9] = daddr & 0xFF; ++ nonce[10] = (daddr >> 8) & 0xFF; ++ nonce[11] = haddr & 0xFF; ++ nonce[12] = (haddr >> 8) & 0xFF; ++ ++ dump_bytes("CCM nonce", nonce, 16); ++} ++ ++/** ++ * Generates a 16-byte cryptographic-grade random number for the Host/Device ++ * Nonce. ++ */ ++void fh_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) ++{ ++ uint8_t inonce[16]; ++ uint32_t temp[4]; ++ ++ /* Fill in the Nonce */ ++ FH_MEMSET(&inonce[0], 0, sizeof(inonce)); ++ inonce[9] = addr & 0xFF; ++ inonce[10] = (addr >> 8) & 0xFF; ++ inonce[11] = inonce[9]; ++ inonce[12] = inonce[10]; ++ ++ /* Collect "randomness samples" */ ++ FH_RANDOM_BYTES((uint8_t *)temp, 16); ++ ++ fh_wusb_prf_128((uint8_t *)temp, nonce, ++ "Random Numbers", (uint8_t *)temp, sizeof(temp), ++ nonce); ++} ++ ++/** ++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the ++ * WUSB spec. ++ * ++ * @param[in] ccm_nonce Pointer to CCM Nonce. ++ * @param[in] mk Master Key to derive the session from ++ * @param[in] hnonce Pointer to Host Nonce. ++ * @param[in] dnonce Pointer to Device Nonce. ++ * @param[out] kck Pointer to where the KCK output is to be written. ++ * @param[out] ptk Pointer to where the PTK output is to be written. ++ */ ++void fh_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, ++ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) ++{ ++ uint8_t idata[32]; ++ uint8_t odata[32]; ++ ++ dump_bytes("ck", mk, 16); ++ dump_bytes("hnonce", hnonce, 16); ++ dump_bytes("dnonce", dnonce, 16); ++ ++ /* The data is the HNonce and DNonce concatenated */ ++ FH_MEMCPY(&idata[0], hnonce, 16); ++ FH_MEMCPY(&idata[16], dnonce, 16); ++ ++ fh_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); ++ ++ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ ++ FH_MEMCPY(kck, &odata[0], 16); ++ FH_MEMCPY(ptk, &odata[16], 16); ++ ++ dump_bytes("kck", kck, 16); ++ dump_bytes("ptk", ptk, 16); ++} ++ ++/** ++ * Generates the Message Integrity Code over the Handshake data per the ++ * WUSB spec. ++ * ++ * @param ccm_nonce Pointer to CCM Nonce. ++ * @param kck Pointer to Key Confirmation Key. ++ * @param data Pointer to Handshake data to be checked. ++ * @param mic Pointer to where the MIC output is to be written. ++ */ ++void fh_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, ++ uint8_t *data, uint8_t *mic) ++{ ++ ++ fh_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", ++ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); ++} ++ ++#endif /* FH_CRYPTOLIB */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.h b/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.h +new file mode 100644 +index 00000000..3e5cb9fb +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_crypto.h +@@ -0,0 +1,111 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_crypto.h $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++ ++#ifndef _FH_CRYPTO_H_ ++#define _FH_CRYPTO_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file contains declarations for the WUSB Cryptographic routines as ++ * defined in the WUSB spec. They are only to be used internally by the FH UWB ++ * modules. ++ */ ++ ++#include "fh_os.h" ++ ++int fh_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); ++ ++void fh_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result); ++void fh_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); ++ ++/** ++ * The PRF-64 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for fh_prf(). ++ */ ++static inline void fh_wusb_prf_64(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ fh_wusb_prf(64, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-128 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for fh_prf(). ++ */ ++static inline void fh_wusb_prf_128(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ fh_wusb_prf(128, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-256 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for fh_prf(). ++ */ ++static inline void fh_wusb_prf_256(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ fh_wusb_prf(256, key, nonce, label, bytes, len, result); ++} ++ ++ ++void fh_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce); ++void fh_wusb_gen_nonce(uint16_t addr, ++ uint8_t *nonce); ++ ++void fh_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, ++ uint8_t *hnonce, uint8_t *dnonce, ++ uint8_t *kck, uint8_t *ptk); ++ ++ ++void fh_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t ++ *kck, uint8_t *data, uint8_t *mic); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_CRYPTO_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_dh.c b/drivers/usb/host/fh_otg/fh_common_port/fh_dh.c +new file mode 100644 +index 00000000..502e2a95 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_dh.c +@@ -0,0 +1,291 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_dh.c $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifdef FH_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "fh_dh.h" ++#include "fh_modpow.h" ++ ++#ifdef DEBUG ++/* This function prints out a buffer in the format described in the Association ++ * Model specification. */ ++static void dh_dump(char *str, void *_num, int len) ++{ ++ uint8_t *num = _num; ++ int i; ++ FH_PRINTF("%s\n", str); ++ for (i = 0; i < len; i ++) { ++ FH_PRINTF("%02x", num[i]); ++ if (((i + 1) % 2) == 0) FH_PRINTF(" "); ++ if (((i + 1) % 26) == 0) FH_PRINTF("\n"); ++ } ++ ++ FH_PRINTF("\n"); ++} ++#else ++#define dh_dump(_x...) do {; } while(0) ++#endif ++ ++/* Constant g value */ ++static __u32 dh_g[] = { ++ 0x02000000, ++}; ++ ++/* Constant p value */ ++static __u32 dh_p[] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, ++ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, ++ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, ++ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, ++ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, ++ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, ++ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, ++ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, ++ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, ++ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, ++ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, ++ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, ++}; ++ ++static void dh_swap_bytes(void *_in, void *_out, uint32_t len) ++{ ++ uint8_t *in = _in; ++ uint8_t *out = _out; ++ int i; ++ for (i=0; i<len; i++) { ++ out[i] = in[len-1-i]; ++ } ++} ++ ++/* Computes the modular exponentiation (num^exp % mod). num, exp, and mod are ++ * big endian numbers of size len, in bytes. Each len value must be a multiple ++ * of 4. */ ++int fh_dh_modpow(void *mem_ctx, void *num, uint32_t num_len, ++ void *exp, uint32_t exp_len, ++ void *mod, uint32_t mod_len, ++ void *out) ++{ ++ /* modpow() takes little endian numbers. AM uses big-endian. This ++ * function swaps bytes of numbers before passing onto modpow. */ ++ ++ int retval = 0; ++ uint32_t *result; ++ ++ uint32_t *bignum_num = fh_alloc(mem_ctx, num_len + 4); ++ uint32_t *bignum_exp = fh_alloc(mem_ctx, exp_len + 4); ++ uint32_t *bignum_mod = fh_alloc(mem_ctx, mod_len + 4); ++ ++ dh_swap_bytes(num, &bignum_num[1], num_len); ++ bignum_num[0] = num_len / 4; ++ ++ dh_swap_bytes(exp, &bignum_exp[1], exp_len); ++ bignum_exp[0] = exp_len / 4; ++ ++ dh_swap_bytes(mod, &bignum_mod[1], mod_len); ++ bignum_mod[0] = mod_len / 4; ++ ++ result = fh_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod); ++ if (!result) { ++ retval = -1; ++ goto dh_modpow_nomem; ++ } ++ ++ dh_swap_bytes(&result[1], out, result[0] * 4); ++ fh_free(mem_ctx, result); ++ ++ dh_modpow_nomem: ++ fh_free(mem_ctx, bignum_num); ++ fh_free(mem_ctx, bignum_exp); ++ fh_free(mem_ctx, bignum_mod); ++ return retval; ++} ++ ++ ++int fh_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash) ++{ ++ int retval; ++ uint8_t m3[385]; ++ ++#ifndef DH_TEST_VECTORS ++ FH_RANDOM_BYTES(exp, 32); ++#endif ++ ++ /* Compute the pkd */ ++ if ((retval = fh_dh_modpow(mem_ctx, dh_g, 4, ++ exp, 32, ++ dh_p, 384, pk))) { ++ return retval; ++ } ++ ++ m3[384] = nd; ++ FH_MEMCPY(&m3[0], pk, 384); ++ FH_SHA256(m3, 385, hash); ++ ++ dh_dump("PK", pk, 384); ++ dh_dump("SHA-256(M3)", hash, 32); ++ return 0; ++} ++ ++int fh_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd, ++ uint8_t *exp, int is_host, ++ char *dd, uint8_t *ck, uint8_t *kdk) ++{ ++ int retval; ++ uint8_t mv[784]; ++ uint8_t sha_result[32]; ++ uint8_t dhkey[384]; ++ uint8_t shared_secret[384]; ++ char *message; ++ uint32_t vd; ++ ++ uint8_t *pk; ++ ++ if (is_host) { ++ pk = pkd; ++ } ++ else { ++ pk = pkh; ++ } ++ ++ if ((retval = fh_dh_modpow(mem_ctx, pk, 384, ++ exp, 32, ++ dh_p, 384, shared_secret))) { ++ return retval; ++ } ++ dh_dump("Shared Secret", shared_secret, 384); ++ ++ FH_SHA256(shared_secret, 384, dhkey); ++ dh_dump("DHKEY", dhkey, 384); ++ ++ FH_MEMCPY(&mv[0], pkd, 384); ++ FH_MEMCPY(&mv[384], pkh, 384); ++ FH_MEMCPY(&mv[768], "displayed digest", 16); ++ dh_dump("MV", mv, 784); ++ ++ FH_SHA256(mv, 784, sha_result); ++ dh_dump("SHA-256(MV)", sha_result, 32); ++ dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4); ++ ++ dh_swap_bytes(sha_result, &vd, 4); ++#ifdef DEBUG ++ FH_PRINTF("Vd (decimal) = %d\n", vd); ++#endif ++ ++ switch (nd) { ++ case 2: ++ vd = vd % 100; ++ FH_SPRINTF(dd, "%02d", vd); ++ break; ++ case 3: ++ vd = vd % 1000; ++ FH_SPRINTF(dd, "%03d", vd); ++ break; ++ case 4: ++ vd = vd % 10000; ++ FH_SPRINTF(dd, "%04d", vd); ++ break; ++ } ++#ifdef DEBUG ++ FH_PRINTF("Display Digits: %s\n", dd); ++#endif ++ ++ message = "connection key"; ++ FH_HMAC_SHA256(message, FH_STRLEN(message), dhkey, 32, sha_result); ++ dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32); ++ FH_MEMCPY(ck, sha_result, 16); ++ ++ message = "key derivation key"; ++ FH_HMAC_SHA256(message, FH_STRLEN(message), dhkey, 32, sha_result); ++ dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32); ++ FH_MEMCPY(kdk, sha_result, 32); ++ ++ return 0; ++} ++ ++ ++#ifdef DH_TEST_VECTORS ++ ++static __u8 dh_a[] = { ++ 0x44, 0x00, 0x51, 0xd6, ++ 0xf0, 0xb5, 0x5e, 0xa9, ++ 0x67, 0xab, 0x31, 0xc6, ++ 0x8a, 0x8b, 0x5e, 0x37, ++ 0xd9, 0x10, 0xda, 0xe0, ++ 0xe2, 0xd4, 0x59, 0xa4, ++ 0x86, 0x45, 0x9c, 0xaa, ++ 0xdf, 0x36, 0x75, 0x16, ++}; ++ ++static __u8 dh_b[] = { ++ 0x5d, 0xae, 0xc7, 0x86, ++ 0x79, 0x80, 0xa3, 0x24, ++ 0x8c, 0xe3, 0x57, 0x8f, ++ 0xc7, 0x5f, 0x1b, 0x0f, ++ 0x2d, 0xf8, 0x9d, 0x30, ++ 0x6f, 0xa4, 0x52, 0xcd, ++ 0xe0, 0x7a, 0x04, 0x8a, ++ 0xde, 0xd9, 0x26, 0x56, ++}; ++ ++void fh_run_dh_test_vectors(void *mem_ctx) ++{ ++ uint8_t pkd[384]; ++ uint8_t pkh[384]; ++ uint8_t hashd[32]; ++ uint8_t hashh[32]; ++ uint8_t ck[16]; ++ uint8_t kdk[32]; ++ char dd[5]; ++ ++ FH_PRINTF("\n\n\nDH_TEST_VECTORS\n\n"); ++ ++ /* compute the PKd and SHA-256(PKd || Nd) */ ++ FH_PRINTF("Computing PKd\n"); ++ fh_dh_pk(mem_ctx, 2, dh_a, pkd, hashd); ++ ++ /* compute the PKd and SHA-256(PKh || Nd) */ ++ FH_PRINTF("Computing PKh\n"); ++ fh_dh_pk(mem_ctx, 2, dh_b, pkh, hashh); ++ ++ /* compute the dhkey */ ++ fh_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk); ++} ++#endif /* DH_TEST_VECTORS */ ++ ++#endif /* !CONFIG_MACH_IPMATE */ ++ ++#endif /* FH_CRYPTOLIB */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_dh.h b/drivers/usb/host/fh_otg/fh_common_port/fh_dh.h +new file mode 100644 +index 00000000..c4c9ccca +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_dh.h +@@ -0,0 +1,106 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_dh.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifndef _FH_DH_H_ ++#define _FH_DH_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fh_os.h" ++ ++/** @file ++ * ++ * This file defines the common functions on device and host for performing ++ * numeric association as defined in the WUSB spec. They are only to be ++ * used internally by the FH UWB modules. */ ++ ++extern int fh_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out); ++extern int fh_dh_hmac_sha256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, ++ uint8_t *out); ++extern int fh_dh_modpow(void *mem_ctx, void *num, uint32_t num_len, ++ void *exp, uint32_t exp_len, ++ void *mod, uint32_t mod_len, ++ void *out); ++ ++/** Computes PKD or PKH, and SHA-256(PKd || Nd) ++ * ++ * PK = g^exp mod p. ++ * ++ * Input: ++ * Nd = Number of digits on the device. ++ * ++ * Output: ++ * exp = A 32-byte buffer to be filled with a randomly generated number. ++ * used as either A or B. ++ * pk = A 384-byte buffer to be filled with the PKH or PKD. ++ * hash = A 32-byte buffer to be filled with SHA-256(PK || ND). ++ */ ++extern int fh_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash); ++ ++/** Computes the DHKEY, and VD. ++ * ++ * If called from host, then it will comput DHKEY=PKD^exp % p. ++ * If called from device, then it will comput DHKEY=PKH^exp % p. ++ * ++ * Input: ++ * pkd = The PKD value. ++ * pkh = The PKH value. ++ * exp = The A value (if device) or B value (if host) generated in fh_wudev_dh_pk. ++ * is_host = Set to non zero if a WUSB host is calling this function. ++ * ++ * Output: ++ ++ * dd = A pointer to an buffer to be set to the displayed digits string to be shown ++ * to the user. This buffer should be at 5 bytes long to hold 4 digits plus a ++ * null termination character. This buffer can be used directly for display. ++ * ck = A 16-byte buffer to be filled with the CK. ++ * kdk = A 32-byte buffer to be filled with the KDK. ++ */ ++extern int fh_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd, ++ uint8_t *exp, int is_host, ++ char *dd, uint8_t *ck, uint8_t *kdk); ++ ++#ifdef DH_TEST_VECTORS ++extern void fh_run_dh_test_vectors(void); ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_DH_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_list.h b/drivers/usb/host/fh_otg/fh_common_port/fh_list.h +new file mode 100644 +index 00000000..11cbf687 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_list.h +@@ -0,0 +1,594 @@ ++/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */ ++/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ ++ ++/* ++ * Copyright (c) 1991, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * @(#)queue.h 8.5 (Berkeley) 8/20/94 ++ */ ++ ++#ifndef _FH_LIST_H_ ++#define _FH_LIST_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines linked list operations. It is derived from BSD with ++ * only the MACRO names being prefixed with FH_. This is because a few of ++ * these names conflict with those on Linux. For documentation on use, see the ++ * inline comments in the source code. The original license for this source ++ * code applies and is preserved in the fh_list.h source file. ++ */ ++ ++/* ++ * This file defines five types of data structures: singly-linked lists, ++ * lists, simple queues, tail queues, and circular queues. ++ * ++ * ++ * A singly-linked list is headed by a single forward pointer. The elements ++ * are singly linked for minimum space and pointer manipulation overhead at ++ * the expense of O(n) removal for arbitrary elements. New elements can be ++ * added to the list after an existing element or at the head of the list. ++ * Elements being removed from the head of the list should use the explicit ++ * macro for this purpose for optimum efficiency. A singly-linked list may ++ * only be traversed in the forward direction. Singly-linked lists are ideal ++ * for applications with large datasets and few or no removals or for ++ * implementing a LIFO queue. ++ * ++ * A list is headed by a single forward pointer (or an array of forward ++ * pointers for a hash table header). The elements are doubly linked ++ * so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before ++ * or after an existing element or at the head of the list. A list ++ * may only be traversed in the forward direction. ++ * ++ * A simple queue is headed by a pair of pointers, one the head of the ++ * list and the other to the tail of the list. The elements are singly ++ * linked to save space, so elements can only be removed from the ++ * head of the list. New elements can be added to the list before or after ++ * an existing element, at the head of the list, or at the end of the ++ * list. A simple queue may only be traversed in the forward direction. ++ * ++ * A tail queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or ++ * after an existing element, at the head of the list, or at the end of ++ * the list. A tail queue may be traversed in either direction. ++ * ++ * A circle queue is headed by a pair of pointers, one to the head of the ++ * list and the other to the tail of the list. The elements are doubly ++ * linked so that an arbitrary element can be removed without a need to ++ * traverse the list. New elements can be added to the list before or after ++ * an existing element, at the head of the list, or at the end of the list. ++ * A circle queue may be traversed in either direction, but has a more ++ * complex end of list detection. ++ * ++ * For details on the use of these macros, see the queue(3) manual page. ++ */ ++ ++/* ++ * Double-linked List. ++ */ ++ ++typedef struct fh_list_link { ++ struct fh_list_link *next; ++ struct fh_list_link *prev; ++} fh_list_link_t; ++ ++#define FH_LIST_INIT(link) do { \ ++ (link)->next = (link); \ ++ (link)->prev = (link); \ ++} while (0) ++ ++#define FH_LIST_FIRST(link) ((link)->next) ++#define FH_LIST_LAST(link) ((link)->prev) ++#define FH_LIST_END(link) (link) ++#define FH_LIST_NEXT(link) ((link)->next) ++#define FH_LIST_PREV(link) ((link)->prev) ++#define FH_LIST_EMPTY(link) \ ++ (FH_LIST_FIRST(link) == FH_LIST_END(link)) ++#define FH_LIST_ENTRY(link, type, field) \ ++ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) ++ ++#if 0 ++#define FH_LIST_INSERT_HEAD(list, link) do { \ ++ (link)->next = (list)->next; \ ++ (link)->prev = (list); \ ++ (list)->next->prev = (link); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define FH_LIST_INSERT_TAIL(list, link) do { \ ++ (link)->next = (list); \ ++ (link)->prev = (list)->prev; \ ++ (list)->prev->next = (link); \ ++ (list)->prev = (link); \ ++} while (0) ++#else ++#define FH_LIST_INSERT_HEAD(list, link) do { \ ++ fh_list_link_t *__next__ = (list)->next; \ ++ __next__->prev = (link); \ ++ (link)->next = __next__; \ ++ (link)->prev = (list); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define FH_LIST_INSERT_TAIL(list, link) do { \ ++ fh_list_link_t *__prev__ = (list)->prev; \ ++ (list)->prev = (link); \ ++ (link)->next = (list); \ ++ (link)->prev = __prev__; \ ++ __prev__->next = (link); \ ++} while (0) ++#endif ++ ++#if 0 ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ entry->next = LIST_POISON1; ++ entry->prev = LIST_POISON2; ++} ++#endif ++ ++#define FH_LIST_REMOVE(link) do { \ ++ (link)->next->prev = (link)->prev; \ ++ (link)->prev->next = (link)->next; \ ++} while (0) ++ ++#define FH_LIST_REMOVE_INIT(link) do { \ ++ FH_LIST_REMOVE(link); \ ++ FH_LIST_INIT(link); \ ++} while (0) ++ ++#define FH_LIST_MOVE_HEAD(list, link) do { \ ++ FH_LIST_REMOVE(link); \ ++ FH_LIST_INSERT_HEAD(list, link); \ ++} while (0) ++ ++#define FH_LIST_MOVE_TAIL(list, link) do { \ ++ FH_LIST_REMOVE(link); \ ++ FH_LIST_INSERT_TAIL(list, link); \ ++} while (0) ++ ++#define FH_LIST_FOREACH(var, list) \ ++ for((var) = FH_LIST_FIRST(list); \ ++ (var) != FH_LIST_END(list); \ ++ (var) = FH_LIST_NEXT(var)) ++ ++#define FH_LIST_FOREACH_SAFE(var, var2, list) \ ++ for((var) = FH_LIST_FIRST(list), (var2) = FH_LIST_NEXT(var); \ ++ (var) != FH_LIST_END(list); \ ++ (var) = (var2), (var2) = FH_LIST_NEXT(var2)) ++ ++#define FH_LIST_FOREACH_REVERSE(var, list) \ ++ for((var) = FH_LIST_LAST(list); \ ++ (var) != FH_LIST_END(list); \ ++ (var) = FH_LIST_PREV(var)) ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define FH_SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define FH_SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define FH_SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define FH_SLIST_FIRST(head) ((head)->slh_first) ++#define FH_SLIST_END(head) NULL ++#define FH_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) ++#define FH_SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define FH_SLIST_FOREACH(var, head, field) \ ++ for((var) = SLIST_FIRST(head); \ ++ (var) != SLIST_END(head); \ ++ (var) = SLIST_NEXT(var, field)) ++ ++#define FH_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ ++ ((var) = *(varp)) != SLIST_END(head); \ ++ (varp) = &SLIST_NEXT((var), field)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define FH_SLIST_INIT(head) { \ ++ SLIST_FIRST(head) = SLIST_END(head); \ ++} ++ ++#define FH_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (0) ++ ++#define FH_SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (0) ++ ++#define FH_SLIST_REMOVE_NEXT(head, elm, field) do { \ ++ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ ++} while (0) ++ ++#define FH_SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (0) ++ ++#define FH_SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while( curelm->field.sle_next != (elm) ) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (0) ++ ++/* ++ * Simple queue definitions. ++ */ ++#define FH_SIMPLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *sqh_first; /* first element */ \ ++ struct type **sqh_last; /* addr of last next element */ \ ++} ++ ++#define FH_SIMPLEQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).sqh_first } ++ ++#define FH_SIMPLEQ_ENTRY(type) \ ++struct { \ ++ struct type *sqe_next; /* next element */ \ ++} ++ ++/* ++ * Simple queue access methods. ++ */ ++#define FH_SIMPLEQ_FIRST(head) ((head)->sqh_first) ++#define FH_SIMPLEQ_END(head) NULL ++#define FH_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) ++#define FH_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) ++ ++#define FH_SIMPLEQ_FOREACH(var, head, field) \ ++ for((var) = SIMPLEQ_FIRST(head); \ ++ (var) != SIMPLEQ_END(head); \ ++ (var) = SIMPLEQ_NEXT(var, field)) ++ ++/* ++ * Simple queue functions. ++ */ ++#define FH_SIMPLEQ_INIT(head) do { \ ++ (head)->sqh_first = NULL; \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++#define FH_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (head)->sqh_first = (elm); \ ++} while (0) ++ ++#define FH_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.sqe_next = NULL; \ ++ *(head)->sqh_last = (elm); \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++} while (0) ++ ++#define FH_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (listelm)->field.sqe_next = (elm); \ ++} while (0) ++ ++#define FH_SIMPLEQ_REMOVE_HEAD(head, field) do { \ ++ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++/* ++ * Tail queue definitions. ++ */ ++#define FH_TAILQ_HEAD(name, type) \ ++struct name { \ ++ struct type *tqh_first; /* first element */ \ ++ struct type **tqh_last; /* addr of last next element */ \ ++} ++ ++#define FH_TAILQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).tqh_first } ++ ++#define FH_TAILQ_ENTRY(type) \ ++struct { \ ++ struct type *tqe_next; /* next element */ \ ++ struct type **tqe_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * tail queue access methods ++ */ ++#define FH_TAILQ_FIRST(head) ((head)->tqh_first) ++#define FH_TAILQ_END(head) NULL ++#define FH_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define FH_TAILQ_LAST(head, headname) \ ++ (*(((struct headname *)((head)->tqh_last))->tqh_last)) ++/* XXX */ ++#define FH_TAILQ_PREV(elm, headname, field) \ ++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) ++#define FH_TAILQ_EMPTY(head) \ ++ (TAILQ_FIRST(head) == TAILQ_END(head)) ++ ++#define FH_TAILQ_FOREACH(var, head, field) \ ++ for((var) = TAILQ_FIRST(head); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_NEXT(var, field)) ++ ++#define FH_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ ++ for((var) = TAILQ_LAST(head, headname); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_PREV(var, headname, field)) ++ ++/* ++ * Tail queue functions. ++ */ ++#define FH_TAILQ_INIT(head) do { \ ++ (head)->tqh_first = NULL; \ ++ (head)->tqh_last = &(head)->tqh_first; \ ++} while (0) ++ ++#define FH_TAILQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ ++ (head)->tqh_first->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (head)->tqh_first = (elm); \ ++ (elm)->field.tqe_prev = &(head)->tqh_first; \ ++} while (0) ++ ++#define FH_TAILQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.tqe_next = NULL; \ ++ (elm)->field.tqe_prev = (head)->tqh_last; \ ++ *(head)->tqh_last = (elm); \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define FH_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (listelm)->field.tqe_next = (elm); \ ++ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ ++} while (0) ++ ++#define FH_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ ++ (elm)->field.tqe_next = (listelm); \ ++ *(listelm)->field.tqe_prev = (elm); \ ++ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define FH_TAILQ_REMOVE(head, elm, field) do { \ ++ if (((elm)->field.tqe_next) != NULL) \ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ (elm)->field.tqe_prev; \ ++ else \ ++ (head)->tqh_last = (elm)->field.tqe_prev; \ ++ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ ++} while (0) ++ ++#define FH_TAILQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ ++ (elm2)->field.tqe_next->field.tqe_prev = \ ++ &(elm2)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm2)->field.tqe_next; \ ++ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ ++ *(elm2)->field.tqe_prev = (elm2); \ ++} while (0) ++ ++/* ++ * Circular queue definitions. ++ */ ++#define FH_CIRCLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *cqh_first; /* first element */ \ ++ struct type *cqh_last; /* last element */ \ ++} ++ ++#define FH_CIRCLEQ_HEAD_INITIALIZER(head) \ ++ { FH_CIRCLEQ_END(&head), FH_CIRCLEQ_END(&head) } ++ ++#define FH_CIRCLEQ_ENTRY(type) \ ++struct { \ ++ struct type *cqe_next; /* next element */ \ ++ struct type *cqe_prev; /* previous element */ \ ++} ++ ++/* ++ * Circular queue access methods ++ */ ++#define FH_CIRCLEQ_FIRST(head) ((head)->cqh_first) ++#define FH_CIRCLEQ_LAST(head) ((head)->cqh_last) ++#define FH_CIRCLEQ_END(head) ((void *)(head)) ++#define FH_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) ++#define FH_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) ++#define FH_CIRCLEQ_EMPTY(head) \ ++ (FH_CIRCLEQ_FIRST(head) == FH_CIRCLEQ_END(head)) ++ ++#define FH_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) ++ ++#define FH_CIRCLEQ_FOREACH(var, head, field) \ ++ for((var) = FH_CIRCLEQ_FIRST(head); \ ++ (var) != FH_CIRCLEQ_END(head); \ ++ (var) = FH_CIRCLEQ_NEXT(var, field)) ++ ++#define FH_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = FH_CIRCLEQ_FIRST(head), var2 = FH_CIRCLEQ_NEXT(var, field); \ ++ (var) != FH_CIRCLEQ_END(head); \ ++ (var) = var2, var2 = FH_CIRCLEQ_NEXT(var, field)) ++ ++#define FH_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ ++ for((var) = FH_CIRCLEQ_LAST(head); \ ++ (var) != FH_CIRCLEQ_END(head); \ ++ (var) = FH_CIRCLEQ_PREV(var, field)) ++ ++/* ++ * Circular queue functions. ++ */ ++#define FH_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = FH_CIRCLEQ_END(head); \ ++ (head)->cqh_last = FH_CIRCLEQ_END(head); \ ++} while (0) ++ ++#define FH_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ ++} while (0) ++ ++#define FH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ ++ (elm)->field.cqe_prev = (listelm); \ ++ if ((listelm)->field.cqe_next == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ ++ (listelm)->field.cqe_next = (elm); \ ++} while (0) ++ ++#define FH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm); \ ++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ ++ if ((listelm)->field.cqe_prev == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ ++ (listelm)->field.cqe_prev = (elm); \ ++} while (0) ++ ++#define FH_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.cqe_next = (head)->cqh_first; \ ++ (elm)->field.cqe_prev = FH_CIRCLEQ_END(head); \ ++ if ((head)->cqh_last == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (head)->cqh_first->field.cqe_prev = (elm); \ ++ (head)->cqh_first = (elm); \ ++} while (0) ++ ++#define FH_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.cqe_next = FH_CIRCLEQ_END(head); \ ++ (elm)->field.cqe_prev = (head)->cqh_last; \ ++ if ((head)->cqh_first == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (head)->cqh_last->field.cqe_next = (elm); \ ++ (head)->cqh_last = (elm); \ ++} while (0) ++ ++#define FH_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm)->field.cqe_prev; \ ++ else \ ++ (elm)->field.cqe_next->field.cqe_prev = \ ++ (elm)->field.cqe_prev; \ ++ if ((elm)->field.cqe_prev == FH_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm)->field.cqe_next; \ ++ else \ ++ (elm)->field.cqe_prev->field.cqe_next = \ ++ (elm)->field.cqe_next; \ ++} while (0) ++ ++#define FH_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ FH_CIRCLEQ_REMOVE(head, elm, field); \ ++ FH_CIRCLEQ_INIT_ENTRY(elm, field); \ ++} while (0) ++ ++#define FH_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ ++ FH_CIRCLEQ_END(head)) \ ++ (head).cqh_last = (elm2); \ ++ else \ ++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ ++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ ++ FH_CIRCLEQ_END(head)) \ ++ (head).cqh_first = (elm2); \ ++ else \ ++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ ++} while (0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_LIST_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_mem.c b/drivers/usb/host/fh_otg/fh_common_port/fh_mem.c +new file mode 100644 +index 00000000..d7fedb34 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_mem.c +@@ -0,0 +1,245 @@ ++/* Memory Debugging */ ++#ifdef FH_DEBUG_MEMORY ++ ++#include "fh_os.h" ++#include "fh_list.h" ++ ++struct allocation { ++ void *addr; ++ void *ctx; ++ char *func; ++ int line; ++ uint32_t size; ++ int dma; ++ FH_CIRCLEQ_ENTRY(allocation) entry; ++}; ++ ++FH_CIRCLEQ_HEAD(allocation_queue, allocation); ++ ++struct allocation_manager { ++ void *mem_ctx; ++ struct allocation_queue allocations; ++ ++ /* statistics */ ++ int num; ++ int num_freed; ++ int num_active; ++ uint32_t total; ++ uint32_t cur; ++ uint32_t max; ++}; ++ ++static struct allocation_manager *manager = NULL; ++ ++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, ++ int dma) ++{ ++ struct allocation *a; ++ ++ FH_ASSERT(manager != NULL, "manager not allocated"); ++ ++ a = __FH_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); ++ if (!a) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ a->func = __FH_ALLOC_ATOMIC(manager->mem_ctx, FH_STRLEN(func) + 1); ++ if (!a->func) { ++ __FH_FREE(manager->mem_ctx, a); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ FH_MEMCPY(a->func, func, FH_STRLEN(func) + 1); ++ a->addr = addr; ++ a->ctx = ctx; ++ a->line = line; ++ a->size = size; ++ a->dma = dma; ++ FH_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); ++ ++ /* Update stats */ ++ manager->num++; ++ manager->num_active++; ++ manager->total += size; ++ manager->cur += size; ++ ++ if (manager->max < manager->cur) { ++ manager->max = manager->cur; ++ } ++ ++ return 0; ++} ++ ++static struct allocation *find_allocation(void *ctx, void *addr) ++{ ++ struct allocation *a; ++ ++ FH_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ if (a->ctx == ctx && a->addr == addr) { ++ return a; ++ } ++ } ++ ++ return NULL; ++} ++ ++static void free_allocation(void *ctx, void *addr, char const *func, int line) ++{ ++ struct allocation *a = find_allocation(ctx, addr); ++ ++ if (!a) { ++ FH_ASSERT(0, ++ "Free of address %p that was never allocated or already freed %s:%d", ++ addr, func, line); ++ return; ++ } ++ ++ FH_CIRCLEQ_REMOVE(&manager->allocations, a, entry); ++ ++ manager->num_active--; ++ manager->num_freed++; ++ manager->cur -= a->size; ++ __FH_FREE(manager->mem_ctx, a->func); ++ __FH_FREE(manager->mem_ctx, a); ++} ++ ++int fh_memory_debug_start(void *mem_ctx) ++{ ++ FH_ASSERT(manager == NULL, "Memory debugging has already started\n"); ++ ++ if (manager) { ++ return -FH_E_BUSY; ++ } ++ ++ manager = __FH_ALLOC(mem_ctx, sizeof(*manager)); ++ if (!manager) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ FH_CIRCLEQ_INIT(&manager->allocations); ++ manager->mem_ctx = mem_ctx; ++ manager->num = 0; ++ manager->num_freed = 0; ++ manager->num_active = 0; ++ manager->total = 0; ++ manager->cur = 0; ++ manager->max = 0; ++ ++ return 0; ++} ++ ++void fh_memory_debug_stop(void) ++{ ++ struct allocation *a; ++ ++ fh_memory_debug_report(); ++ ++ FH_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ FH_ERROR("Memory leaked from %s:%d\n", a->func, a->line); ++ free_allocation(a->ctx, a->addr, NULL, -1); ++ } ++ ++ __FH_FREE(manager->mem_ctx, manager); ++} ++ ++void fh_memory_debug_report(void) ++{ ++ struct allocation *a; ++ ++ FH_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); ++ FH_PRINTF("Num Allocations = %d\n", manager->num); ++ FH_PRINTF("Freed = %d\n", manager->num_freed); ++ FH_PRINTF("Active = %d\n", manager->num_active); ++ FH_PRINTF("Current Memory Used = %d\n", manager->cur); ++ FH_PRINTF("Total Memory Used = %d\n", manager->total); ++ FH_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); ++ FH_PRINTF("Unfreed allocations:\n"); ++ ++ FH_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ FH_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", ++ a->addr, a->size, a->func, a->line, a->dma); ++ } ++} ++ ++/* The replacement functions */ ++void *fh_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) ++{ ++ void *addr = __FH_ALLOC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __FH_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *fh_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, ++ int line) ++{ ++ void *addr = __FH_ALLOC_ATOMIC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __FH_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void fh_free_debug(void *mem_ctx, void *addr, char const *func, int line) ++{ ++ free_allocation(mem_ctx, addr, func, line); ++ __FH_FREE(mem_ctx, addr); ++} ++ ++void *fh_dma_alloc_debug(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr, ++ char const *func, int line) ++{ ++ void *addr = __FH_DMA_ALLOC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __FH_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *fh_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, ++ fh_dma_t *dma_addr, char const *func, int line) ++{ ++ void *addr = __FH_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __FH_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void fh_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ fh_dma_t dma_addr, char const *func, int line) ++{ ++ free_allocation(dma_ctx, virt_addr, func, line); ++ __FH_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++#endif /* FH_DEBUG_MEMORY */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.c b/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.c +new file mode 100644 +index 00000000..625495c7 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.c +@@ -0,0 +1,634 @@ ++/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. ++ * ++ * PuTTY is copyright 1997-2007 Simon Tatham. ++ * ++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian ++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, ++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus ++ * Kuhn, and CORE SDI S.A. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE ++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF ++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifdef FH_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include <asm/div64.h> ++#include "fh_modpow.h" ++ ++#define BIGNUM_INT_MASK 0xFFFFFFFFUL ++#define BIGNUM_TOP_BIT 0x80000000UL ++#define BIGNUM_INT_BITS 32 ++ ++ ++static void *snmalloc(void *mem_ctx, size_t n, size_t size) ++{ ++ void *p; ++ size *= n; ++ if (size == 0) size = 1; ++ p = fh_alloc(mem_ctx, size); ++ return p; ++} ++ ++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) ++#define sfree fh_free ++ ++/* ++ * Usage notes: ++ * * Do not call the DIVMOD_WORD macro with expressions such as array ++ * subscripts, as some implementations object to this (see below). ++ * * Note that none of the division methods below will cope if the ++ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful ++ * to avoid this case. ++ * If this condition occurs, in the case of the x86 DIV instruction, ++ * an overflow exception will occur, which (according to a correspondent) ++ * will manifest on Windows as something like ++ * 0xC0000095: Integer overflow ++ * The C variant won't give the right answer, either. ++ */ ++ ++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) ++ ++#if defined __GNUC__ && defined __i386__ ++#define DIVMOD_WORD(q, r, hi, lo, w) \ ++ __asm__("div %2" : \ ++ "=d" (r), "=a" (q) : \ ++ "r" (w), "d" (hi), "a" (lo)) ++#else ++#define DIVMOD_WORD(q, r, hi, lo, w) do { \ ++ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ ++ r = do_div(n, w); \ ++ q = n; \ ++} while (0) ++#endif ++ ++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) ++ ++#define BIGNUM_INTERNAL ++ ++static Bignum newbn(void *mem_ctx, int length) ++{ ++ Bignum b = snewn(mem_ctx, length + 1, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ FH_MEMSET(b, 0, (length + 1) * sizeof(*b)); ++ b[0] = length; ++ return b; ++} ++ ++void freebn(void *mem_ctx, Bignum b) ++{ ++ /* ++ * Burn the evidence, just in case. ++ */ ++ FH_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); ++ sfree(mem_ctx, b); ++} ++ ++/* ++ * Compute c = a * b. ++ * Input is in the first len words of a and b. ++ * Result is returned in the first 2*len words of c. ++ */ ++static void internal_mul(BignumInt *a, BignumInt *b, ++ BignumInt *c, int len) ++{ ++ int i, j; ++ BignumDblInt t; ++ ++ for (j = 0; j < 2 * len; j++) ++ c[j] = 0; ++ ++ for (i = len - 1; i >= 0; i--) { ++ t = 0; ++ for (j = len - 1; j >= 0; j--) { ++ t += MUL_WORD(a[i], (BignumDblInt) b[j]); ++ t += (BignumDblInt) c[i + j + 1]; ++ c[i + j + 1] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ c[i] = (BignumInt) t; ++ } ++} ++ ++static void internal_add_shifted(BignumInt *number, ++ unsigned n, int shift) ++{ ++ int word = 1 + (shift / BIGNUM_INT_BITS); ++ int bshift = shift % BIGNUM_INT_BITS; ++ BignumDblInt addend; ++ ++ addend = (BignumDblInt)n << bshift; ++ ++ while (addend) { ++ addend += number[word]; ++ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; ++ addend >>= BIGNUM_INT_BITS; ++ word++; ++ } ++} ++ ++/* ++ * Compute a = a % m. ++ * Input in first alen words of a and first mlen words of m. ++ * Output in first alen words of a ++ * (of which first alen-mlen words will be zero). ++ * The MSW of m MUST have its high bit set. ++ * Quotient is accumulated in the `quotient' array, which is a Bignum ++ * rather than the internal bigendian format. Quotient parts are shifted ++ * left by `qshift' before adding into quot. ++ */ ++static void internal_mod(BignumInt *a, int alen, ++ BignumInt *m, int mlen, ++ BignumInt *quot, int qshift) ++{ ++ BignumInt m0, m1; ++ unsigned int h; ++ int i, k; ++ ++ m0 = m[0]; ++ if (mlen > 1) ++ m1 = m[1]; ++ else ++ m1 = 0; ++ ++ for (i = 0; i <= alen - mlen; i++) { ++ BignumDblInt t; ++ unsigned int q, r, c, ai1; ++ ++ if (i == 0) { ++ h = 0; ++ } else { ++ h = a[i - 1]; ++ a[i - 1] = 0; ++ } ++ ++ if (i == alen - 1) ++ ai1 = 0; ++ else ++ ai1 = a[i + 1]; ++ ++ /* Find q = h:a[i] / m0 */ ++ if (h >= m0) { ++ /* ++ * Special case. ++ * ++ * To illustrate it, suppose a BignumInt is 8 bits, and ++ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then ++ * our initial division will be 0xA123 / 0xA1, which ++ * will give a quotient of 0x100 and a divide overflow. ++ * However, the invariants in this division algorithm ++ * are not violated, since the full number A1:23:... is ++ * _less_ than the quotient prefix A1:B2:... and so the ++ * following correction loop would have sorted it out. ++ * ++ * In this situation we set q to be the largest ++ * quotient we _can_ stomach (0xFF, of course). ++ */ ++ q = BIGNUM_INT_MASK; ++ } else { ++ /* Macro doesn't want an array subscript expression passed ++ * into it (see definition), so use a temporary. */ ++ BignumInt tmplo = a[i]; ++ DIVMOD_WORD(q, r, h, tmplo, m0); ++ ++ /* Refine our estimate of q by looking at ++ h:a[i]:a[i+1] / m0:m1 */ ++ t = MUL_WORD(m1, q); ++ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { ++ q--; ++ t -= m1; ++ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ ++ if (r >= (BignumDblInt) m0 && ++ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; ++ } ++ } ++ ++ /* Subtract q * m from a[i...] */ ++ c = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t = MUL_WORD(q, m[k]); ++ t += c; ++ c = (unsigned)(t >> BIGNUM_INT_BITS); ++ if ((BignumInt) t > a[i + k]) ++ c++; ++ a[i + k] -= (BignumInt) t; ++ } ++ ++ /* Add back m in case of borrow */ ++ if (c != h) { ++ t = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t += m[k]; ++ t += a[i + k]; ++ a[i + k] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ q--; ++ } ++ if (quot) ++ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); ++ } ++} ++ ++/* ++ * Compute p % mod. ++ * The most significant word of mod MUST be non-zero. ++ * We assume that the result array is the same size as the mod array. ++ * We optionally write out a quotient if `quotient' is non-NULL. ++ * We can avoid writing out the result if `result' is NULL. ++ */ ++void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) ++{ ++ BignumInt *n, *m; ++ int mshift; ++ int plen, mlen, i, j; ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ plen = p[0]; ++ /* Ensure plen > mlen */ ++ if (plen <= mlen) ++ plen = mlen + 1; ++ ++ /* Allocate n of size plen, copy p to n */ ++ n = snewn(mem_ctx, plen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ for (j = 0; j < plen; j++) ++ n[j] = 0; ++ for (j = 1; j <= (int)p[0]; j++) ++ n[plen - j] = p[j]; ++ ++ /* Main computation */ ++ internal_mod(n, plen, m, mlen, quotient, mshift); ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = plen - mlen - 1; i < plen - 1; i++) ++ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ n[plen - 1] = n[plen - 1] << mshift; ++ internal_mod(n, plen, m, mlen, quotient, 0); ++ for (i = plen - 1; i >= plen - mlen; i--) ++ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ if (result) { ++ for (i = 1; i <= (int)result[0]; i++) { ++ int j = plen - i; ++ result[i] = j >= 0 ? n[j] : 0; ++ } ++ } ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < plen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++} ++ ++/* ++ * Simple remainder. ++ */ ++Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) ++{ ++ Bignum r = newbn(mem_ctx, b[0]); ++ bigdivmod(mem_ctx, a, b, r, NULL); ++ return r; ++} ++ ++/* ++ * Compute (base ^ exp) % mod. ++ */ ++Bignum fh_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) ++{ ++ BignumInt *a, *b, *n, *m; ++ int mshift; ++ int mlen, i, j; ++ Bignum base, result; ++ ++ /* ++ * The most significant word of mod needs to be non-zero. It ++ * should already be, but let's make sure. ++ */ ++ //assert(mod[mod[0]] != 0); ++ ++ /* ++ * Make sure the base is smaller than the modulus, by reducing ++ * it modulo the modulus if not. ++ */ ++ base = bigmod(mem_ctx, base_in, mod); ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = ++ (m[i] << mshift) | (m[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ /* Allocate n of size mlen, copy base to n */ ++ n = snewn(mem_ctx, mlen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ i = mlen - base[0]; ++ for (j = 0; j < i; j++) ++ n[j] = 0; ++ for (j = 0; j < base[0]; j++) ++ n[i + j] = base[base[0] - j]; ++ ++ /* Allocate a and b of size 2*mlen. Set a = 1 */ ++ a = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!a) ++ //abort(); /* FIXME */ ++ b = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ a[2 * mlen - 1] = 1; ++ ++ /* Skip leading zero bits of exp. */ ++ i = 0; ++ j = BIGNUM_INT_BITS - 1; ++ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { ++ j--; ++ if (j < 0) { ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ } ++ ++ /* Main computation */ ++ while (i < exp[0]) { ++ while (j >= 0) { ++ internal_mul(a + mlen, a + mlen, b, mlen); ++ internal_mod(b, mlen * 2, m, mlen, NULL, 0); ++ if ((exp[exp[0] - i] & (1 << j)) != 0) { ++ internal_mul(b + mlen, n, a, mlen); ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ } else { ++ BignumInt *t; ++ t = a; ++ a = b; ++ b = t; ++ } ++ j--; ++ } ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = mlen - 1; i < 2 * mlen - 1; i++) ++ a[i] = ++ (a[i] << mshift) | (a[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ for (i = 2 * mlen - 1; i >= mlen; i--) ++ a[i] = ++ (a[i] >> mshift) | (a[i - 1] << ++ (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ result = newbn(mem_ctx, mod[0]); ++ for (i = 0; i < mlen; i++) ++ result[result[0] - i] = a[i + mlen]; ++ while (result[0] > 1 && result[result[0]] == 0) ++ result[0]--; ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ sfree(mem_ctx, a); ++ for (i = 0; i < 2 * mlen; i++) ++ b[i] = 0; ++ sfree(mem_ctx, b); ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < mlen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++ ++ freebn(mem_ctx, base); ++ ++ return result; ++} ++ ++ ++#ifdef UNITTEST ++ ++static __u32 dh_p[] = { ++ 96, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++ 0xA93AD2CA, ++ 0x4B82D120, ++ 0xE0FD108E, ++ 0x43DB5BFC, ++ 0x74E5AB31, ++ 0x08E24FA0, ++ 0xBAD946E2, ++ 0x770988C0, ++ 0x7A615D6C, ++ 0xBBE11757, ++ 0x177B200C, ++ 0x521F2B18, ++ 0x3EC86A64, ++ 0xD8760273, ++ 0xD98A0864, ++ 0xF12FFA06, ++ 0x1AD2EE6B, ++ 0xCEE3D226, ++ 0x4A25619D, ++ 0x1E8C94E0, ++ 0xDB0933D7, ++ 0xABF5AE8C, ++ 0xA6E1E4C7, ++ 0xB3970F85, ++ 0x5D060C7D, ++ 0x8AEA7157, ++ 0x58DBEF0A, ++ 0xECFB8504, ++ 0xDF1CBA64, ++ 0xA85521AB, ++ 0x04507A33, ++ 0xAD33170D, ++ 0x8AAAC42D, ++ 0x15728E5A, ++ 0x98FA0510, ++ 0x15D22618, ++ 0xEA956AE5, ++ 0x3995497C, ++ 0x95581718, ++ 0xDE2BCBF6, ++ 0x6F4C52C9, ++ 0xB5C55DF0, ++ 0xEC07A28F, ++ 0x9B2783A2, ++ 0x180E8603, ++ 0xE39E772C, ++ 0x2E36CE3B, ++ 0x32905E46, ++ 0xCA18217C, ++ 0xF1746C08, ++ 0x4ABC9804, ++ 0x670C354E, ++ 0x7096966D, ++ 0x9ED52907, ++ 0x208552BB, ++ 0x1C62F356, ++ 0xDCA3AD96, ++ 0x83655D23, ++ 0xFD24CF5F, ++ 0x69163FA8, ++ 0x1C55D39A, ++ 0x98DA4836, ++ 0xA163BF05, ++ 0xC2007CB8, ++ 0xECE45B3D, ++ 0x49286651, ++ 0x7C4B1FE6, ++ 0xAE9F2411, ++ 0x5A899FA5, ++ 0xEE386BFB, ++ 0xF406B7ED, ++ 0x0BFF5CB6, ++ 0xA637ED6B, ++ 0xF44C42E9, ++ 0x625E7EC6, ++ 0xE485B576, ++ 0x6D51C245, ++ 0x4FE1356D, ++ 0xF25F1437, ++ 0x302B0A6D, ++ 0xCD3A431B, ++ 0xEF9519B3, ++ 0x8E3404DD, ++ 0x514A0879, ++ 0x3B139B22, ++ 0x020BBEA6, ++ 0x8A67CC74, ++ 0x29024E08, ++ 0x80DC1CD1, ++ 0xC4C6628B, ++ 0x2168C234, ++ 0xC90FDAA2, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++}; ++ ++static __u32 dh_a[] = { ++ 8, ++ 0xdf367516, ++ 0x86459caa, ++ 0xe2d459a4, ++ 0xd910dae0, ++ 0x8a8b5e37, ++ 0x67ab31c6, ++ 0xf0b55ea9, ++ 0x440051d6, ++}; ++ ++static __u32 dh_b[] = { ++ 8, ++ 0xded92656, ++ 0xe07a048a, ++ 0x6fa452cd, ++ 0x2df89d30, ++ 0xc75f1b0f, ++ 0x8ce3578f, ++ 0x7980a324, ++ 0x5daec786, ++}; ++ ++static __u32 dh_g[] = { ++ 1, ++ 2, ++}; ++ ++int main(void) ++{ ++ int i; ++ __u32 *k; ++ k = fh_modpow(NULL, dh_g, dh_a, dh_p); ++ ++ printf("\n\n"); ++ for (i=0; i<k[0]; i++) { ++ __u32 word32 = k[k[0] - i]; ++ __u16 l = word32 & 0xffff; ++ __u16 m = (word32 & 0xffff0000) >> 16; ++ printf("%04x %04x ", m, l); ++ if (!((i + 1)%13)) printf("\n"); ++ } ++ printf("\n\n"); ++ ++ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { ++ printf("PASS\n\n"); ++ } ++ else { ++ printf("FAIL\n\n"); ++ } ++ ++} ++ ++#endif /* UNITTEST */ ++ ++#endif /* CONFIG_MACH_IPMATE */ ++ ++#endif /*FH_CRYPTOLIB */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.h b/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.h +new file mode 100644 +index 00000000..96cdb551 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_modpow.h +@@ -0,0 +1,34 @@ ++/* ++ * fh_modpow.h ++ * See fh_modpow.c for license and changes ++ */ ++#ifndef _FH_MODPOW_H ++#define _FH_MODPOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fh_os.h" ++ ++/** @file ++ * ++ * This file defines the module exponentiation function which is only used ++ * internally by the FH UWB modules for calculation of PKs during numeric ++ * association. The routine is taken from the PUTTY, an open source terminal ++ * emulator. The PUTTY License is preserved in the fh_modpow.c file. ++ * ++ */ ++ ++typedef uint32_t BignumInt; ++typedef uint64_t BignumDblInt; ++typedef BignumInt *Bignum; ++ ++/* Compute modular exponentiaion */ ++extern Bignum fh_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LINUX_BIGNUM_H */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.c b/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.c +new file mode 100644 +index 00000000..a2878fe2 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.c +@@ -0,0 +1,319 @@ ++#ifdef FH_NOTIFYLIB ++ ++#include "fh_notifier.h" ++#include "fh_list.h" ++ ++typedef struct fh_observer { ++ void *observer; ++ fh_notifier_callback_t callback; ++ void *data; ++ char *notification; ++ FH_CIRCLEQ_ENTRY(fh_observer) list_entry; ++} observer_t; ++ ++FH_CIRCLEQ_HEAD(observer_queue, fh_observer); ++ ++typedef struct fh_notifier { ++ void *mem_ctx; ++ void *object; ++ struct observer_queue observers; ++ FH_CIRCLEQ_ENTRY(fh_notifier) list_entry; ++} notifier_t; ++ ++FH_CIRCLEQ_HEAD(notifier_queue, fh_notifier); ++ ++typedef struct manager { ++ void *mem_ctx; ++ void *wkq_ctx; ++ fh_workq_t *wq; ++// fh_mutex_t *mutex; ++ struct notifier_queue notifiers; ++} manager_t; ++ ++static manager_t *manager = NULL; ++ ++static int create_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ manager = fh_alloc(mem_ctx, sizeof(manager_t)); ++ if (!manager) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ FH_CIRCLEQ_INIT(&manager->notifiers); ++ ++ manager->wq = fh_workq_alloc(wkq_ctx, "FH Notification WorkQ"); ++ if (!manager->wq) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ return 0; ++} ++ ++static void free_manager(void) ++{ ++ fh_workq_free(manager->wq); ++ ++ /* All notifiers must have unregistered themselves before this module ++ * can be removed. Hitting this assertion indicates a programmer ++ * error. */ ++ FH_ASSERT(FH_CIRCLEQ_EMPTY(&manager->notifiers), ++ "Notification manager being freed before all notifiers have been removed"); ++ fh_free(manager->mem_ctx, manager); ++} ++ ++#ifdef DEBUG ++static void dump_manager(void) ++{ ++ notifier_t *n; ++ observer_t *o; ++ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ FH_DEBUG("List of all notifiers and observers:\n"); ++ FH_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ FH_DEBUG("Notifier %p has observers:\n", n->object); ++ FH_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { ++ FH_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ } ++} ++#else ++#define dump_manager(...) ++#endif ++ ++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, ++ fh_notifier_callback_t callback, void *data) ++{ ++ observer_t *new_observer = fh_alloc(mem_ctx, sizeof(observer_t)); ++ ++ if (!new_observer) { ++ return NULL; ++ } ++ ++ FH_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); ++ new_observer->observer = observer; ++ new_observer->notification = notification; ++ new_observer->callback = callback; ++ new_observer->data = data; ++ return new_observer; ++} ++ ++static void free_observer(void *mem_ctx, observer_t *observer) ++{ ++ fh_free(mem_ctx, observer); ++} ++ ++static notifier_t *alloc_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ notifier = fh_alloc(mem_ctx, sizeof(notifier_t)); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ FH_CIRCLEQ_INIT(¬ifier->observers); ++ FH_CIRCLEQ_INIT_ENTRY(notifier, list_entry); ++ ++ notifier->mem_ctx = mem_ctx; ++ notifier->object = object; ++ return notifier; ++} ++ ++static void free_notifier(notifier_t *notifier) ++{ ++ observer_t *observer; ++ ++ FH_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { ++ free_observer(notifier->mem_ctx, observer); ++ } ++ ++ fh_free(notifier->mem_ctx, notifier); ++} ++ ++static notifier_t *find_notifier(void *object) ++{ ++ notifier_t *notifier; ++ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ FH_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { ++ if (notifier->object == object) { ++ return notifier; ++ } ++ } ++ ++ return NULL; ++} ++ ++int fh_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ return create_manager(mem_ctx, wkq_ctx); ++} ++ ++void fh_free_notification_manager(void) ++{ ++ free_manager(); ++} ++ ++fh_notifier_t *fh_register_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ notifier = find_notifier(object); ++ if (notifier) { ++ FH_ERROR("Notifier %p is already registered\n", object); ++ return NULL; ++ } ++ ++ notifier = alloc_notifier(mem_ctx, object); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ FH_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); ++ ++ FH_INFO("Notifier %p registered", object); ++ dump_manager(); ++ ++ return notifier; ++} ++ ++void fh_unregister_notifier(fh_notifier_t *notifier) ++{ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ if (!FH_CIRCLEQ_EMPTY(¬ifier->observers)) { ++ observer_t *o; ++ ++ FH_ERROR("Notifier %p has active observers when removing\n", notifier->object); ++ FH_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ FH_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ ++ FH_ASSERT(FH_CIRCLEQ_EMPTY(¬ifier->observers), ++ "Notifier %p has active observers when removing", notifier); ++ } ++ ++ FH_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); ++ free_notifier(notifier); ++ ++ FH_INFO("Notifier unregistered"); ++ dump_manager(); ++} ++ ++/* Add an observer to observe the notifier for a particular state, event, or notification. */ ++int fh_add_observer(void *observer, void *object, char *notification, ++ fh_notifier_callback_t callback, void *data) ++{ ++ notifier_t *notifier = find_notifier(object); ++ observer_t *new_observer; ++ ++ if (!notifier) { ++ FH_ERROR("Notifier %p is not found when adding observer\n", object); ++ return -FH_E_INVALID; ++ } ++ ++ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); ++ if (!new_observer) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ FH_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); ++ ++ FH_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p", ++ observer, object, notification, callback, data); ++ ++ dump_manager(); ++ return 0; ++} ++ ++int fh_remove_observer(void *observer) ++{ ++ notifier_t *n; ++ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ FH_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ observer_t *o; ++ observer_t *o2; ++ ++ FH_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { ++ if (o->observer == observer) { ++ FH_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); ++ FH_INFO("Removing observer %p from notifier %p watching notification %s:", ++ o->observer, n->object, o->notification); ++ free_observer(n->mem_ctx, o); ++ } ++ } ++ } ++ ++ dump_manager(); ++ return 0; ++} ++ ++typedef struct callback_data { ++ void *mem_ctx; ++ fh_notifier_callback_t cb; ++ void *observer; ++ void *data; ++ void *object; ++ char *notification; ++ void *notification_data; ++} cb_data_t; ++ ++static void cb_task(void *data) ++{ ++ cb_data_t *cb = (cb_data_t *)data; ++ ++ cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); ++ fh_free(cb->mem_ctx, cb); ++} ++ ++void fh_notify(fh_notifier_t *notifier, char *notification, void *notification_data) ++{ ++ observer_t *o; ++ ++ FH_ASSERT(manager, "Notification manager not found"); ++ ++ FH_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ int len = FH_STRLEN(notification); ++ ++ if (FH_STRLEN(o->notification) != len) { ++ continue; ++ } ++ ++ if (FH_STRNCMP(o->notification, notification, len) == 0) { ++ cb_data_t *cb_data = fh_alloc(notifier->mem_ctx, sizeof(cb_data_t)); ++ ++ if (!cb_data) { ++ FH_ERROR("Failed to allocate callback data\n"); ++ return; ++ } ++ ++ cb_data->mem_ctx = notifier->mem_ctx; ++ cb_data->cb = o->callback; ++ cb_data->observer = o->observer; ++ cb_data->data = o->data; ++ cb_data->object = notifier->object; ++ cb_data->notification = notification; ++ cb_data->notification_data = notification_data; ++ FH_DEBUG("Observer found %p for notification %s\n", o->observer, notification); ++ FH_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, ++ "Notify callback from %p for Notification %s, to observer %p", ++ cb_data->object, notification, cb_data->observer); ++ } ++ } ++} ++ ++#endif /* FH_NOTIFYLIB */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.h b/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.h +new file mode 100644 +index 00000000..97386291 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_notifier.h +@@ -0,0 +1,122 @@ ++ ++#ifndef __FH_NOTIFIER_H__ ++#define __FH_NOTIFIER_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fh_os.h" ++ ++/** @file ++ * ++ * A simple implementation of the Observer pattern. Any "module" can ++ * register as an observer or notifier. The notion of "module" is abstract and ++ * can mean anything used to identify either an observer or notifier. Usually ++ * it will be a pointer to a data structure which contains some state, ie an ++ * object. ++ * ++ * Before any notifiers can be added, the global notification manager must be ++ * brought up with fh_alloc_notification_manager(). ++ * fh_free_notification_manager() will bring it down and free all resources. ++ * These would typically be called upon module load and unload. The ++ * notification manager is a single global instance that handles all registered ++ * observable modules and observers so this should be done only once. ++ * ++ * A module can be observable by using Notifications to publicize some general ++ * information about it's state or operation. It does not care who listens, or ++ * even if anyone listens, or what they do with the information. The observable ++ * modules do not need to know any information about it's observers or their ++ * interface, or their state or data. ++ * ++ * Any module can register to emit Notifications. It should publish a list of ++ * notifications that it can emit and their behavior, such as when they will get ++ * triggered, and what information will be provided to the observer. Then it ++ * should register itself as an observable module. See fh_register_notifier(). ++ * ++ * Any module can observe any observable, registered module, provided it has a ++ * handle to the other module and knows what notifications to observe. See ++ * fh_add_observer(). ++ * ++ * A function of type fh_notifier_callback_t is called whenever a notification ++ * is triggered with one or more observers observing it. This function is ++ * called in it's own process so it may sleep or block if needed. It is ++ * guaranteed to be called sometime after the notification has occurred and will ++ * be called once per each time the notification is triggered. It will NOT be ++ * called in the same process context used to trigger the notification. ++ * ++ * @section Limitiations ++ * ++ * Keep in mind that Notifications that can be triggered in rapid sucession may ++ * schedule too many processes too handle. Be aware of this limitation when ++ * designing to use notifications, and only add notifications for appropriate ++ * observable information. ++ * ++ * Also Notification callbacks are not synchronous. If you need to synchronize ++ * the behavior between module/observer you must use other means. And perhaps ++ * that will mean Notifications are not the proper solution. ++ */ ++ ++struct fh_notifier; ++typedef struct fh_notifier fh_notifier_t; ++ ++/** The callback function must be of this type. ++ * ++ * @param object This is the object that is being observed. ++ * @param notification This is the notification that was triggered. ++ * @param observer This is the observer ++ * @param notification_data This is notification-specific data that the notifier ++ * has included in this notification. The value of this should be published in ++ * the documentation of the observable module with the notifications. ++ * @param user_data This is any custom data that the observer provided when ++ * adding itself as an observer to the notification. */ ++typedef void (*fh_notifier_callback_t)(void *object, char *notification, void *observer, ++ void *notification_data, void *user_data); ++ ++/** Brings up the notification manager. */ ++extern int fh_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); ++/** Brings down the notification manager. */ ++extern void fh_free_notification_manager(void); ++ ++/** This function registers an observable module. A fh_notifier_t object is ++ * returned to the observable module. This is an opaque object that is used by ++ * the observable module to trigger notifications. This object should only be ++ * accessible to functions that are authorized to trigger notifications for this ++ * module. Observers do not need this object. */ ++extern fh_notifier_t *fh_register_notifier(void *mem_ctx, void *object); ++ ++/** This function unregisters an observable module. All observers have to be ++ * removed prior to unregistration. */ ++extern void fh_unregister_notifier(fh_notifier_t *notifier); ++ ++/** Add a module as an observer to the observable module. The observable module ++ * needs to have previously registered with the notification manager. ++ * ++ * @param observer The observer module ++ * @param object The module to observe ++ * @param notification The notification to observe ++ * @param callback The callback function to call ++ * @param user_data Any additional user data to pass into the callback function */ ++extern int fh_add_observer(void *observer, void *object, char *notification, ++ fh_notifier_callback_t callback, void *user_data); ++ ++/** Removes the specified observer from all notifications that it is currently ++ * observing. */ ++extern int fh_remove_observer(void *observer); ++ ++/** This function triggers a Notification. It should be called by the ++ * observable module, or any module or library which the observable module ++ * allows to trigger notification on it's behalf. Such as the fh_cc_t. ++ * ++ * fh_notify is a non-blocking function. Callbacks are scheduled called in ++ * their own process context for each trigger. Callbacks can be blocking. ++ * fh_notify can be called from interrupt context if needed. ++ * ++ */ ++void fh_notify(fh_notifier_t *notifier, char *notification, void *notification_data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __FH_NOTIFIER_H__ */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/fh_os.h b/drivers/usb/host/fh_otg/fh_common_port/fh_os.h +new file mode 100644 +index 00000000..d73ab583 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/fh_os.h +@@ -0,0 +1,1245 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/fh_common_port_2/fh_os.h $ ++ * $Revision: #15 $ ++ * $Date: 2015/06/12 $ ++ * $Change: 2859407 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifndef _FH_OS_H_ ++#define _FH_OS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * FH portability library, low level os-wrapper functions ++ * ++ */ ++ ++/* These basic types need to be defined by some OS header file or custom header ++ * file for your specific target architecture. ++ * ++ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t ++ * ++ * Any custom or alternate header file must be added and enabled here. ++ */ ++ ++#ifdef FH_LINUX ++# include <linux/types.h> ++# ifdef CONFIG_DEBUG_MUTEXES ++# include <linux/mutex.h> ++# endif ++# include <linux/errno.h> ++# include <stdarg.h> ++#endif ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++# include <os_dep.h> ++#endif ++ ++ ++/** @name Primitive Types and Values */ ++ ++/** We define a boolean type for consistency. Can be either YES or NO */ ++typedef uint8_t fh_bool_t; ++#define YES 1 ++#define NO 0 ++ ++#ifdef FH_LINUX ++ ++/** @name Error Codes */ ++#define FH_E_INVALID EINVAL ++#define FH_E_NO_MEMORY ENOMEM ++#define FH_E_NO_DEVICE ENODEV ++#define FH_E_NOT_SUPPORTED EOPNOTSUPP ++#define FH_E_TIMEOUT ETIMEDOUT ++#define FH_E_BUSY EBUSY ++#define FH_E_AGAIN EAGAIN ++#define FH_E_RESTART ERESTART ++#define FH_E_ABORT ECONNABORTED ++#define FH_E_SHUTDOWN ESHUTDOWN ++#define FH_E_NO_DATA ENODATA ++#define FH_E_DISCONNECT ECONNRESET ++#define FH_E_UNKNOWN EINVAL ++#define FH_E_NO_STREAM_RES ENOSR ++#define FH_E_COMMUNICATION ECOMM ++#define FH_E_OVERFLOW EOVERFLOW ++#define FH_E_PROTOCOL EPROTO ++#define FH_E_IN_PROGRESS EINPROGRESS ++#define FH_E_PIPE EPIPE ++#define FH_E_IO EIO ++#define FH_E_NO_SPACE ENOSPC ++ ++#else ++ ++/** @name Error Codes */ ++#define FH_E_INVALID 1001 ++#define FH_E_NO_MEMORY 1002 ++#define FH_E_NO_DEVICE 1003 ++#define FH_E_NOT_SUPPORTED 1004 ++#define FH_E_TIMEOUT 1005 ++#define FH_E_BUSY 1006 ++#define FH_E_AGAIN 1007 ++#define FH_E_RESTART 1008 ++#define FH_E_ABORT 1009 ++#define FH_E_SHUTDOWN 1010 ++#define FH_E_NO_DATA 1011 ++#define FH_E_DISCONNECT 2000 ++#define FH_E_UNKNOWN 3000 ++#define FH_E_NO_STREAM_RES 4001 ++#define FH_E_COMMUNICATION 4002 ++#define FH_E_OVERFLOW 4003 ++#define FH_E_PROTOCOL 4004 ++#define FH_E_IN_PROGRESS 4005 ++#define FH_E_PIPE 4006 ++#define FH_E_IO 4007 ++#define FH_E_NO_SPACE 4008 ++ ++#endif ++ ++ ++/** @name Tracing/Logging Functions ++ * ++ * These function provide the capability to add tracing, debugging, and error ++ * messages, as well exceptions as assertions. The WUDEV uses these ++ * extensively. These could be logged to the main console, the serial port, an ++ * internal buffer, etc. These functions could also be no-op if they are too ++ * expensive on your system. By default undefining the DEBUG macro already ++ * no-ops some of these functions. */ ++ ++/** Returns non-zero if in interrupt context. */ ++extern fh_bool_t FH_IN_IRQ(void); ++#define fh_in_irq FH_IN_IRQ ++ ++/** Returns "IRQ" if FH_IN_IRQ is true. */ ++static inline char *fh_irq(void) { ++ return FH_IN_IRQ() ? "IRQ" : ""; ++} ++ ++/** Returns non-zero if in bottom-half context. */ ++extern fh_bool_t FH_IN_BH(void); ++#define fh_in_bh FH_IN_BH ++ ++/** Returns "BH" if FH_IN_BH is true. */ ++static inline char *fh_bh(void) { ++ return FH_IN_BH() ? "BH" : ""; ++} ++ ++/** ++ * A vprintf() clone. Just call vprintf if you've got it. ++ */ ++extern void FH_VPRINTF(char *format, va_list args); ++#define fh_vprintf FH_VPRINTF ++ ++/** ++ * A vsnprintf() clone. Just call vprintf if you've got it. ++ */ ++extern int FH_VSNPRINTF(char *str, int size, char *format, va_list args); ++#define fh_vsnprintf FH_VSNPRINTF ++ ++/** ++ * printf() clone. Just call printf if you've go it. ++ */ ++extern void FH_PRINTF(char *format, ...) ++/* This provides compiler level static checking of the parameters if you're ++ * using GCC. */ ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define fh_printf FH_PRINTF ++ ++/** ++ * sprintf() clone. Just call sprintf if you've got it. ++ */ ++extern int FH_SPRINTF(char *string, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 2, 3))); ++#else ++ ; ++#endif ++#define fh_sprintf FH_SPRINTF ++ ++/** ++ * snprintf() clone. Just call snprintf if you've got it. ++ */ ++extern int FH_SNPRINTF(char *string, int size, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 3, 4))); ++#else ++ ; ++#endif ++#define fh_snprintf FH_SNPRINTF ++ ++/** ++ * Prints a WARNING message. On systems that don't differentiate between ++ * warnings and regular log messages, just print it. Indicates that something ++ * may be wrong with the driver. Works like printf(). ++ * ++ * Use the FH_WARN macro to call this function. ++ */ ++extern void __FH_WARN(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an error message. On systems that don't differentiate between errors ++ * and regular log messages, just print it. Indicates that something went wrong ++ * with the driver. Works like printf(). ++ * ++ * Use the FH_ERROR macro to call this function. ++ */ ++extern void __FH_ERROR(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an exception error message and takes some user-defined action such as ++ * print out a backtrace or trigger a breakpoint. Indicates that something went ++ * abnormally wrong with the driver such as programmer error, or other ++ * exceptional condition. It should not be ignored so even on systems without ++ * printing capability, some action should be taken to notify the developer of ++ * it. Works like printf(). ++ */ ++extern void FH_EXCEPTION(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define fh_exception FH_EXCEPTION ++ ++#ifdef DEBUG ++/** ++ * Prints out a debug message. Used for logging/trace messages. ++ * ++ * Use the FH_DEBUG macro to call this function ++ */ ++extern void __FH_DEBUG(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#else ++#define __FH_DEBUG(...) ++#endif ++ ++/** ++ * Prints out a Debug message. ++ */ ++#define FH_DEBUG(_format, _args...) __FH_DEBUG("DEBUG:%s:%s: " _format "\n", \ ++ __func__, fh_irq(), ## _args) ++#define fh_debug FH_DEBUG ++/** ++ * Prints out an informative message. ++ */ ++#define FH_INFO(_format, _args...) FH_PRINTF("INFO:%s: " _format "\n", \ ++ fh_irq(), ## _args) ++#define fh_info FH_INFO ++/** ++ * Prints out a warning message. ++ */ ++#define FH_WARN(_format, _args...) __FH_WARN("WARN:%s:%s:%d: " _format "\n", \ ++ fh_irq(), __func__, __LINE__, ## _args) ++#define fh_warn FH_WARN ++/** ++ * Prints out an error message. ++ */ ++#define FH_ERROR(_format, _args...) __FH_ERROR("ERROR:%s:%s:%d: " _format "\n", \ ++ fh_irq(), __func__, __LINE__, ## _args) ++#define fh_error FH_ERROR ++ ++#define FH_PROTO_ERROR(_format, _args...) __FH_WARN("ERROR:%s:%s:%d: " _format "\n", \ ++ fh_irq(), __func__, __LINE__, ## _args) ++#define fh_proto_error FH_PROTO_ERROR ++ ++#ifdef DEBUG ++/** Prints out a exception error message if the _expr expression fails. Disabled ++ * if DEBUG is not enabled. */ ++#define FH_ASSERT(_expr, _format, _args...) do { \ ++ if (!(_expr)) { FH_EXCEPTION("%s:%s:%d: " _format "\n", fh_irq(), \ ++ __FILE__, __LINE__, ## _args); } \ ++ } while (0) ++#else ++#define FH_ASSERT(_x...) ++#endif ++#define fh_assert FH_ASSERT ++ ++ ++/** @name Byte Ordering ++ * The following functions are for conversions between processor's byte ordering ++ * and specific ordering you want. ++ */ ++ ++/** Converts 32 bit data in CPU byte ordering to little endian. */ ++extern uint32_t FH_CPU_TO_LE32(uint32_t *p); ++#define fh_cpu_to_le32 FH_CPU_TO_LE32 ++ ++/** Converts 32 bit data in CPU byte orderint to big endian. */ ++extern uint32_t FH_CPU_TO_BE32(uint32_t *p); ++#define fh_cpu_to_be32 FH_CPU_TO_BE32 ++ ++/** Converts 32 bit little endian data to CPU byte ordering. */ ++extern uint32_t FH_LE32_TO_CPU(uint32_t *p); ++#define fh_le32_to_cpu FH_LE32_TO_CPU ++ ++/** Converts 32 bit big endian data to CPU byte ordering. */ ++extern uint32_t FH_BE32_TO_CPU(uint32_t *p); ++#define fh_be32_to_cpu FH_BE32_TO_CPU ++ ++/** Converts 16 bit data in CPU byte ordering to little endian. */ ++extern uint16_t FH_CPU_TO_LE16(uint16_t *p); ++#define fh_cpu_to_le16 FH_CPU_TO_LE16 ++ ++/** Converts 16 bit data in CPU byte orderint to big endian. */ ++extern uint16_t FH_CPU_TO_BE16(uint16_t *p); ++#define fh_cpu_to_be16 FH_CPU_TO_BE16 ++ ++/** Converts 16 bit little endian data to CPU byte ordering. */ ++extern uint16_t FH_LE16_TO_CPU(uint16_t *p); ++#define fh_le16_to_cpu FH_LE16_TO_CPU ++ ++/** Converts 16 bit bi endian data to CPU byte ordering. */ ++extern uint16_t FH_BE16_TO_CPU(uint16_t *p); ++#define fh_be16_to_cpu FH_BE16_TO_CPU ++ ++ ++/** @name Register Read/Write ++ * ++ * The following six functions should be implemented to read/write registers of ++ * 32-bit and 64-bit sizes. All modules use this to read/write register values. ++ * The reg value is a pointer to the register calculated from the void *base ++ * variable passed into the driver when it is started. */ ++ ++#ifdef FH_LINUX ++/* Linux doesn't need any extra parameters for register read/write, so we ++ * just throw away the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t FH_READ_REG32(uint32_t volatile *reg); ++#define fh_read_reg32(_ctx_,_reg_) FH_READ_REG32(_reg_) ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t FH_READ_REG64(uint64_t volatile *reg); ++#define fh_read_reg64(_ctx_,_reg_) FH_READ_REG64(_reg_) ++ ++/** Writes to a 32-bit register. */ ++extern void FH_WRITE_REG32(uint32_t volatile *reg, uint32_t value); ++#define fh_write_reg32(_ctx_,_reg_,_val_) FH_WRITE_REG32(_reg_, _val_) ++ ++/** Writes to a 64-bit register. */ ++extern void FH_WRITE_REG64(uint64_t volatile *reg, uint64_t value); ++#define fh_write_reg64(_ctx_,_reg_,_val_) FH_WRITE_REG64(_reg_, _val_) ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void FH_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define fh_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) FH_MODIFY_REG32(_reg_,_cmsk_,_smsk_) ++extern void FH_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define fh_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) FH_MODIFY_REG64(_reg_,_cmsk_,_smsk_) ++ ++#endif /* FH_LINUX */ ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++typedef struct fh_ioctx { ++ struct device *dev; ++ bus_space_tag_t iot; ++ bus_space_handle_t ioh; ++} fh_ioctx_t; ++ ++/** BSD needs two extra parameters for register read/write, so we pass ++ * them in using the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t FH_READ_REG32(void *io_ctx, uint32_t volatile *reg); ++#define fh_read_reg32 FH_READ_REG32 ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t FH_READ_REG64(void *io_ctx, uint64_t volatile *reg); ++#define fh_read_reg64 FH_READ_REG64 ++ ++/** Writes to a 32-bit register. */ ++extern void FH_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); ++#define fh_write_reg32 FH_WRITE_REG32 ++ ++/** Writes to a 64-bit register. */ ++extern void FH_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); ++#define fh_write_reg64 FH_WRITE_REG64 ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void FH_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define fh_modify_reg32 FH_MODIFY_REG32 ++extern void FH_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define fh_modify_reg64 FH_MODIFY_REG64 ++ ++#endif /* FH_FREEBSD || FH_NETBSD */ ++ ++/** @cond */ ++ ++/** @name Some convenience MACROS used internally. Define FH_DEBUG_REGS to log the ++ * register writes. */ ++ ++#ifdef FH_LINUX ++ ++# ifdef FH_DEBUG_REGS ++ ++#define fh_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg##_n(_container_type *container, int num) { \ ++ return FH_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void fh_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ FH_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ FH_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define fh_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg(_container_type *container) { \ ++ return FH_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void fh_write_##_reg(_container_type *container, uint32_t data) { \ ++ FH_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ FH_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# else /* FH_DEBUG_REGS */ ++ ++#define fh_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg##_n(_container_type *container, int num) { \ ++ return FH_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void fh_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ FH_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define fh_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg(_container_type *container) { \ ++ return FH_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void fh_write_##_reg(_container_type *container, uint32_t data) { \ ++ FH_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# endif /* FH_DEBUG_REGS */ ++ ++#endif /* FH_LINUX */ ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++ ++# ifdef FH_DEBUG_REGS ++ ++#define fh_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return FH_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void fh_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ FH_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ FH_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define fh_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return FH_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void fh_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ FH_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ FH_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# else /* FH_DEBUG_REGS */ ++ ++#define fh_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return FH_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void fh_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ FH_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define fh_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t fh_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return FH_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void fh_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ FH_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# endif /* FH_DEBUG_REGS */ ++ ++#endif /* FH_FREEBSD || FH_NETBSD */ ++ ++/** @endcond */ ++ ++ ++#ifdef FH_CRYPTOLIB ++/** @name Crypto Functions ++ * ++ * These are the low-level cryptographic functions used by the driver. */ ++ ++/** Perform AES CBC */ ++extern int FH_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); ++#define fh_aes_cbc FH_AES_CBC ++ ++/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ ++extern void FH_RANDOM_BYTES(uint8_t *buffer, uint32_t length); ++#define fh_random_bytes FH_RANDOM_BYTES ++ ++/** Perform the SHA-256 hash function */ ++extern int FH_SHA256(uint8_t *message, uint32_t len, uint8_t *out); ++#define fh_sha256 FH_SHA256 ++ ++/** Calculated the HMAC-SHA256 */ ++extern int FH_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); ++#define fh_hmac_sha256 FH_HMAC_SHA256 ++ ++#endif /* FH_CRYPTOLIB */ ++ ++ ++/** @name Memory Allocation ++ * ++ * These function provide access to memory allocation. There are only 2 DMA ++ * functions and 3 Regular memory functions that need to be implemented. None ++ * of the memory debugging routines need to be implemented. The allocation ++ * routines all ZERO the contents of the memory. ++ * ++ * Defining FH_DEBUG_MEMORY turns on memory debugging and statistic gathering. ++ * This checks for memory leaks, keeping track of alloc/free pairs. It also ++ * keeps track of how much memory the driver is using at any given time. */ ++ ++#define FH_PAGE_SIZE 4096 ++#define FH_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff) ++#define FH_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0) ++ ++#define FH_INVALID_DMA_ADDR 0x0 ++ ++#ifdef FH_LINUX ++/** Type for a DMA address */ ++typedef dma_addr_t fh_dma_t; ++#endif ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++typedef bus_addr_t fh_dma_t; ++#endif ++ ++#ifdef FH_FREEBSD ++typedef struct fh_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} fh_dmactx_t; ++#endif ++ ++#ifdef FH_NETBSD ++typedef struct fh_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_dma_segment_t segs[1]; ++ int nsegs; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} fh_dmactx_t; ++#endif ++ ++/* @todo these functions will be added in the future */ ++#if 0 ++/** ++ * Creates a DMA pool from which you can allocate DMA buffers. Buffers ++ * allocated from this pool will be guaranteed to meet the size, alignment, and ++ * boundary requirements specified. ++ * ++ * @param[in] size Specifies the size of the buffers that will be allocated from ++ * this pool. ++ * @param[in] align Specifies the byte alignment requirements of the buffers ++ * allocated from this pool. Must be a power of 2. ++ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from ++ * this pool must not cross. ++ * ++ * @returns A pointer to an internal opaque structure which is not to be ++ * accessed outside of these library functions. Use this handle to specify ++ * which pools to allocate/free DMA buffers from and also to destroy the pool, ++ * when you are done with it. ++ */ ++extern fh_pool_t *FH_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); ++ ++/** ++ * Destroy a DMA pool. All buffers allocated from that pool must be freed first. ++ */ ++extern void FH_DMA_POOL_DESTROY(fh_pool_t *pool); ++ ++/** ++ * Allocate a buffer from the specified DMA pool and zeros its contents. ++ */ ++extern void *FH_DMA_POOL_ALLOC(fh_pool_t *pool, uint64_t *dma_addr); ++ ++/** ++ * Free a previously allocated buffer from the DMA pool. ++ */ ++extern void FH_DMA_POOL_FREE(fh_pool_t *pool, void *vaddr, void *daddr); ++#endif ++ ++/** Allocates a DMA capable buffer and zeroes its contents. */ ++extern void *__FH_DMA_ALLOC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr); ++ ++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ ++extern void *__FH_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr); ++ ++/** Frees a previously allocated buffer. */ ++extern void __FH_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, fh_dma_t dma_addr); ++ ++/** Allocates a block of memory and zeroes its contents. */ ++extern void *__FH_ALLOC(void *mem_ctx, uint32_t size); ++ ++/** Allocates a block of memory and zeroes its contents, in an atomic manner ++ * which can be used inside interrupt context. The size should be sufficiently ++ * small, a few KB at most, such that failures are not likely to occur. Can just call ++ * __FH_ALLOC if it is atomic. */ ++extern void *__FH_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); ++ ++/** Frees a previously allocated buffer. */ ++extern void __FH_FREE(void *mem_ctx, void *addr); ++ ++#ifndef FH_DEBUG_MEMORY ++ ++#define FH_ALLOC(_size_) __FH_ALLOC(NULL, _size_) ++#define FH_ALLOC_ATOMIC(_size_) __FH_ALLOC_ATOMIC(NULL, _size_) ++#define FH_FREE(_addr_) __FH_FREE(NULL, _addr_) ++ ++# ifdef FH_LINUX ++#define FH_DMA_ALLOC(_size_,_dma_) __FH_DMA_ALLOC(NULL, _size_, _dma_) ++#define FH_DMA_ALLOC_ATOMIC(_size_,_dma_) __FH_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) ++#define FH_DMA_FREE(_size_,_virt_,_dma_) __FH_DMA_FREE(NULL, _size_, _virt_, _dma_) ++# endif ++ ++# if defined(FH_FREEBSD) || defined(FH_NETBSD) ++#define FH_DMA_ALLOC __FH_DMA_ALLOC ++#define FH_DMA_FREE __FH_DMA_FREE ++# endif ++ ++#else /* FH_DEBUG_MEMORY */ ++ ++extern void *fh_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void *fh_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void fh_free_debug(void *mem_ctx, void *addr, char const *func, int line); ++extern void *fh_dma_alloc_debug(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr, ++ char const *func, int line); ++extern void *fh_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, fh_dma_t *dma_addr, ++ char const *func, int line); ++extern void fh_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ fh_dma_t dma_addr, char const *func, int line); ++ ++extern int fh_memory_debug_start(void *mem_ctx); ++extern void fh_memory_debug_stop(void); ++extern void fh_memory_debug_report(void); ++ ++#define FH_ALLOC(_size_) fh_alloc_debug(NULL, _size_, __func__, __LINE__) ++#define FH_ALLOC_ATOMIC(_size_) fh_alloc_atomic_debug(NULL, _size_, \ ++ __func__, __LINE__) ++#define FH_FREE(_addr_) fh_free_debug(NULL, _addr_, __func__, __LINE__) ++ ++# ifdef FH_LINUX ++#define FH_DMA_ALLOC(_size_,_dma_) fh_dma_alloc_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define FH_DMA_ALLOC_ATOMIC(_size_,_dma_) fh_dma_alloc_atomic_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define FH_DMA_FREE(_size_,_virt_,_dma_) fh_dma_free_debug(NULL, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++# if defined(FH_FREEBSD) || defined(FH_NETBSD) ++#define FH_DMA_ALLOC(_ctx_,_size_,_dma_) fh_dma_alloc_debug(_ctx_, _size_, \ ++ _dma_, __func__, __LINE__) ++#define FH_DMA_FREE(_ctx_,_size_,_virt_,_dma_) fh_dma_free_debug(_ctx_, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++#endif /* FH_DEBUG_MEMORY */ ++ ++#define fh_alloc(_ctx_,_size_) FH_ALLOC(_size_) ++#define fh_alloc_atomic(_ctx_,_size_) FH_ALLOC_ATOMIC(_size_) ++#define fh_free(_ctx_,_addr_) FH_FREE(_addr_) ++ ++#ifdef FH_LINUX ++/* Linux doesn't need any extra parameters for DMA buffer allocation, so we ++ * just throw away the DMA context parameter. ++ */ ++#define fh_dma_alloc(_ctx_,_size_,_dma_) FH_DMA_ALLOC(_size_, _dma_) ++#define fh_dma_alloc_atomic(_ctx_,_size_,_dma_) FH_DMA_ALLOC_ATOMIC(_size_, _dma_) ++#define fh_dma_free(_ctx_,_size_,_virt_,_dma_) FH_DMA_FREE(_size_, _virt_, _dma_) ++#endif ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++/** BSD needs several extra parameters for DMA buffer allocation, so we pass ++ * them in using the DMA context parameter. ++ */ ++#define fh_dma_alloc FH_DMA_ALLOC ++#define fh_dma_free FH_DMA_FREE ++#endif ++ ++ ++/** @name Memory and String Processing */ ++ ++/** memset() clone */ ++extern void *FH_MEMSET(void *dest, uint8_t byte, uint32_t size); ++#define fh_memset FH_MEMSET ++ ++/** memcpy() clone */ ++extern void *FH_MEMCPY(void *dest, void const *src, uint32_t size); ++#define fh_memcpy FH_MEMCPY ++ ++/** memmove() clone */ ++extern void *FH_MEMMOVE(void *dest, void *src, uint32_t size); ++#define fh_memmove FH_MEMMOVE ++ ++/** memcmp() clone */ ++extern int FH_MEMCMP(void *m1, void *m2, uint32_t size); ++#define fh_memcmp FH_MEMCMP ++ ++/** strcmp() clone */ ++extern int FH_STRCMP(void *s1, void *s2); ++#define fh_strcmp FH_STRCMP ++ ++/** strncmp() clone */ ++extern int FH_STRNCMP(void *s1, void *s2, uint32_t size); ++#define fh_strncmp FH_STRNCMP ++ ++/** strlen() clone, for NULL terminated ASCII strings */ ++extern int FH_STRLEN(char const *str); ++#define fh_strlen FH_STRLEN ++ ++/** strcpy() clone, for NULL terminated ASCII strings */ ++extern char *FH_STRCPY(char *to, const char *from); ++#define fh_strcpy FH_STRCPY ++ ++/** strdup() clone. If you wish to use memory allocation debugging, this ++ * implementation of strdup should use the FH_* memory routines instead of ++ * calling a predefined strdup. Otherwise the memory allocated by this routine ++ * will not be seen by the debugging routines. */ ++extern char *FH_STRDUP(char const *str); ++#define fh_strdup(_ctx_,_str_) FH_STRDUP(_str_) ++ ++/** NOT an atoi() clone. Read the description carefully. Returns an integer ++ * converted from the string str in base 10 unless the string begins with a "0x" ++ * in which case it is base 16. String must be a NULL terminated sequence of ++ * ASCII characters and may optionally begin with whitespace, a + or -, and a ++ * "0x" prefix if base 16. The remaining characters must be valid digits for ++ * the number and end with a NULL character. If any invalid characters are ++ * encountered or it returns with a negative error code and the results of the ++ * conversion are undefined. On sucess it returns 0. Overflow conditions are ++ * undefined. An example implementation using atoi() can be referenced from the ++ * Linux implementation. */ ++extern int FH_ATOI(const char *str, int32_t *value); ++#define fh_atoi FH_ATOI ++ ++/** Same as above but for unsigned. */ ++extern int FH_ATOUI(const char *str, uint32_t *value); ++#define fh_atoui FH_ATOUI ++ ++#ifdef FH_UTFLIB ++/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ ++extern int FH_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); ++#define fh_utf8_to_utf16le FH_UTF8_TO_UTF16LE ++#endif ++ ++ ++/** @name Wait queues ++ * ++ * Wait queues provide a means of synchronizing between threads or processes. A ++ * process can block on a waitq if some condition is not true, waiting for it to ++ * become true. When the waitq is triggered all waiting process will get ++ * unblocked and the condition will be check again. Waitqs should be triggered ++ * every time a condition can potentially change.*/ ++struct fh_waitq; ++ ++/** Type for a waitq */ ++typedef struct fh_waitq fh_waitq_t; ++ ++/** The type of waitq condition callback function. This is called every time ++ * condition is evaluated. */ ++typedef int (*fh_waitq_condition_t)(void *data); ++ ++/** Allocate a waitq */ ++extern fh_waitq_t *FH_WAITQ_ALLOC(void); ++#define fh_waitq_alloc(_ctx_) FH_WAITQ_ALLOC() ++ ++/** Free a waitq */ ++extern void FH_WAITQ_FREE(fh_waitq_t *wq); ++#define fh_waitq_free FH_WAITQ_FREE ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, check the ++ * condition again. The function returns when the condition becomes true. The return value ++ * is 0 on condition true, FH_WAITQ_ABORTED on abort or killed, or FH_WAITQ_UNKNOWN on error. */ ++extern int32_t FH_WAITQ_WAIT(fh_waitq_t *wq, fh_waitq_condition_t cond, void *data); ++#define fh_waitq_wait FH_WAITQ_WAIT ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, ++ * check the condition again. The function returns when the condition become ++ * true or the timeout has passed. The return value is 0 on condition true or ++ * FH_TIMED_OUT on timeout, or FH_WAITQ_ABORTED, or FH_WAITQ_UNKNOWN on ++ * error. */ ++extern int32_t FH_WAITQ_WAIT_TIMEOUT(fh_waitq_t *wq, fh_waitq_condition_t cond, ++ void *data, int32_t msecs); ++#define fh_waitq_wait_timeout FH_WAITQ_WAIT_TIMEOUT ++ ++/** Trigger a waitq, unblocking all processes. This should be called whenever a condition ++ * has potentially changed. */ ++extern void FH_WAITQ_TRIGGER(fh_waitq_t *wq); ++#define fh_waitq_trigger FH_WAITQ_TRIGGER ++ ++/** Unblock all processes waiting on the waitq with an ABORTED result. */ ++extern void FH_WAITQ_ABORT(fh_waitq_t *wq); ++#define fh_waitq_abort FH_WAITQ_ABORT ++ ++ ++/** @name Threads ++ * ++ * A thread must be explicitly stopped. It must check FH_THREAD_SHOULD_STOP ++ * whenever it is woken up, and then return. The FH_THREAD_STOP function ++ * returns the value from the thread. ++ */ ++ ++struct fh_thread; ++ ++/** Type for a thread */ ++typedef struct fh_thread fh_thread_t; ++ ++/** The thread function */ ++typedef int (*fh_thread_function_t)(void *data); ++ ++/** Create a thread and start it running the thread_function. Returns a handle ++ * to the thread */ ++extern fh_thread_t *FH_THREAD_RUN(fh_thread_function_t func, char *name, void *data); ++#define fh_thread_run(_ctx_,_func_,_name_,_data_) FH_THREAD_RUN(_func_, _name_, _data_) ++ ++/** Stops a thread. Return the value returned by the thread. Or will return ++ * FH_ABORT if the thread never started. */ ++extern int FH_THREAD_STOP(fh_thread_t *thread); ++#define fh_thread_stop FH_THREAD_STOP ++ ++/** Signifies to the thread that it must stop. */ ++#ifdef FH_LINUX ++/* Linux doesn't need any parameters for kthread_should_stop() */ ++extern fh_bool_t FH_THREAD_SHOULD_STOP(void); ++#define fh_thread_should_stop(_thrd_) FH_THREAD_SHOULD_STOP() ++ ++/* No thread_exit function in Linux */ ++#define fh_thread_exit(_thrd_) ++#endif ++ ++#if defined(FH_FREEBSD) || defined(FH_NETBSD) ++/** BSD needs the thread pointer for kthread_suspend_check() */ ++extern fh_bool_t FH_THREAD_SHOULD_STOP(fh_thread_t *thread); ++#define fh_thread_should_stop FH_THREAD_SHOULD_STOP ++ ++/** The thread must call this to exit. */ ++extern void FH_THREAD_EXIT(fh_thread_t *thread); ++#define fh_thread_exit FH_THREAD_EXIT ++#endif ++ ++ ++/** @name Work queues ++ * ++ * Workqs are used to queue a callback function to be called at some later time, ++ * in another thread. */ ++struct fh_workq; ++ ++/** Type for a system work */ ++struct work_struct; ++ ++/** Type for a workq */ ++typedef struct fh_workq fh_workq_t; ++ ++/** The type of the callback function to be called. */ ++typedef void (*fh_work_callback_t)(void *data); ++ ++/** Allocate a workq */ ++extern fh_workq_t *FH_WORKQ_ALLOC(char *name); ++#define fh_workq_alloc(_ctx_,_name_) FH_WORKQ_ALLOC(_name_) ++ ++/** Free a workq. All work must be completed before being freed. */ ++extern void FH_WORKQ_FREE(fh_workq_t *workq); ++#define fh_workq_free FH_WORKQ_FREE ++ ++/** Schedule a callback on the workq, passing in data. The function will be ++ * scheduled at some later time. */ ++extern void FH_WORKQ_SCHEDULE(fh_workq_t *workq, fh_work_callback_t cb, ++ void *data, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 4, 5))); ++#else ++ ; ++#endif ++ ++#define fh_schedule_system_work FH_SCHEDULE_SYSTEM_WORK ++/** Schedule a work on the system workq */ ++extern bool FH_SCHEDULE_SYSTEM_WORK(struct work_struct *work); ++ ++#define fh_workq_schedule FH_WORKQ_SCHEDULE ++ ++/** Schedule a callback on the workq, that will be called until at least ++ * given number miliseconds have passed. */ ++extern void FH_WORKQ_SCHEDULE_DELAYED(fh_workq_t *workq, fh_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 5, 6))); ++#else ++ ; ++#endif ++#define fh_workq_schedule_delayed FH_WORKQ_SCHEDULE_DELAYED ++ ++/** The number of processes in the workq */ ++extern int FH_WORKQ_PENDING(fh_workq_t *workq); ++#define fh_workq_pending FH_WORKQ_PENDING ++ ++/** Blocks until all the work in the workq is complete or timed out. Returns < ++ * 0 on timeout. */ ++extern int FH_WORKQ_WAIT_WORK_DONE(fh_workq_t *workq, int timeout); ++#define fh_workq_wait_work_done FH_WORKQ_WAIT_WORK_DONE ++ ++ ++/** @name Tasklets ++ * ++ */ ++struct fh_tasklet; ++ ++/** Type for a tasklet */ ++typedef struct fh_tasklet fh_tasklet_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*fh_tasklet_callback_t)(void *data); ++ ++/** Allocates a tasklet */ ++extern fh_tasklet_t *FH_TASK_ALLOC(char *name, fh_tasklet_callback_t cb, void *data); ++#define fh_task_alloc(_ctx_,_name_,_cb_,_data_) FH_TASK_ALLOC(_name_, _cb_, _data_) ++ ++/** Frees a tasklet */ ++extern void FH_TASK_FREE(fh_tasklet_t *task); ++#define fh_task_free FH_TASK_FREE ++ ++/** Schedules a tasklet to run */ ++extern void FH_TASK_SCHEDULE(fh_tasklet_t *task); ++#define fh_task_schedule FH_TASK_SCHEDULE ++ ++ ++/** @name Timer ++ * ++ * Callbacks must be small and atomic. ++ */ ++struct fh_timer; ++ ++/** Type for a timer */ ++typedef struct fh_timer fh_timer_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*fh_timer_callback_t)(void *data); ++ ++/** Allocates a timer */ ++extern fh_timer_t *FH_TIMER_ALLOC(char *name, fh_timer_callback_t cb, void *data); ++#define fh_timer_alloc(_ctx_,_name_,_cb_,_data_) FH_TIMER_ALLOC(_name_,_cb_,_data_) ++ ++/** Frees a timer */ ++extern void FH_TIMER_FREE(fh_timer_t *timer); ++#define fh_timer_free FH_TIMER_FREE ++ ++/** Schedules the timer to run at time ms from now. And will repeat at every ++ * repeat_interval msec therafter ++ * ++ * Modifies a timer that is still awaiting execution to a new expiration time. ++ * The mod_time is added to the old time. */ ++extern void FH_TIMER_SCHEDULE(fh_timer_t *timer, uint32_t time); ++#define fh_timer_schedule FH_TIMER_SCHEDULE ++ ++/** Disables the timer from execution. */ ++extern void FH_TIMER_CANCEL(fh_timer_t *timer); ++#define fh_timer_cancel FH_TIMER_CANCEL ++ ++ ++/** @name Spinlocks ++ * ++ * These locks are used when the work between the lock/unlock is atomic and ++ * short. Interrupts are also disabled during the lock/unlock and thus they are ++ * suitable to lock between interrupt/non-interrupt context. They also lock ++ * between processes if you have multiple CPUs or Preemption. If you don't have ++ * multiple CPUS or Preemption, then the you can simply implement the ++ * FH_SPINLOCK and FH_SPINUNLOCK to disable and enable interrupts. Because ++ * the work between the lock/unlock is atomic, the process context will never ++ * change, and so you never have to lock between processes. */ ++ ++struct fh_spinlock; ++ ++/** Type for a spinlock */ ++typedef struct fh_spinlock fh_spinlock_t; ++ ++/** Type for the 'flags' argument to spinlock funtions */ ++typedef unsigned long fh_irqflags_t; ++ ++/** Returns an initialized lock variable. This function should allocate and ++ * initialize the OS-specific data structure used for locking. This data ++ * structure is to be used for the FH_LOCK and FH_UNLOCK functions and should ++ * be freed by the FH_FREE_LOCK when it is no longer used. */ ++extern fh_spinlock_t *FH_SPINLOCK_ALLOC(void); ++#define fh_spinlock_alloc(_ctx_) FH_SPINLOCK_ALLOC() ++ ++/** Frees an initialized lock variable. */ ++extern void FH_SPINLOCK_FREE(fh_spinlock_t *lock); ++#define fh_spinlock_free(_ctx_,_lock_) FH_SPINLOCK_FREE(_lock_) ++ ++/** Disables interrupts and blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. ++ */ ++extern void FH_SPINLOCK_IRQSAVE(fh_spinlock_t *lock, fh_irqflags_t *flags); ++#define fh_spinlock_irqsave FH_SPINLOCK_IRQSAVE ++ ++/** Re-enables the interrupt and releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. Must be the same as was ++ * passed into FH_LOCK. ++ */ ++extern void FH_SPINUNLOCK_IRQRESTORE(fh_spinlock_t *lock, fh_irqflags_t flags); ++#define fh_spinunlock_irqrestore FH_SPINUNLOCK_IRQRESTORE ++ ++/** Blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void FH_SPINLOCK(fh_spinlock_t *lock); ++#define fh_spinlock FH_SPINLOCK ++ ++/** Releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void FH_SPINUNLOCK(fh_spinlock_t *lock); ++#define fh_spinunlock FH_SPINUNLOCK ++ ++ ++/** @name Mutexes ++ * ++ * Unlike spinlocks Mutexes lock only between processes and the work between the ++ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context. ++ */ ++ ++struct fh_mutex; ++ ++/** Type for a mutex */ ++typedef struct fh_mutex fh_mutex_t; ++ ++/* For Linux Mutex Debugging make it inline because the debugging routines use ++ * the symbol to determine recursive locking. This makes it falsely think ++ * recursive locking occurs. */ ++#if defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define FH_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ ++ __mutexp = (fh_mutex_t *)FH_ALLOC(sizeof(struct mutex)); \ ++ mutex_init((struct mutex *)__mutexp); \ ++}) ++#endif ++ ++/** Allocate a mutex */ ++extern fh_mutex_t *FH_MUTEX_ALLOC(void); ++#define fh_mutex_alloc(_ctx_) FH_MUTEX_ALLOC() ++ ++/* For memory leak debugging when using Linux Mutex Debugging */ ++#if defined(FH_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define FH_MUTEX_FREE(__mutexp) do { \ ++ mutex_destroy((struct mutex *)__mutexp); \ ++ FH_FREE(__mutexp); \ ++} while(0) ++#else ++/** Free a mutex */ ++extern void FH_MUTEX_FREE(fh_mutex_t *mutex); ++#define fh_mutex_free(_ctx_,_mutex_) FH_MUTEX_FREE(_mutex_) ++#endif ++ ++/** Lock a mutex */ ++extern void FH_MUTEX_LOCK(fh_mutex_t *mutex); ++#define fh_mutex_lock FH_MUTEX_LOCK ++ ++/** Non-blocking lock returns 1 on successful lock. */ ++extern int FH_MUTEX_TRYLOCK(fh_mutex_t *mutex); ++#define fh_mutex_trylock FH_MUTEX_TRYLOCK ++ ++/** Unlock a mutex */ ++extern void FH_MUTEX_UNLOCK(fh_mutex_t *mutex); ++#define fh_mutex_unlock FH_MUTEX_UNLOCK ++ ++ ++/** @name Time */ ++ ++/** Microsecond delay. ++ * ++ * @param usecs Microseconds to delay. ++ */ ++extern void FH_UDELAY(uint32_t usecs); ++#define fh_udelay FH_UDELAY ++ ++/** Millisecond delay. ++ * ++ * @param msecs Milliseconds to delay. ++ */ ++extern void FH_MDELAY(uint32_t msecs); ++#define fh_mdelay FH_MDELAY ++ ++/** Non-busy waiting. ++ * Sleeps for specified number of milliseconds. ++ * ++ * @param msecs Milliseconds to sleep. ++ */ ++extern void FH_MSLEEP(uint32_t msecs); ++#define fh_msleep FH_MSLEEP ++ ++/** ++ * Returns number of milliseconds since boot. ++ */ ++extern uint32_t FH_TIME(void); ++#define fh_time FH_TIME ++ ++ ++ ++ ++/* @mainpage FH Portability and Common Library ++ * ++ * This is the documentation for the FH Portability and Common Library. ++ * ++ * @section intro Introduction ++ * ++ * The FH Portability library consists of wrapper calls and data structures to ++ * all low-level functions which are typically provided by the OS. The WUDEV ++ * driver uses only these functions. In order to port the WUDEV driver, only ++ * the functions in this library need to be re-implemented, with the same ++ * behavior as documented here. ++ * ++ * The Common library consists of higher level functions, which rely only on ++ * calling the functions from the FH Portability library. These common ++ * routines are shared across modules. Some of the common libraries need to be ++ * used directly by the driver programmer when porting WUDEV. Such as the ++ * parameter and notification libraries. ++ * ++ * @section low Portability Library OS Wrapper Functions ++ * ++ * Any function starting with FH and in all CAPS is a low-level OS-wrapper that ++ * needs to be implemented when porting, for example FH_MUTEX_ALLOC(). All of ++ * these functions are included in the fh_os.h file. ++ * ++ * There are many functions here covering a wide array of OS services. Please ++ * see fh_os.h for details, and implementation notes for each function. ++ * ++ * @section common Common Library Functions ++ * ++ * Any function starting with fh and in all lowercase is a common library ++ * routine. These functions have a portable implementation and do not need to ++ * be reimplemented when porting. The common routines can be used by any ++ * driver, and some must be used by the end user to control the drivers. For ++ * example, you must use the Parameter common library in order to set the ++ * parameters in the WUDEV module. ++ * ++ * The common libraries consist of the following: ++ * ++ * - Connection Contexts - Used internally and can be used by end-user. See fh_cc.h ++ * - Parameters - Used internally and can be used by end-user. See fh_params.h ++ * - Notifications - Used internally and can be used by end-user. See fh_notifier.h ++ * - Lists - Used internally and can be used by end-user. See fh_list.h ++ * - Memory Debugging - Used internally and can be used by end-user. See fh_os.h ++ * - Modpow - Used internally only. See fh_modpow.h ++ * - DH - Used internally only. See fh_dh.h ++ * - Crypto - Used internally only. See fh_crypto.h ++ * ++ * ++ * @section prereq Prerequistes For fh_os.h ++ * @subsection types Data Types ++ * ++ * The fh_os.h file assumes that several low-level data types are pre defined for the ++ * compilation environment. These data types are: ++ * ++ * - uint8_t - unsigned 8-bit data type ++ * - int8_t - signed 8-bit data type ++ * - uint16_t - unsigned 16-bit data type ++ * - int16_t - signed 16-bit data type ++ * - uint32_t - unsigned 32-bit data type ++ * - int32_t - signed 32-bit data type ++ * - uint64_t - unsigned 64-bit data type ++ * - int64_t - signed 64-bit data type ++ * ++ * Ensure that these are defined before using fh_os.h. The easiest way to do ++ * that is to modify the top of the file to include the appropriate header. ++ * This is already done for the Linux environment. If the FH_LINUX macro is ++ * defined, the correct header will be added. A standard header <stdint.h> is ++ * also used for environments where standard C headers are available. ++ * ++ * @subsection stdarg Variable Arguments ++ * ++ * Variable arguments are provided by a standard C header <stdarg.h>. it is ++ * available in Both the Linux and ANSI C enviornment. An equivalent must be ++ * provided in your enviornment in order to use fh_os.h with the debug and ++ * tracing message functionality. ++ * ++ * @subsection thread Threading ++ * ++ * WUDEV Core must be run on an operating system that provides for multiple ++ * threads/processes. Threading can be implemented in many ways, even in ++ * embedded systems without an operating system. At the bare minimum, the ++ * system should be able to start any number of processes at any time to handle ++ * special work. It need not be a pre-emptive system. Process context can ++ * change upon a call to a blocking function. The hardware interrupt context ++ * that calls the module's ISR() function must be differentiable from process ++ * context, even if your processes are impemented via a hardware interrupt. ++ * Further locking mechanism between process must exist (or be implemented), and ++ * process context must have a way to disable interrupts for a period of time to ++ * lock them out. If all of this exists, the functions in fh_os.h related to ++ * threading should be able to be implemented with the defined behavior. ++ * ++ */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_OS_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_common_port/usb.h b/drivers/usb/host/fh_otg/fh_common_port/usb.h +new file mode 100644 +index 00000000..27bda82d +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_common_port/usb.h +@@ -0,0 +1,946 @@ ++/* ++ * Copyright (c) 1998 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Lennart Augustsson (lennart@augustsson.net) at ++ * Carlstedt Research & Technology. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ++ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/* Modified by Synopsys, Inc, 12/12/2007 */ ++ ++ ++#ifndef _USB_H_ ++#define _USB_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ++ * The USB records contain some unaligned little-endian word ++ * components. The U[SG]ETW macros take care of both the alignment ++ * and endian problem and should always be used to access non-byte ++ * values. ++ */ ++typedef u_int8_t uByte; ++typedef u_int8_t uWord[2]; ++typedef u_int8_t uDWord[4]; ++ ++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } ++ ++#if 1 ++#define UGETW(w) ((w)[0] | ((w)[1] << 8)) ++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) ++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) ++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ ++ (w)[1] = (u_int8_t)((v) >> 8), \ ++ (w)[2] = (u_int8_t)((v) >> 16), \ ++ (w)[3] = (u_int8_t)((v) >> 24)) ++#else ++/* ++ * On little-endian machines that can handle unanliged accesses ++ * (e.g. i386) these macros can be replaced by the following. ++ */ ++#define UGETW(w) (*(u_int16_t *)(w)) ++#define USETW(w,v) (*(u_int16_t *)(w) = (v)) ++#define UGETDW(w) (*(u_int32_t *)(w)) ++#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) ++#endif ++ ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ ++#define UPACKED __attribute__((__packed__)) ++ ++typedef struct { ++ uByte bmRequestType; ++ uByte bRequest; ++ uWord wValue; ++ uWord wIndex; ++ uWord wLength; ++} UPACKED usb_device_request_t; ++ ++#define UT_GET_DIR(a) ((a) & 0x80) ++#define UT_WRITE 0x00 ++#define UT_READ 0x80 ++ ++#define UT_GET_TYPE(a) ((a) & 0x60) ++#define UT_STANDARD 0x00 ++#define UT_CLASS 0x20 ++#define UT_VENDOR 0x40 ++ ++#define UT_GET_RECIPIENT(a) ((a) & 0x1f) ++#define UT_DEVICE 0x00 ++#define UT_INTERFACE 0x01 ++#define UT_ENDPOINT 0x02 ++#define UT_OTHER 0x03 ++ ++#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) ++#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) ++#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) ++#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) ++#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) ++#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) ++#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) ++#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) ++#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) ++#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) ++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) ++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) ++#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) ++#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) ++#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) ++#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) ++#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) ++#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) ++#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) ++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) ++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) ++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) ++ ++/* Requests */ ++#define UR_GET_STATUS 0x00 ++#define USTAT_STANDARD_STATUS 0x00 ++#define WUSTAT_WUSB_FEATURE 0x01 ++#define WUSTAT_CHANNEL_INFO 0x02 ++#define WUSTAT_RECEIVED_DATA 0x03 ++#define WUSTAT_MAS_AVAILABILITY 0x04 ++#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 ++#define UR_CLEAR_FEATURE 0x01 ++#define UR_SET_FEATURE 0x03 ++#define UR_SET_AND_TEST_FEATURE 0x0c ++#define UR_SET_ADDRESS 0x05 ++#define UR_GET_DESCRIPTOR 0x06 ++#define UDESC_DEVICE 0x01 ++#define UDESC_CONFIG 0x02 ++#define UDESC_STRING 0x03 ++#define UDESC_INTERFACE 0x04 ++#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 ++#define UDESC_DEVICE_QUALIFIER 0x06 ++#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 ++#define UDESC_INTERFACE_POWER 0x08 ++#define UDESC_OTG 0x09 ++#define WUDESC_SECURITY 0x0c ++#define WUDESC_KEY 0x0d ++#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) ++#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) ++#define WUD_KEY_TYPE_ASSOC 0x01 ++#define WUD_KEY_TYPE_GTK 0x02 ++#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) ++#define WUD_KEY_ORIGIN_HOST 0x00 ++#define WUD_KEY_ORIGIN_DEVICE 0x01 ++#define WUDESC_ENCRYPTION_TYPE 0x0e ++#define WUDESC_BOS 0x0f ++#define WUDESC_DEVICE_CAPABILITY 0x10 ++#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 ++#define UDESC_CS_DEVICE 0x21 /* class specific */ ++#define UDESC_CS_CONFIG 0x22 ++#define UDESC_CS_STRING 0x23 ++#define UDESC_CS_INTERFACE 0x24 ++#define UDESC_CS_ENDPOINT 0x25 ++#define UDESC_HUB 0x29 ++#define UR_SET_DESCRIPTOR 0x07 ++#define UR_GET_CONFIG 0x08 ++#define UR_SET_CONFIG 0x09 ++#define UR_GET_INTERFACE 0x0a ++#define UR_SET_INTERFACE 0x0b ++#define UR_SYNCH_FRAME 0x0c ++#define WUR_SET_ENCRYPTION 0x0d ++#define WUR_GET_ENCRYPTION 0x0e ++#define WUR_SET_HANDSHAKE 0x0f ++#define WUR_GET_HANDSHAKE 0x10 ++#define WUR_SET_CONNECTION 0x11 ++#define WUR_SET_SECURITY_DATA 0x12 ++#define WUR_GET_SECURITY_DATA 0x13 ++#define WUR_SET_WUSB_DATA 0x14 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUR_LOOPBACK_DATA_WRITE 0x15 ++#define WUR_LOOPBACK_DATA_READ 0x16 ++#define WUR_SET_INTERFACE_DS 0x17 ++ ++/* Feature numbers */ ++#define UF_ENDPOINT_HALT 0 ++#define UF_DEVICE_REMOTE_WAKEUP 1 ++#define UF_TEST_MODE 2 ++#define UF_DEVICE_B_HNP_ENABLE 3 ++#define UF_DEVICE_A_HNP_SUPPORT 4 ++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 ++ ++/* Class requests from the USB 2.0 hub spec, table 11-15 */ ++#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) ++#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) ++#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) ++#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) ++#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) ++#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) ++#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) ++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) ++ ++#ifdef _MSC_VER ++#include <pshpack1.h> ++#endif ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDescriptorSubtype; ++} UPACKED usb_descriptor_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++#define UD_USB_2_0 0x0200 ++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize; ++ /* The fields below are not part of the initial descriptor. */ ++ uWord idVendor; ++ uWord idProduct; ++ uWord bcdDevice; ++ uByte iManufacturer; ++ uByte iProduct; ++ uByte iSerialNumber; ++ uByte bNumConfigurations; ++} UPACKED usb_device_descriptor_t; ++#define USB_DEVICE_DESCRIPTOR_SIZE 18 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumInterface; ++ uByte bConfigurationValue; ++ uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ ++ uByte bmAttributes; ++#define UC_BUS_POWERED 0x80 ++#define UC_SELF_POWERED 0x40 ++#define UC_REMOTE_WAKEUP 0x20 ++ uByte bMaxPower; /* max current in 2 mA units */ ++#define UC_POWER_FACTOR 2 ++} UPACKED usb_config_descriptor_t; ++#define USB_CONFIG_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bInterfaceNumber; ++ uByte bAlternateSetting; ++ uByte bNumEndpoints; ++ uByte bInterfaceClass; ++ uByte bInterfaceSubClass; ++ uByte bInterfaceProtocol; ++ uByte iInterface; ++} UPACKED usb_interface_descriptor_t; ++#define USB_INTERFACE_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bEndpointAddress; ++#define UE_GET_DIR(a) ((a) & 0x80) ++#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) ++#define UE_DIR_IN 0x80 ++#define UE_DIR_OUT 0x00 ++#define UE_ADDR 0x0f ++#define UE_GET_ADDR(a) ((a) & UE_ADDR) ++ uByte bmAttributes; ++#define UE_XFERTYPE 0x03 ++#define UE_CONTROL 0x00 ++#define UE_ISOCHRONOUS 0x01 ++#define UE_BULK 0x02 ++#define UE_INTERRUPT 0x03 ++#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) ++#define UE_ISO_TYPE 0x0c ++#define UE_ISO_ASYNC 0x04 ++#define UE_ISO_ADAPT 0x08 ++#define UE_ISO_SYNC 0x0c ++#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) ++ uWord wMaxPacketSize; ++ uByte bInterval; ++} UPACKED usb_endpoint_descriptor_t; ++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 ++ ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bString[127]; ++} UPACKED usb_string_descriptor_t; ++#define USB_MAX_STRING_LEN 128 ++#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ ++ ++/* Hub specific request */ ++#define UR_GET_BUS_STATE 0x02 ++#define UR_CLEAR_TT_BUFFER 0x08 ++#define UR_RESET_TT 0x09 ++#define UR_GET_TT_STATE 0x0a ++#define UR_STOP_TT 0x0b ++ ++/* Hub features */ ++#define UHF_C_HUB_LOCAL_POWER 0 ++#define UHF_C_HUB_OVER_CURRENT 1 ++#define UHF_PORT_CONNECTION 0 ++#define UHF_PORT_ENABLE 1 ++#define UHF_PORT_SUSPEND 2 ++#define UHF_PORT_OVER_CURRENT 3 ++#define UHF_PORT_RESET 4 ++#define UHF_PORT_L1 5 ++#define UHF_PORT_POWER 8 ++#define UHF_PORT_LOW_SPEED 9 ++#define UHF_PORT_HIGH_SPEED 10 ++#define UHF_C_PORT_CONNECTION 16 ++#define UHF_C_PORT_ENABLE 17 ++#define UHF_C_PORT_SUSPEND 18 ++#define UHF_C_PORT_OVER_CURRENT 19 ++#define UHF_C_PORT_RESET 20 ++#define UHF_C_PORT_L1 23 ++#define UHF_PORT_TEST 21 ++#define UHF_PORT_INDICATOR 22 ++ ++typedef struct { ++ uByte bDescLength; ++ uByte bDescriptorType; ++ uByte bNbrPorts; ++ uWord wHubCharacteristics; ++#define UHD_PWR 0x0003 ++#define UHD_PWR_GANGED 0x0000 ++#define UHD_PWR_INDIVIDUAL 0x0001 ++#define UHD_PWR_NO_SWITCH 0x0002 ++#define UHD_COMPOUND 0x0004 ++#define UHD_OC 0x0018 ++#define UHD_OC_GLOBAL 0x0000 ++#define UHD_OC_INDIVIDUAL 0x0008 ++#define UHD_OC_NONE 0x0010 ++#define UHD_TT_THINK 0x0060 ++#define UHD_TT_THINK_8 0x0000 ++#define UHD_TT_THINK_16 0x0020 ++#define UHD_TT_THINK_24 0x0040 ++#define UHD_TT_THINK_32 0x0060 ++#define UHD_PORT_IND 0x0080 ++ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ ++#define UHD_PWRON_FACTOR 2 ++ uByte bHubContrCurrent; ++ uByte DeviceRemovable[32]; /* max 255 ports */ ++#define UHD_NOT_REMOV(desc, i) \ ++ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) ++ /* deprecated */ uByte PortPowerCtrlMask[1]; ++} UPACKED usb_hub_descriptor_t; ++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize0; ++ uByte bNumConfigurations; ++ uByte bReserved; ++} UPACKED usb_device_qualifier_t; ++#define USB_DEVICE_QUALIFIER_SIZE 10 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bmAttributes; ++#define UOTG_SRP 0x01 ++#define UOTG_HNP 0x02 ++} UPACKED usb_otg_descriptor_t; ++ ++/* OTG feature selectors */ ++#define UOTG_B_HNP_ENABLE 3 ++#define UOTG_A_HNP_SUPPORT 4 ++#define UOTG_A_ALT_HNP_SUPPORT 5 ++ ++typedef struct { ++ uWord wStatus; ++/* Device status flags */ ++#define UDS_SELF_POWERED 0x0001 ++#define UDS_REMOTE_WAKEUP 0x0002 ++/* Endpoint status flags */ ++#define UES_HALT 0x0001 ++} UPACKED usb_status_t; ++ ++typedef struct { ++ uWord wHubStatus; ++#define UHS_LOCAL_POWER 0x0001 ++#define UHS_OVER_CURRENT 0x0002 ++ uWord wHubChange; ++} UPACKED usb_hub_status_t; ++ ++typedef struct { ++ uWord wPortStatus; ++#define UPS_CURRENT_CONNECT_STATUS 0x0001 ++#define UPS_PORT_ENABLED 0x0002 ++#define UPS_SUSPEND 0x0004 ++#define UPS_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_RESET 0x0010 ++#define UPS_PORT_POWER 0x0100 ++#define UPS_LOW_SPEED 0x0200 ++#define UPS_HIGH_SPEED 0x0400 ++#define UPS_PORT_TEST 0x0800 ++#define UPS_PORT_INDICATOR 0x1000 ++ uWord wPortChange; ++#define UPS_C_CONNECT_STATUS 0x0001 ++#define UPS_C_PORT_ENABLED 0x0002 ++#define UPS_C_SUSPEND 0x0004 ++#define UPS_C_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_C_PORT_RESET 0x0010 ++} UPACKED usb_port_status_t; ++ ++#ifdef _MSC_VER ++#include <poppack.h> ++#endif ++ ++/* Device class codes */ ++#define UDCLASS_IN_INTERFACE 0x00 ++#define UDCLASS_COMM 0x02 ++#define UDCLASS_HUB 0x09 ++#define UDSUBCLASS_HUB 0x00 ++#define UDPROTO_FSHUB 0x00 ++#define UDPROTO_HSHUBSTT 0x01 ++#define UDPROTO_HSHUBMTT 0x02 ++#define UDCLASS_DIAGNOSTIC 0xdc ++#define UDCLASS_WIRELESS 0xe0 ++#define UDSUBCLASS_RF 0x01 ++#define UDPROTO_BLUETOOTH 0x01 ++#define UDCLASS_VENDOR 0xff ++ ++/* Interface class codes */ ++#define UICLASS_UNSPEC 0x00 ++ ++#define UICLASS_AUDIO 0x01 ++#define UISUBCLASS_AUDIOCONTROL 1 ++#define UISUBCLASS_AUDIOSTREAM 2 ++#define UISUBCLASS_MIDISTREAM 3 ++ ++#define UICLASS_CDC 0x02 /* communication */ ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UIPROTO_CDC_AT 1 ++ ++#define UICLASS_HID 0x03 ++#define UISUBCLASS_BOOT 1 ++#define UIPROTO_BOOT_KEYBOARD 1 ++ ++#define UICLASS_PHYSICAL 0x05 ++ ++#define UICLASS_IMAGE 0x06 ++ ++#define UICLASS_PRINTER 0x07 ++#define UISUBCLASS_PRINTER 1 ++#define UIPROTO_PRINTER_UNI 1 ++#define UIPROTO_PRINTER_BI 2 ++#define UIPROTO_PRINTER_1284 3 ++ ++#define UICLASS_MASS 0x08 ++#define UISUBCLASS_RBC 1 ++#define UISUBCLASS_SFF8020I 2 ++#define UISUBCLASS_QIC157 3 ++#define UISUBCLASS_UFI 4 ++#define UISUBCLASS_SFF8070I 5 ++#define UISUBCLASS_SCSI 6 ++#define UIPROTO_MASS_CBI_I 0 ++#define UIPROTO_MASS_CBI 1 ++#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ ++#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ ++ ++#define UICLASS_HUB 0x09 ++#define UISUBCLASS_HUB 0 ++#define UIPROTO_FSHUB 0 ++#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ ++#define UIPROTO_HSHUBMTT 1 ++ ++#define UICLASS_CDC_DATA 0x0a ++#define UISUBCLASS_DATA 0 ++#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ ++#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ ++#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ ++#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ ++#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ ++#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ ++#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ ++#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ ++#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ ++#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ ++#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ ++#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ ++#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ ++ ++#define UICLASS_SMARTCARD 0x0b ++ ++/*#define UICLASS_FIRM_UPD 0x0c*/ ++ ++#define UICLASS_SECURITY 0x0d ++ ++#define UICLASS_DIAGNOSTIC 0xdc ++ ++#define UICLASS_WIRELESS 0xe0 ++#define UISUBCLASS_RF 0x01 ++#define UIPROTO_BLUETOOTH 0x01 ++ ++#define UICLASS_APPL_SPEC 0xfe ++#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 ++#define UISUBCLASS_IRDA 2 ++#define UIPROTO_IRDA 0 ++ ++#define UICLASS_VENDOR 0xff ++ ++#define USB_HUB_MAX_DEPTH 5 ++ ++/* ++ * Minimum time a device needs to be powered down to go through ++ * a power cycle. XXX Are these time in the spec? ++ */ ++#define USB_POWER_DOWN_TIME 200 /* ms */ ++#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ ++ ++#if 0 ++/* These are the values from the spec. */ ++#define USB_PORT_RESET_DELAY 10 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_RESET_RECOVERY 10 /* ms */ ++#define USB_PORT_POWERUP_DELAY 100 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 2 /* ms */ ++#define USB_RESUME_DELAY (20*5) /* ms */ ++#define USB_RESUME_WAIT 10 /* ms */ ++#define USB_RESUME_RECOVERY 10 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ ++#else ++/* Allow for marginal (i.e. non-conforming) devices. */ ++#define USB_PORT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ ++#define USB_PORT_RESET_RECOVERY 250 /* ms */ ++#define USB_PORT_POWERUP_DELAY 300 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 10 /* ms */ ++#define USB_RESUME_DELAY (50*5) /* ms */ ++#define USB_RESUME_WAIT 50 /* ms */ ++#define USB_RESUME_RECOVERY 50 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ ++#endif ++ ++#define USB_MIN_POWER 100 /* mA */ ++#define USB_MAX_POWER 500 /* mA */ ++ ++#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ ++ ++#define USB_UNCONFIG_NO 0 ++#define USB_UNCONFIG_INDEX (-1) ++ ++/*** ioctl() related stuff ***/ ++ ++struct usb_ctl_request { ++ int ucr_addr; ++ usb_device_request_t ucr_request; ++ void *ucr_data; ++ int ucr_flags; ++#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ ++ int ucr_actlen; /* actual length transferred */ ++}; ++ ++struct usb_alt_interface { ++ int uai_config_index; ++ int uai_interface_index; ++ int uai_alt_no; ++}; ++ ++#define USB_CURRENT_CONFIG_INDEX (-1) ++#define USB_CURRENT_ALT_INDEX (-1) ++ ++struct usb_config_desc { ++ int ucd_config_index; ++ usb_config_descriptor_t ucd_desc; ++}; ++ ++struct usb_interface_desc { ++ int uid_config_index; ++ int uid_interface_index; ++ int uid_alt_index; ++ usb_interface_descriptor_t uid_desc; ++}; ++ ++struct usb_endpoint_desc { ++ int ued_config_index; ++ int ued_interface_index; ++ int ued_alt_index; ++ int ued_endpoint_index; ++ usb_endpoint_descriptor_t ued_desc; ++}; ++ ++struct usb_full_desc { ++ int ufd_config_index; ++ u_int ufd_size; ++ u_char *ufd_data; ++}; ++ ++struct usb_string_desc { ++ int usd_string_index; ++ int usd_language_id; ++ usb_string_descriptor_t usd_desc; ++}; ++ ++struct usb_ctl_report_desc { ++ int ucrd_size; ++ u_char ucrd_data[1024]; /* filled data size will vary */ ++}; ++ ++typedef struct { u_int32_t cookie; } usb_event_cookie_t; ++ ++#define USB_MAX_DEVNAMES 4 ++#define USB_MAX_DEVNAMELEN 16 ++struct usb_device_info { ++ u_int8_t udi_bus; ++ u_int8_t udi_addr; /* device address */ ++ usb_event_cookie_t udi_cookie; ++ char udi_product[USB_MAX_STRING_LEN]; ++ char udi_vendor[USB_MAX_STRING_LEN]; ++ char udi_release[8]; ++ u_int16_t udi_productNo; ++ u_int16_t udi_vendorNo; ++ u_int16_t udi_releaseNo; ++ u_int8_t udi_class; ++ u_int8_t udi_subclass; ++ u_int8_t udi_protocol; ++ u_int8_t udi_config; ++ u_int8_t udi_speed; ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 ++ int udi_power; /* power consumption in mA, 0 if selfpowered */ ++ int udi_nports; ++ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; ++ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ ++#define USB_PORT_ENABLED 0xff ++#define USB_PORT_SUSPENDED 0xfe ++#define USB_PORT_POWERED 0xfd ++#define USB_PORT_DISABLED 0xfc ++}; ++ ++struct usb_ctl_report { ++ int ucr_report; ++ u_char ucr_data[1024]; /* filled data size will vary */ ++}; ++ ++struct usb_device_stats { ++ u_long uds_requests[4]; /* indexed by transfer type UE_* */ ++}; ++ ++#define WUSB_MIN_IE 0x80 ++#define WUSB_WCTA_IE 0x80 ++#define WUSB_WCONNECTACK_IE 0x81 ++#define WUSB_WHOSTINFO_IE 0x82 ++#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 ++#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) ++#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 ++#define WUSB_WDEV_DISCONNECT_IE 0x84 ++#define WUSB_WHOST_DISCONNECT_IE 0x85 ++#define WUSB_WRELEASE_CHANNEL_IE 0x86 ++#define WUSB_WWORK_IE 0x87 ++#define WUSB_WCHANNEL_STOP_IE 0x88 ++#define WUSB_WDEV_KEEPALIVE_IE 0x89 ++#define WUSB_WISOCH_DISCARD_IE 0x8A ++#define WUSB_WRESETDEVICE_IE 0x8B ++#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C ++#define WUSB_MAX_IE 0x8C ++ ++/* Device Notification Types */ ++ ++#define WUSB_DN_MIN 0x01 ++#define WUSB_DN_CONNECT 0x01 ++# define WUSB_DA_OLDCONN 0x00 ++# define WUSB_DA_NEWCONN 0x01 ++# define WUSB_DA_SELF_BEACON 0x02 ++# define WUSB_DA_DIR_BEACON 0x04 ++# define WUSB_DA_NO_BEACON 0x06 ++#define WUSB_DN_DISCONNECT 0x02 ++#define WUSB_DN_EPRDY 0x03 ++#define WUSB_DN_MASAVAILCHANGED 0x04 ++#define WUSB_DN_REMOTEWAKEUP 0x05 ++#define WUSB_DN_SLEEP 0x06 ++#define WUSB_DN_ALIVE 0x07 ++#define WUSB_DN_MAX 0x07 ++ ++#ifdef _MSC_VER ++#include <pshpack1.h> ++#endif ++ ++/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ ++typedef struct wusb_hndshk_data { ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; ++} UPACKED wusb_hndshk_data_t; ++#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 ++ ++/* WUSB Connection Context */ ++typedef struct wusb_conn_context { ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; ++} UPACKED wusb_conn_context_t; ++ ++/* WUSB Security Descriptor */ ++typedef struct wusb_security_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; ++} UPACKED wusb_security_desc_t; ++ ++/* WUSB Encryption Type Descriptor */ ++typedef struct wusb_encrypt_type_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 ++#define WUETD_WIRED 1 ++#define WUETD_CCM_1 2 ++#define WUETD_RSA_1 3 ++ ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; ++} UPACKED wusb_encrypt_type_desc_t; ++ ++/* WUSB Key Descriptor */ ++typedef struct wusb_key_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ ++} UPACKED wusb_key_desc_t; ++ ++/* WUSB BOS Descriptor (Binary device Object Store) */ ++typedef struct wusb_bos_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; ++} UPACKED wusb_bos_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; ++ ++/* Device Capability Type Codes */ ++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ ++} UPACKED wusb_dev_cap_desc_t; ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_uwb_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; ++} UPACKED wusb_dev_cap_uwb_desc_t; ++ ++/* Wireless USB Endpoint Companion Descriptor */ ++typedef struct wusb_endpoint_companion_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; ++} UPACKED wusb_endpoint_companion_desc_t; ++ ++/* Wireless USB Numeric Association M1 Data Structure */ ++typedef struct wusb_m1_data { ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; ++} UPACKED wusb_m1_data_t; ++ ++typedef struct wusb_m2_data { ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; ++} UPACKED wusb_m2_data_t; ++ ++typedef struct wusb_m3_data { ++ uByte pkd[384]; ++ uByte nd; ++} UPACKED wusb_m3_data_t; ++ ++typedef struct wusb_m4_data { ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; ++ ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; ++ ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; ++ ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; ++ ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; ++ ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; ++ ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; ++} UPACKED wusb_m4_data_t; ++ ++#ifdef _MSC_VER ++#include <poppack.h> ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _USB_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/Kconfig b/drivers/usb/host/fh_otg/fh_otg/Kconfig +new file mode 100644 +index 00000000..d48d79a7 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/Kconfig +@@ -0,0 +1,14 @@ ++config FH_HOST_ONLY ++ bool "Host only mode" ++ default y ++ depends on USB_FH_OTG ++ help ++ The USB2.0 high-speed host controller ++ integrated into many SoCs. ++ ++config FH_DEVICE_ONLY ++ bool "Device only mode" ++ depends on USB_FH_OTG ++ help ++ The USB2.0 high-speed gadget controller ++ integrated into many SoCs. +diff --git a/drivers/usb/host/fh_otg/fh_otg/Makefile b/drivers/usb/host/fh_otg/fh_otg/Makefile +new file mode 100644 +index 00000000..bdafb31d +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/Makefile +@@ -0,0 +1,80 @@ ++# ++# Makefile for FH_otg Highspeed USB controller driver ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++# Use the BUS_INTERFACE variable to compile the software for either ++# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. ++ifeq ($(BUS_INTERFACE),) ++ BUS_INTERFACE = -DPCI_INTERFACE ++# BUS_INTERFACE = -DLM_INTERFACE ++endif ++ ++#EXTRA_CFLAGS += -DDEBUG ++ ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++ ++ifeq ($(CONFIG_FH_HOST_ONLY)_$(CONFIG_FH_DEVICE_ONLY), y_y) ++$(error "FH_HOST_ONLY FH_DEVICE_ONLY should be one of them or none!!!") ++endif ++ ++ifneq ($(CONFIG_FH_HOST_ONLY),) ++EXTRA_CFLAGS += -DFH_HOST_ONLY ++endif ++ifneq ($(CONFIG_FH_DEVICE_ONLY),) ++EXTRA_CFLAGS += -DFH_DEVICE_ONLY ++endif ++ ++EXTRA_CFLAGS += -Dlinux -DFH_HS_ELECT_TST ++#EXTRA_CFLAGS += -DFH_EN_ISOC ++EXTRA_CFLAGS += -I$(PWD)/../fh_common_port ++#EXTRA_CFLAGS += -I$(PORTLIB) ++EXTRA_CFLAGS += -DFH_LINUX ++EXTRA_CFLAGS += $(CFI) ++EXTRA_CFLAGS += $(BUS_INTERFACE) ++#EXTRA_CFLAGS += -DFH_DEV_SRPCAP ++ ++obj-$(CONFIG_USB_FH_OTG):= fh_otg.o ++ ++fh_otg-objs := fh_otg_driver.o fh_otg_attr.o ++fh_otg-objs += fh_otg_cil.o fh_otg_cil_intr.o ++fh_otg-objs += fh_otg_pcd_linux.o fh_otg_pcd.o fh_otg_pcd_intr.o ++fh_otg-objs += fh_otg_hcd.o fh_otg_hcd_linux.o fh_otg_hcd_intr.o fh_otg_hcd_queue.o fh_otg_hcd_ddma.o ++fh_otg-objs += fh_otg_adp.o ++ifneq ($(CFI),) ++fh_otg-objs += fh_otg_cfi.o ++endif ++ ++else ++ ++PWD := $(shell pwd) ++PORTLIB := $(PWD)/../fh_common_port ++ ++# Command paths ++CTAGS := $(CTAGS) ++DOXYGEN := $(DOXYGEN) ++ ++default: portlib ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: default ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install ++ $(MAKE) -C$(KDIR) M=$(PWD) modules_install ++ ++portlib: ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ cp $(PORTLIB)/Module.symvers $(PWD)/ ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++ ++clean: ++ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers ++ ++endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/README b/drivers/usb/host/fh_otg/fh_otg/README +new file mode 100644 +index 00000000..93cfd3b4 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/README +@@ -0,0 +1,17 @@ ++Instructions for building HSOTG driver ++Portability library will be built on the fly ++--------------------------------------- ++- Export necessary environment variables or pass them to the make command line. ++ ++# Path to the installed kernel directory ++ % export KDIR=/... ++# Architecture type - for HAPS x86_64/x86, for IPMATE ARM ++ % export ARCH=x86_64 ++# If BUS_INTERFACE not exported, PCI_INTERFACE is the default, for IPMATE use LM_INTERFACE ++ ++- Build the driver. ++ % make ++ ++- Install the driver (by default /lib/modules/x.x.xx.x/extra or export INSTALL_MOD_PATH for custom directory) ++ % make install ++ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_cfi_common.h b/drivers/usb/host/fh_otg/fh_otg/fh_cfi_common.h +new file mode 100644 +index 00000000..34b453fd +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_cfi_common.h +@@ -0,0 +1,142 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__FH_CFI_COMMON_H__) ++#define __FH_CFI_COMMON_H__ ++ ++//#include <linux/types.h> ++ ++/** ++ * @file ++ * ++ * This file contains the CFI specific common constants, interfaces ++ * (functions and macros) and structures for Linux. No PCD specific ++ * data structure or definition is to be included in this file. ++ * ++ */ ++ ++/** This is a request for all Core Features */ ++#define VEN_CORE_GET_FEATURES 0xB1 ++ ++/** This is a request to get the value of a specific Core Feature */ ++#define VEN_CORE_GET_FEATURE 0xB2 ++ ++/** This command allows the host to set the value of a specific Core Feature */ ++#define VEN_CORE_SET_FEATURE 0xB3 ++ ++/** This command allows the host to set the default values of ++ * either all or any specific Core Feature ++ */ ++#define VEN_CORE_RESET_FEATURES 0xB4 ++ ++/** This command forces the PCD to write the deferred values of a Core Features */ ++#define VEN_CORE_ACTIVATE_FEATURES 0xB5 ++ ++/** This request reads a DWORD value from a register at the specified offset */ ++#define VEN_CORE_READ_REGISTER 0xB6 ++ ++/** This request writes a DWORD value into a register at the specified offset */ ++#define VEN_CORE_WRITE_REGISTER 0xB7 ++ ++/** This structure is the header of the Core Features dataset returned to ++ * the Host ++ */ ++struct cfi_all_features_header { ++/** The features header structure length is */ ++#define CFI_ALL_FEATURES_HDR_LEN 8 ++ /** ++ * The total length of the features dataset returned to the Host ++ */ ++ uint16_t wTotalLen; ++ ++ /** ++ * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H). ++ * This field identifies the version of the CFI Specification with which ++ * the device is compliant. ++ */ ++ uint16_t wVersion; ++ ++ /** The ID of the Core */ ++ uint16_t wCoreID; ++#define CFI_CORE_ID_UDC 1 ++#define CFI_CORE_ID_OTG 2 ++#define CFI_CORE_ID_WUDEV 3 ++ ++ /** Number of features returned by VEN_CORE_GET_FEATURES request */ ++ uint16_t wNumFeatures; ++} UPACKED; ++ ++typedef struct cfi_all_features_header cfi_all_features_header_t; ++ ++/** This structure is a header of the Core Feature descriptor dataset returned to ++ * the Host after the VEN_CORE_GET_FEATURES request ++ */ ++struct cfi_feature_desc_header { ++#define CFI_FEATURE_DESC_HDR_LEN 8 ++ ++ /** The feature ID */ ++ uint16_t wFeatureID; ++ ++ /** Length of this feature descriptor in bytes - including the ++ * length of the feature name string ++ */ ++ uint16_t wLength; ++ ++ /** The data length of this feature in bytes */ ++ uint16_t wDataLength; ++ ++ /** ++ * Attributes of this features ++ * D0: Access rights ++ * 0 - Read/Write ++ * 1 - Read only ++ */ ++ uint8_t bmAttributes; ++#define CFI_FEATURE_ATTR_RO 1 ++#define CFI_FEATURE_ATTR_RW 0 ++ ++ /** Length of the feature name in bytes */ ++ uint8_t bNameLen; ++ ++ /** The feature name buffer */ ++ //uint8_t *name; ++} UPACKED; ++ ++typedef struct cfi_feature_desc_header cfi_feature_desc_header_t; ++ ++/** ++ * This structure describes a NULL terminated string referenced by its id field. ++ * It is very similar to usb_string structure but has the id field type set to 16-bit. ++ */ ++struct cfi_string { ++ uint16_t id; ++ const uint8_t *s; ++}; ++typedef struct cfi_string cfi_string_t; ++ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.c +new file mode 100644 +index 00000000..55f1e9d5 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.c +@@ -0,0 +1,908 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_adp.c $ ++ * $Revision: #16 $ ++ * $Date: 2013/04/22 $ ++ * $Change: 2211149 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#include "../fh_common_port/fh_os.h" ++#include "fh_otg_regs.h" ++#include "fh_otg_cil.h" ++#include "fh_otg_adp.h" ++ ++/** @file ++ * ++ * This file contains the most of the Attach Detect Protocol implementation for ++ * the driver to support OTG Rev2.0. ++ * ++ */ ++ ++void fh_otg_adp_write_reg(fh_otg_core_if_t * core_if, uint32_t value) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = value; ++ adpctl.b.ar = 0x2; ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = FH_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++} ++ ++/** ++ * Function is called to read ADP registers ++ */ ++uint32_t fh_otg_adp_read_reg(fh_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = 0; ++ adpctl.b.ar = 0x1; ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = FH_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to read ADPCTL register and filter Write-clear bits ++ */ ++uint32_t fh_otg_adp_read_reg_filter(fh_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 0; ++ adpctl.b.adp_prb_int = 0; ++ adpctl.b.adp_tmout_int = 0; ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to write ADP registers ++ */ ++void fh_otg_adp_modify_reg(fh_otg_core_if_t * core_if, uint32_t clr, ++ uint32_t set) ++{ ++ fh_otg_adp_write_reg(core_if, ++ (fh_otg_adp_read_reg(core_if) & (~clr)) | set); ++} ++ ++static void adp_probe_func(void * ptr) ++{ ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) ptr; ++ fh_otg_adp_probe_start(core_if); ++} ++ ++static void adp_sense_timeout(void *ptr) ++{ ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) ptr; ++ core_if->adp.sense_timer_started = 0; ++ FH_DEBUGPL(DBG_PCD, "ADP SENSE TIMEOUT\n"); ++ if (core_if->adp_enable) { ++ fh_otg_adp_sense_stop(core_if); ++ FH_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, adp_probe_func, ++ core_if, 100 , "start probe"); ++ } ++} ++ ++/** ++ * This function is called when the ADP vbus timer expires. Timeout is 1.1s. ++ */ ++static void adp_vbuson_timeout(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn; ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) ptr; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ FH_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__); ++ if (core_if) { ++ core_if->adp.vbuson_timer_started = 0; ++ if(fh_otg_is_host_mode(core_if)) { ++ /* Turn off vbus */ ++ hprt0.b.prtpwr = 1; ++ FH_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0); ++ cil_hcd_disconnect(core_if); ++ } ++ gpwrdn.d32 = 0; ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ /* Enable Wakeup Logic */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ /* Suspend the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Switch on VDD */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ } else { ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ if(fh_otg_is_host_mode(core_if)) ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ fh_mdelay(220); ++ fh_otg_adp_probe_start(core_if); ++ } ++ ++} ++ ++/** ++ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is ++ * not asserted within 1.1 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void fh_otg_adp_vbuson_timer_start(fh_otg_core_if_t * core_if) ++{ ++ core_if->adp.vbuson_timer_started = 1; ++ if (core_if->adp.vbuson_timer) ++ { ++ FH_PRINTF("SCHEDULING VBUSON TIMER\n"); ++ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ ++ FH_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); ++ } else { ++ FH_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); ++ } ++} ++ ++#if 0 ++/** ++ * Masks all FH OTG core interrupts ++ * ++ */ ++static void mask_all_interrupts(fh_otg_core_if_t * core_if) ++{ ++ int i; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ++ /* Mask Host Interrupts */ ++ ++ /* Clear and disable HCINTs */ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ FH_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0); ++ FH_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF); ++ ++ } ++ ++ /* Clear and disable HAINT */ ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000); ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF); ++ ++ /* Mask Device Interrupts */ ++ if (!core_if->multiproc_int_enable) { ++ /* Clear and disable IN Endpoint interrupts */ ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable OUT Endpoint interrupts */ ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable DAINT */ ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint, ++ 0xFFFFFFFF); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0); ++ } else { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ 0); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint, ++ 0xFFFFFFFF); ++ ++ } ++ ++ /* Disable interrupts */ ++ ahbcfg.b.glblintrmsk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++ ++ /* Disable all interrupts. */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Clear any pending OTG Interrupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF); ++} ++ ++/** ++ * Unmask Port Connection Detected interrupt ++ * ++ */ ++static void unmask_conn_det_intr(fh_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 }; ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++} ++#endif ++ ++/** ++ * Starts the ADP Probing ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++uint32_t fh_otg_adp_probe_start(fh_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl = {.d32 = 0}; ++ gpwrdn_data_t gpwrdn; ++#if 0 ++ adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1, ++ .b.adp_sns_int = 1, b.adp_tmout_int}; ++#endif ++ if (core_if->stop_adpprb) { ++ core_if->stop_adpprb = 0; ++ return 0; ++ } ++ ++ fh_otg_disable_global_interrupts(core_if); ++ FH_DEBUGPL(DBG_ANY, "ADP Probe Start\n"); ++ core_if->adp.probe_enabled = 1; ++ ++ adpctl.b.adpres = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.d32 = 0; ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* In Host mode unmask SRP detected interrupt also change the ++ * probe preiod accordingly */ ++ if (!gpwrdn.b.idsts) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ adpctl.b.prb_per = 0; ++ } ++ else { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.sts_chngint_msk = 1; ++ adpctl.b.prb_per = 1; ++ } ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ adpctl.b.adp_tmout_int_msk = 1; ++ adpctl.b.adp_prb_int_msk = 1; ++ adpctl.b.prb_dschg = 1; ++ adpctl.b.prb_delta = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ adpctl.b.adpen = 1; ++ adpctl.b.enaprb = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ FH_DEBUGPL(DBG_ANY, "ADP Probe Finish\n"); ++ ++ return 0; ++} ++ ++/** ++ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted ++ * within 3 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void fh_otg_adp_sense_timer_start(fh_otg_core_if_t * core_if) ++{ ++ core_if->adp.sense_timer_started = 1; ++ FH_TIMER_SCHEDULE(core_if->adp.sense_timer, 3300 /* 3.3 secs */ ); ++} ++ ++/** ++ * Starts the ADP Sense ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t fh_otg_adp_sense_start(fh_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ FH_DEBUGPL(DBG_PCD, "ADP Sense Start\n"); ++ ++ /* Set ADP reset bit*/ ++ adpctl.d32 = fh_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adpres = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ } ++ ++ /* Unmask ADP sense interrupt and mask all other from the core */ ++ adpctl.d32 = fh_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adp_sns_int_msk = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ fh_otg_disable_global_interrupts(core_if); ++ ++ adpctl.b.adpres = 0; ++ adpctl.b.adpen = 1; ++ adpctl.b.enasns = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ fh_otg_adp_sense_timer_start(core_if); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Probing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t fh_otg_adp_probe_stop(fh_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl; ++ FH_DEBUGPL(DBG_ANY, "Stop ADP probe\n"); ++ core_if->adp.probe_enabled = 0; ++ //core_if->adp.probe_counter = 0; ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ ++ adpctl.b.adpen = 0; ++ adpctl.b.adp_prb_int = 1; ++ adpctl.b.adp_tmout_int = 1; ++ adpctl.b.adp_sns_int = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Sensing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t fh_otg_adp_sense_stop(fh_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ core_if->adp.sense_enabled = 0; ++ ++ adpctl.d32 = fh_otg_adp_read_reg_filter(core_if); ++ adpctl.b.enasns = 0; ++ adpctl.b.adp_sns_int = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Called to turn on the VBUS after initial ADP probe in host mode. ++ * If port power was already enabled in cil_hcd_start function then ++ * only schedule a timer. ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++void fh_otg_adp_turnon_vbus(fh_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ FH_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); ++ ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ //FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ fh_otg_adp_vbuson_timer_start(core_if); ++} ++ ++/** ++ * Called right after driver is loaded ++ * to perform initial actions for ADP ++ * ++ * @param core_if the pointer to core_if structure. ++ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN ++ */ ++void fh_otg_adp_start(fh_otg_core_if_t * core_if, uint8_t is_host) ++{ ++ gpwrdn_data_t gpwrdn; ++ ++ FH_DEBUGPL(DBG_ANY, "ADP Initial Start\n"); ++ core_if->adp.adp_started = 1; ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ fh_otg_disable_global_interrupts(core_if); ++ if (is_host) { ++ FH_PRINTF("HOST MODE\n"); ++ //core_if->op_state = A_HOST; - vahrama, modified checking in hcd_start() ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Initialize first ADP probe to obtain Ramp Time value */ ++ core_if->adp.initial_probe = 1; ++ fh_otg_adp_probe_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ gotgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ FH_DEBUGPL(DBG_ANY, "DEVICE MODE\n"); ++ //fh_otg_core_init(core_if); ++ if (gotgctl.b.bsesvld == 0) { ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ FH_DEBUGPL(DBG_ANY, "VBUS is not valid - start ADP probe\n"); ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Do not need to return to inital probe if we are coming back to ++ * the device mode after HNP */ ++ if (core_if->op_state != B_HOST) ++ core_if->adp.initial_probe = 1; ++ fh_otg_adp_probe_start(core_if); ++ } else { ++ FH_PRINTF("VBUS is valid - initialize core as a Device\n"); ++ core_if->op_state = B_PERIPHERAL; ++ //fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ fh_otg_dump_global_registers(core_if); ++ fh_otg_dump_dev_registers(core_if); ++ } ++ } ++} ++ ++void fh_otg_adp_init(fh_otg_core_if_t * core_if) ++{ ++ core_if->adp.adp_started = 0; ++ core_if->adp.initial_probe = 0; ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.sense_enabled = 0; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ core_if->adp.attached = FH_OTG_ADP_UNKOWN; ++ /* Initialize timers */ ++ core_if->adp.sense_timer = ++ FH_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if); ++ core_if->adp.vbuson_timer = ++ FH_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if); ++ if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer) ++ { ++ FH_ERROR("Could not allocate memory for ADP timers\n"); ++ } ++} ++ ++void fh_otg_adp_remove(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (core_if->adp.probe_enabled) ++ fh_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ fh_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ FH_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ FH_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ FH_TIMER_FREE(core_if->adp.sense_timer); ++ FH_TIMER_FREE(core_if->adp.vbuson_timer); ++} ++ ++///////////////////////////////////////////////////////////////////// ++////////////// ADP Interrupt Handlers /////////////////////////////// ++///////////////////////////////////////////////////////////////////// ++/** ++ * This function sets Ramp Timer values ++ */ ++static uint32_t set_timer_value(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ if (core_if->adp.probe_timer_values[0] == -1) { ++ core_if->adp.probe_timer_values[0] = val; ++ core_if->adp.probe_timer_values[1] = -1; ++ return 1; ++ } else { ++ core_if->adp.probe_timer_values[1] = ++ core_if->adp.probe_timer_values[0]; ++ core_if->adp.probe_timer_values[0] = val; ++ return 0; ++ } ++} ++ ++/** ++ * This function compares Ramp Timer values ++ */ ++static uint32_t compare_timer_values(fh_otg_core_if_t * core_if) ++{ ++ uint32_t diff; ++ uint32_t thres; ++ gpwrdn_data_t gpwrdn; ++ ++ /* RTIM difference thresold differs for host and device modes */ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.idsts) ++ thres = HOST_RTIM_THRESHOLD; ++ else ++ thres = DEVICE_RTIM_THRESHOLD; ++ ++ FH_DEBUGPL(DBG_ANY, "timer value 0 %d timer value 1 %d\n", ++ core_if->adp.probe_timer_values[0], core_if->adp.probe_timer_values[1]); ++ if (core_if->adp.probe_timer_values[0] >= core_if->adp.probe_timer_values[1]) ++ diff = core_if->adp.probe_timer_values[0] - core_if->adp.probe_timer_values[1]; ++ else ++ diff = core_if->adp.probe_timer_values[1] - core_if->adp.probe_timer_values[0]; ++ if (diff < thres) ++ return 0; ++ else ++ return 1; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t fh_otg_adp_handle_prb_intr(fh_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn, temp; ++ adpctl.d32 = val; ++ ++ temp.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ core_if->adp.gpwrdn = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (adpctl.b.rtim == 0 /*&& !temp.b.idsts*/){ ++ FH_PRINTF("RTIM value is 0\n"); ++ goto exit; ++ } ++ core_if->adp.probe_counter++; ++ ++ if (set_timer_value(core_if, adpctl.b.rtim) && ++ core_if->adp.initial_probe) { ++ core_if->adp.initial_probe = 0; ++ fh_otg_adp_probe_stop(core_if); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Choose right op_state depending on previous one */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ fh_otg_enable_global_interrupts(core_if); ++ /* ++ * Turn on VBUS after initial ADP probe. ++ */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_hcd_start(core_if); ++ fh_otg_adp_turnon_vbus(core_if); ++ FH_SPINLOCK(core_if->lock); ++ } else { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ fh_otg_enable_global_interrupts(core_if); ++ fh_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp.probe_counter > 2){ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (compare_timer_values(core_if)) { ++ FH_PRINTF("Difference in timer values !!! \n"); ++// core_if->adp.attached = FH_OTG_ADP_ATTACHED; ++ fh_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ * Choose right op_state depending on previous one ++ */ ++ if (core_if->op_state == B_PERIPHERAL) ++ core_if->op_state = B_HOST; ++ else ++ core_if->op_state = A_HOST; ++ ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ fh_otg_adp_turnon_vbus(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ //fh_otg_core_init(core_if); ++ cil_pcd_start(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ ++ gotgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (!gotgctl.b.bsesvld) ++ fh_otg_initiate_srp(core_if); ++ } ++ } ++ if (core_if->power_down == 2) { ++ if (gpwrdn.b.bsessvld) { ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ } ++exit: ++ /* Clear interrupt */ ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ adpctl.b.adp_prb_int = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function hadles ADP Sense Interrupt ++ */ ++static int32_t fh_otg_adp_handle_sns_intr(fh_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ /* Stop ADP Sense timer */ ++ FH_TIMER_CANCEL(core_if->adp.sense_timer); ++ ++ /* Restart ADP Sense timer */ ++ fh_otg_adp_sense_timer_start(core_if); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ adpctl.b.adp_sns_int = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t fh_otg_adp_handle_prb_tmout_intr(fh_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ adpctl.d32 = val; ++ set_timer_value(core_if, adpctl.b.rtim); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 1; ++ fh_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * ADP Interrupt handler. ++ * ++ */ ++int32_t fh_otg_adp_handle_intr(fh_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ adpctl_data_t adpctl = {.d32 = 0}; ++ ++ adpctl.d32 = fh_otg_adp_read_reg(core_if); ++ FH_DEBUGPL(DBG_ANY, "ADPCTL = %08x RAMP TIME = %d\n", adpctl.d32, adpctl.b.rtim); ++ ++ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { ++ FH_DEBUGPL(DBG_ANY, "ADP Sense interrupt\n"); ++ retval |= fh_otg_adp_handle_sns_intr(core_if); ++ } ++ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { ++ FH_DEBUGPL(DBG_ANY, "ADP timeout interrupt\n"); ++ retval |= fh_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); ++ } ++ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { ++ FH_DEBUGPL(DBG_ANY, "ADP Probe interrupt\n"); ++ adpctl.b.adp_prb_int = 1; ++ retval |= fh_otg_adp_handle_prb_intr(core_if, adpctl.d32); ++ } ++ ++// fh_otg_adp_modify_reg(core_if, adpctl.d32, 0); ++ //fh_otg_adp_write_reg(core_if, adpctl.d32); ++ FH_DEBUGPL(DBG_ANY, "RETURN FROM ADP ISR\n"); ++ ++ return retval; ++} ++ ++/** ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++int32_t fh_otg_adp_handle_srp_intr(fh_otg_core_if_t * core_if) ++{ ++ ++#ifndef FH_HOST_ONLY ++ hprt0_data_t hprt0; ++ gpwrdn_data_t gpwrdn; ++ FH_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); ++ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /* check which value is for device mode and which for Host mode */ ++ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ ++ FH_PRINTF("SRP: Host mode\n"); ++ ++ if (core_if->adp_enable) { ++ fh_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } else { ++ FH_DEBUGPL(DBG_PCD, "SRP: Device mode %s\n", __FUNCTION__); ++ if (core_if->adp_enable) { ++ fh_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 0; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++#endif ++ return 1; ++} +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.h +new file mode 100644 +index 00000000..3ecc22ef +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_adp.h +@@ -0,0 +1,82 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_adp.h $ ++ * $Revision: #8 $ ++ * $Date: 2013/04/09 $ ++ * $Change: 2201932 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __FH_OTG_ADP_H__ ++#define __FH_OTG_ADP_H__ ++ ++/** ++ * @file ++ * ++ * This file contains the Attach Detect Protocol interfaces and defines ++ * (functions) and structures for Linux. ++ * ++ */ ++ ++#define FH_OTG_ADP_UNATTACHED 0 ++#define FH_OTG_ADP_ATTACHED 1 ++#define FH_OTG_ADP_UNKOWN 2 ++#define HOST_RTIM_THRESHOLD 5 ++#define DEVICE_RTIM_THRESHOLD 3 ++ ++typedef struct fh_otg_adp { ++ uint32_t adp_started; ++ uint32_t initial_probe; ++ int32_t probe_timer_values[2]; ++ uint32_t probe_enabled; ++ uint32_t sense_enabled; ++ fh_timer_t *sense_timer; ++ uint32_t sense_timer_started; ++ fh_timer_t *vbuson_timer; ++ uint32_t vbuson_timer_started; ++ uint32_t attached; ++ uint32_t probe_counter; ++ uint32_t gpwrdn; ++} fh_otg_adp_t; ++ ++/** ++ * Attach Detect Protocol functions ++ */ ++ ++extern void fh_otg_adp_write_reg(fh_otg_core_if_t * core_if, uint32_t value); ++extern uint32_t fh_otg_adp_read_reg(fh_otg_core_if_t * core_if); ++extern uint32_t fh_otg_adp_probe_start(fh_otg_core_if_t * core_if); ++extern uint32_t fh_otg_adp_sense_start(fh_otg_core_if_t * core_if); ++extern uint32_t fh_otg_adp_probe_stop(fh_otg_core_if_t * core_if); ++extern uint32_t fh_otg_adp_sense_stop(fh_otg_core_if_t * core_if); ++extern void fh_otg_adp_start(fh_otg_core_if_t * core_if, uint8_t is_host); ++extern void fh_otg_adp_init(fh_otg_core_if_t * core_if); ++extern void fh_otg_adp_remove(fh_otg_core_if_t * core_if); ++extern int32_t fh_otg_adp_handle_intr(fh_otg_core_if_t * core_if); ++extern int32_t fh_otg_adp_handle_srp_intr(fh_otg_core_if_t * core_if); ++ ++#endif //__FH_OTG_ADP_H__ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.c +new file mode 100644 +index 00000000..648b08b9 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.c +@@ -0,0 +1,1440 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_attr.c $ ++ * $Revision: #47 $ ++ * $Date: 2015/08/07 $ ++ * $Change: 2913245 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. The Linux driver attributes ++ * feature will be used to provide the Linux Diagnostic ++ * Interface. These attributes are accessed through sysfs. ++ */ ++ ++/** @page "Linux Module Attributes" ++ * ++ * The Linux module attributes feature is used to provide the Linux ++ * Diagnostic Interface. These attributes are accessed through sysfs. ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. ++ ++ The following table shows the attributes. ++ <table> ++ <tr> ++ <td><b> Name</b></td> ++ <td><b> Description</b></td> ++ <td><b> Access</b></td> ++ </tr> ++ ++ <tr> ++ <td> mode </td> ++ <td> Returns the current mode: 0 for device mode, 1 for host mode</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hnpcapable </td> ++ <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> srpcapable </td> ++ <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> hsic_connect </td> ++ <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register. ++ Read returns the current value.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> inv_sel_hsic </td> ++ <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register. ++ Read returns the current value.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> hnp </td> ++ <td> Initiates the Host Negotiation Protocol. Read returns the status.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> srp </td> ++ <td> Initiates the Session Request Protocol. Read returns the status.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> buspower </td> ++ <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> bussuspend </td> ++ <td> Suspends the USB bus.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> busconnected </td> ++ <td> Gets the connection status of the bus</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> gotgctl </td> ++ <td> Gets or sets the Core Control Status Register.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> gusbcfg </td> ++ <td> Gets or sets the Core USB Configuration Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> grxfsiz </td> ++ <td> Gets or sets the Receive FIFO Size Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> gnptxfsiz </td> ++ <td> Gets or sets the non-periodic Transmit Size Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> gpvndctl </td> ++ <td> Gets or sets the PHY Vendor Control Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> ggpio </td> ++ <td> Gets the value in the lower 16-bits of the General Purpose IO Register ++ or sets the upper 16 bits.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> guid </td> ++ <td> Gets or sets the value of the User ID Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> gsnpsid </td> ++ <td> Gets the value of the Synopsys ID Regester</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> devspeed </td> ++ <td> Gets or sets the device speed setting in the DCFG register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> enumspeed </td> ++ <td> Gets the device enumeration Speed.</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hptxfsiz </td> ++ <td> Gets the value of the Host Periodic Transmit FIFO</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hprt0 </td> ++ <td> Gets or sets the value in the Host Port Control and Status Register</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> regoffset </td> ++ <td> Sets the register offset for the next Register Access</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> regvalue </td> ++ <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> remote_wakeup </td> ++ <td> On read, shows the status of Remote Wakeup. On write, initiates a remote ++ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote ++ Wakeup signalling bit in the Device Control Register is set for 1 ++ milli-second.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> rem_wakeup_pwrdn </td> ++ <td> On read, shows the status core - hibernated or not. On write, initiates ++ a remote wakeup of the device from Hibernation. </td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> mode_ch_tim_en </td> ++ <td> This bit is used to enable or disable the host core to wait for 200 PHY ++ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 ++ after Suspend or LPM. </td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> fr_interval </td> ++ <td> On read, shows the value of HFIR Frame Interval. On write, dynamically ++ reload HFIR register during runtime. The application can write a value to this ++ register only after the Port Enable bit of the Host Port Control and Status ++ register (HPRT.PrtEnaPort) has been set </td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> disconnect_us </td> ++ <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us ++ which causes soft disconnect for 100us. Applicable only for device mode of operation.</td> ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> regdump </td> ++ <td> Dumps the contents of core registers.</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> spramdump </td> ++ <td> Dumps the contents of core registers.</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hcddump </td> ++ <td> Dumps the current HCD state.</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hcd_frrem </td> ++ <td> Shows the average value of the Frame Remaining ++ field in the Host Frame Number/Frame Remaining register when an SOF interrupt ++ occurs. This can be used to determine the average interrupt latency. Also ++ shows the average Frame Remaining value for start_transfer and the "a" and ++ "b" sample points. The "a" and "b" sample points may be used during debugging ++ bto determine how long it takes to execute a section of the HCD code.</td> ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> rd_reg_test </td> ++ <td> Displays the time required to read the GNPTXFSIZ register many times ++ (the output shows the number of times the register is read). ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> wr_reg_test </td> ++ <td> Displays the time required to write the GNPTXFSIZ register many times ++ (the output shows the number of times the register is written). ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> lpm_response </td> ++ <td> Gets or sets lpm_response mode. Applicable only in device mode. ++ <td> Write</td> ++ </tr> ++ ++ <tr> ++ <td> sleep_status </td> ++ <td> Shows sleep status of device. ++ <td> Read</td> ++ </tr> ++ ++ <tr> ++ <td> hird_thres </td> ++ <td> Gets or sets the "HIRD_Thres[3:0]" bits in the Core LPM Configuration Register. ++ <td> Read/Write</td> ++ </tr> ++ ++ <tr> ++ <td> besl_reject </td> ++ <td> Gets or sets the "besl_reject" bit in the Device Control Register. ++ <td> Read/Write</td> ++ </tr> ++ ++ </table> ++ ++ Example usage: ++ To get the current mode: ++ cat /sys/devices/lm0/mode ++ ++ To power down the USB: ++ echo 0 > /sys/devices/lm0/buspower ++ */ ++#include <linux/platform_device.h> ++ ++#include "fh_otg_os_dep.h" ++#include "../fh_common_port/fh_os.h" ++#include "fh_otg_driver.h" ++#include "fh_otg_attr.h" ++#include "fh_otg_core_if.h" ++#include "fh_otg_pcd_if.h" ++#include "fh_otg_hcd_if.h" ++ ++/* ++ * MACROs for defining sysfs attribute ++ */ ++#ifdef LM_INTERFACE ++ ++#define FH_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = fh_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define FH_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ fh_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++#elif defined(PCI_INTERFACE) ++ ++#define FH_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val; \ ++ val = fh_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define FH_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ fh_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++#endif ++ ++/* ++ * MACROs for defining sysfs attribute for 32-bit registers ++ */ ++#ifdef LM_INTERFACE ++#define FH_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = fh_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define FH_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ fh_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++#elif defined(PCI_INTERFACE) ++#define FH_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val; \ ++ val = fh_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define FH_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ fh_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++ ++#endif ++ ++#define FH_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \ ++FH_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++FH_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define FH_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \ ++FH_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++#define FH_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \ ++FH_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++FH_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define FH_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \ ++FH_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++/** @name Functions for Show/Store of Attributes */ ++/**@{*/ ++ ++/** ++ * Show the register offset of the Register Access. ++ */ ++static ssize_t regoffset_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", ++ otg_dev->os_dep.reg_offset); ++} ++ ++/** ++ * Set the register offset for the next Register Access Read/Write ++ */ ++static ssize_t regoffset_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t offset = simple_strtoul(buf, NULL, 16); ++#ifdef LM_INTERFACE ++ if (offset < SZ_256K) { ++#elif defined(PCI_INTERFACE) ++ if (offset < 0x00040000) { ++#endif ++ otg_dev->os_dep.reg_offset = offset; ++ } else { ++ dev_err(_dev, "invalid offset\n"); ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); ++ ++/** ++ * Show the value of the register at the offset in the reg_offset ++ * attribute. ++ */ ++static ssize_t regvalue_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t val; ++ volatile uint32_t *addr; ++ ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ val = FH_READ_REG32(addr); ++ return snprintf(buf, ++ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, ++ val); ++ } else { ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); ++ return sprintf(buf, "invalid offset\n"); ++ } ++} ++ ++/** ++ * Store the value in the register at the offset in the reg_offset ++ * attribute. ++ * ++ */ ++static ssize_t regvalue_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ volatile uint32_t *addr; ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ FH_WRITE_REG32(addr, val); ++ } else { ++ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", ++ otg_dev->os_dep.reg_offset); ++ } ++ return count; ++} ++ ++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); ++ ++/* ++ * Attributes ++ */ ++FH_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); ++ ++//FH_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++//FH_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected"); ++ ++FH_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL"); ++FH_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ "GUSBCFG"); ++FH_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, ++ &(otg_dev->core_if->core_global_regs->grxfsiz), ++ "GRXFSIZ"); ++FH_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, ++ &(otg_dev->core_if->core_global_regs->gnptxfsiz), ++ "GNPTXFSIZ"); ++FH_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, ++ &(otg_dev->core_if->core_global_regs->gpvndctl), ++ "GPVNDCTL"); ++FH_OTG_DEVICE_ATTR_REG32_RW(ggpio, ++ &(otg_dev->core_if->core_global_regs->ggpio), ++ "GGPIO"); ++FH_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), ++ "GUID"); ++FH_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, ++ &(otg_dev->core_if->core_global_regs->gsnpsid), ++ "GSNPSID"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed"); ++FH_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed"); ++ ++FH_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, ++ &(otg_dev->core_if->core_global_regs->hptxfsiz), ++ "HPTXFSIZ"); ++FH_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); ++ ++/** ++ * @todo Add code to initiate the HNP. ++ */ ++/** ++ * Show the HNP status bit ++ */ ++static ssize_t hnp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ return sprintf(buf, "HstNegScs = 0x%x\n", ++ fh_otg_get_hnpstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HNP Request bit ++ */ ++static ssize_t hnp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ fh_otg_set_hnpreq(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); ++ ++/** ++ * @todo Add code to initiate the SRP. ++ */ ++/** ++ * Show the SRP status bit ++ */ ++static ssize_t srp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ return sprintf(buf, "SesReqScs = 0x%x\n", ++ fh_otg_get_srpstatus(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Set the SRP Request bit ++ */ ++static ssize_t srp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ fh_otg_pcd_initiate_srp(otg_dev->pcd); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(srp, 0644, srp_show, srp_store); ++ ++/** ++ * @todo Need to do more for power on/off? ++ */ ++/** ++ * Show the Bus Power status ++ */ ++static ssize_t buspower_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ return sprintf(buf, "Bus Power = 0x%x\n", ++ fh_otg_get_prtpower(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Power status ++ */ ++static ssize_t buspower_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ uint32_t on = simple_strtoul(buf, NULL, 16); ++ fh_otg_set_prtpower(otg_dev->core_if, on); ++ return count; ++} ++ ++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); ++ ++/** ++ * @todo Need to do more for suspend? ++ */ ++/** ++ * Show the Bus Suspend status ++ */ ++static ssize_t bussuspend_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return sprintf(buf, "Bus Suspend = 0x%x\n", ++ fh_otg_get_prtsuspend(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Suspend status ++ */ ++static ssize_t bussuspend_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ fh_otg_set_prtsuspend(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); ++ ++/** ++ * Show the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", ++ fh_otg_get_mode_ch_tim(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ fh_otg_set_mode_ch_tim(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); ++ ++/** ++ * Show the value of HFIR Frame Interval bitfield ++ */ ++static ssize_t fr_interval_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return sprintf(buf, "Frame Interval = 0x%x\n", ++ fh_otg_get_fr_interval(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HFIR Frame Interval value ++ */ ++static ssize_t fr_interval_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t in = simple_strtoul(buf, NULL, 10); ++ fh_otg_set_fr_interval(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); ++ ++/** ++ * Show the status of Remote Wakeup. ++ */ ++static ssize_t remote_wakeup_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return sprintf(buf, ++ "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", ++ fh_otg_get_remotewakesig(otg_dev->core_if), ++ fh_otg_pcd_get_rmwkup_enable(otg_dev->pcd), ++ fh_otg_get_lpm_remotewakeenabled(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif /* FH_HOST_ONLY */ ++} ++ ++/** ++ * Initiate a remote wakeup of the host. The Device control register ++ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable ++ * flag is set. ++ * ++ */ ++static ssize_t remote_wakeup_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (val & 1) { ++ fh_otg_pcd_remote_wakeup(otg_dev->pcd, 1); ++ } else { ++ fh_otg_pcd_remote_wakeup(otg_dev->pcd, 0); ++ } ++#endif /* FH_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, ++ remote_wakeup_store); ++ ++/** ++ * Show the whether core is hibernated or not. ++ */ ++static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ if (fh_otg_get_core_state(otg_dev->core_if)) { ++ FH_PRINTF("Core is in hibernation\n"); ++ } else { ++ FH_PRINTF("Core is not in hibernation\n"); ++ } ++#endif /* FH_HOST_ONLY */ ++ return 0; ++} ++ ++extern int fh_otg_device_hibernation_restore(fh_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/** ++ * Initiate a remote wakeup of the device to exit from hibernation. ++ */ ++static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ fh_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, ++ rem_wakeup_pwrdn_store); ++ ++static ssize_t disconnect_us(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++#ifndef FH_HOST_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ FH_PRINTF("The Passed value is %04x\n", val); ++ ++ fh_otg_pcd_disconnect_us(otg_dev->pcd, 50); ++ ++#endif /* FH_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t regdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ fh_otg_dump_global_registers(otg_dev->core_if); ++ if (fh_otg_is_host_mode(otg_dev->core_if)) { ++ fh_otg_dump_host_registers(otg_dev->core_if); ++ } else { ++ fh_otg_dump_dev_registers(otg_dev->core_if); ++ ++ } ++ return sprintf(buf, "Register Dump\n"); ++} ++ ++DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t spramdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ fh_otg_dump_spram(otg_dev->core_if); ++ ++ return sprintf(buf, "SPRAM Dump\n"); ++} ++ ++DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0); ++ ++/** ++ * Dump the current hcd state. ++ */ ++static ssize_t hcddump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef FH_DEVICE_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ fh_otg_hcd_dump_state(otg_dev->hcd); ++#endif /* FH_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump\n"); ++} ++ ++DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ */ ++static ssize_t hcd_frrem_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef FH_DEVICE_ONLY ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ fh_otg_hcd_dump_frrem(otg_dev->hcd); ++#endif /* FH_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump Frame Remaining\n"); ++} ++ ++DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0); ++ ++/** ++ * Displays the time required to read the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is read). ++ */ ++#define RW_REG_COUNT 10000000 ++#define MSEC_PER_JIFFIE 1000/HZ ++static ssize_t rd_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ fh_otg_get_gnptxfsiz(otg_dev->core_if); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0); ++ ++/** ++ * Displays the time required to write the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is written). ++ */ ++static ssize_t wr_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t reg_val; ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ reg_val = fh_otg_get_gnptxfsiz(otg_dev->core_if); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ fh_otg_set_gnptxfsiz(otg_dev->core_if, reg_val); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0); ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++ ++/** ++* Show the lpm_response attribute. ++*/ ++static ssize_t lpmresp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ return sprintf(buf, "lpm_response = %d\n", ++ fh_otg_get_lpmresponse(otg_dev->core_if)); ++} ++ ++/** ++* Store the lpm_response attribute. ++*/ ++static ssize_t lpmresp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ fh_otg_set_lpmresponse(otg_dev->core_if, val); ++ return count; ++} ++ ++DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store); ++ ++/** ++* Show the besl_reject attribute. ++*/ ++static ssize_t beslreject_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ if (!fh_otg_get_param_besl_enable(otg_dev->core_if)) ++ return sprintf(buf, "** EnBesl is DISABLED **\n"); ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "besl_reject = %d\n", ++ fh_otg_get_beslreject(otg_dev->core_if)); ++} ++ ++/** ++* Store the besl_reject attribute. ++*/ ++static ssize_t beslreject_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!fh_otg_get_param_besl_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ fh_otg_set_beslreject(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(besl_reject, S_IRUGO | S_IWUSR, beslreject_show, beslreject_store); ++ ++/** ++* Show the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ ++ return sprintf(buf, "hirdthresh = 0x%x\n", ++ fh_otg_get_hirdthresh(otg_dev->core_if)); ++} ++ ++/** ++* Store the hird_thresh attribute. ++*/ ++static ssize_t hirdthresh_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!fh_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!fh_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ fh_otg_set_hirdthresh(otg_dev->core_if,val); ++ ++ return count; ++} ++ ++DEVICE_ATTR(hird_thres, S_IRUGO | S_IWUSR, hirdthresh_show, hirdthresh_store); ++ ++/** ++* Show the sleep_status attribute. ++*/ ++static ssize_t sleepstatus_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ return sprintf(buf, "Sleep Status = %d\n", ++ fh_otg_get_lpm_portsleepstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Store the sleep_status attribure. ++ */ ++static ssize_t sleepstatus_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifdef LM_INTERFACE ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); ++ fh_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); ++#elif defined(PCI_INTERFACE) ++ fh_otg_device_t *otg_dev = dev_get_drvdata(_dev); ++#endif ++ ++ fh_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ if (fh_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { ++ if (fh_otg_is_host_mode(core_if)) { ++ ++ FH_PRINTF("Host initiated resume\n"); ++ fh_otg_set_prtresume(otg_dev->core_if, 1); ++ } ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, ++ sleepstatus_store); ++ ++#endif /* CONFIG_USB_FH_OTG_LPM_ENABLE */ ++ ++/**@}*/ ++ ++/** ++ * Create the device files ++ */ ++void fh_otg_attr_create(struct platform_device *dev) ++{ ++ int error; ++ ++ error = device_create_file(&dev->dev, &dev_attr_regoffset); ++ error = device_create_file(&dev->dev, &dev_attr_regvalue); ++ error = device_create_file(&dev->dev, &dev_attr_mode); ++ error = device_create_file(&dev->dev, &dev_attr_hnpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_srpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_hsic_connect); ++ error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ error = device_create_file(&dev->dev, &dev_attr_hnp); ++ error = device_create_file(&dev->dev, &dev_attr_srp); ++ error = device_create_file(&dev->dev, &dev_attr_buspower); ++ error = device_create_file(&dev->dev, &dev_attr_bussuspend); ++ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ error = device_create_file(&dev->dev, &dev_attr_fr_interval); ++ error = device_create_file(&dev->dev, &dev_attr_busconnected); ++ error = device_create_file(&dev->dev, &dev_attr_gotgctl); ++ error = device_create_file(&dev->dev, &dev_attr_gusbcfg); ++ error = device_create_file(&dev->dev, &dev_attr_grxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gpvndctl); ++ error = device_create_file(&dev->dev, &dev_attr_ggpio); ++ error = device_create_file(&dev->dev, &dev_attr_guid); ++ error = device_create_file(&dev->dev, &dev_attr_gsnpsid); ++ error = device_create_file(&dev->dev, &dev_attr_devspeed); ++ error = device_create_file(&dev->dev, &dev_attr_enumspeed); ++ error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_hprt0); ++ error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); ++ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); ++ error = device_create_file(&dev->dev, &dev_attr_regdump); ++ error = device_create_file(&dev->dev, &dev_attr_spramdump); ++ error = device_create_file(&dev->dev, &dev_attr_hcddump); ++ error = device_create_file(&dev->dev, &dev_attr_hcd_frrem); ++ error = device_create_file(&dev->dev, &dev_attr_rd_reg_test); ++ error = device_create_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ error = device_create_file(&dev->dev, &dev_attr_lpm_response); ++ error = device_create_file(&dev->dev, &dev_attr_sleep_status); ++ error = device_create_file(&dev->dev, &dev_attr_besl_reject); ++ error = device_create_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} ++ ++/** ++ * Remove the device files ++ */ ++void fh_otg_attr_remove(struct platform_device *dev) ++{ ++ device_remove_file(&dev->dev, &dev_attr_regoffset); ++ device_remove_file(&dev->dev, &dev_attr_regvalue); ++ device_remove_file(&dev->dev, &dev_attr_mode); ++ device_remove_file(&dev->dev, &dev_attr_hnpcapable); ++ device_remove_file(&dev->dev, &dev_attr_srpcapable); ++ device_remove_file(&dev->dev, &dev_attr_hsic_connect); ++ device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ device_remove_file(&dev->dev, &dev_attr_hnp); ++ device_remove_file(&dev->dev, &dev_attr_srp); ++ device_remove_file(&dev->dev, &dev_attr_buspower); ++ device_remove_file(&dev->dev, &dev_attr_bussuspend); ++ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ device_remove_file(&dev->dev, &dev_attr_fr_interval); ++ device_remove_file(&dev->dev, &dev_attr_busconnected); ++ device_remove_file(&dev->dev, &dev_attr_gotgctl); ++ device_remove_file(&dev->dev, &dev_attr_gusbcfg); ++ device_remove_file(&dev->dev, &dev_attr_grxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gnptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gpvndctl); ++ device_remove_file(&dev->dev, &dev_attr_ggpio); ++ device_remove_file(&dev->dev, &dev_attr_guid); ++ device_remove_file(&dev->dev, &dev_attr_gsnpsid); ++ device_remove_file(&dev->dev, &dev_attr_devspeed); ++ device_remove_file(&dev->dev, &dev_attr_enumspeed); ++ device_remove_file(&dev->dev, &dev_attr_hptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_hprt0); ++ device_remove_file(&dev->dev, &dev_attr_remote_wakeup); ++ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ device_remove_file(&dev->dev, &dev_attr_disconnect_us); ++ device_remove_file(&dev->dev, &dev_attr_regdump); ++ device_remove_file(&dev->dev, &dev_attr_spramdump); ++ device_remove_file(&dev->dev, &dev_attr_hcddump); ++ device_remove_file(&dev->dev, &dev_attr_hcd_frrem); ++ device_remove_file(&dev->dev, &dev_attr_rd_reg_test); ++ device_remove_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ device_remove_file(&dev->dev, &dev_attr_lpm_response); ++ device_remove_file(&dev->dev, &dev_attr_sleep_status); ++ device_remove_file(&dev->dev, &dev_attr_besl_reject); ++ device_remove_file(&dev->dev, &dev_attr_hird_thres); ++#endif ++} +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.h +new file mode 100644 +index 00000000..cee86fd4 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_attr.h +@@ -0,0 +1,76 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_attr.h $ ++ * $Revision: #13 $ ++ * $Date: 2010/06/21 $ ++ * $Change: 1532021 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__FH_OTG_ATTR_H__) ++#define __FH_OTG_ATTR_H__ ++ ++#include <linux/platform_device.h> ++ ++/** @file ++ * This file contains the interface to the Linux device attributes. ++ */ ++extern struct device_attribute dev_attr_regoffset; ++extern struct device_attribute dev_attr_regvalue; ++ ++extern struct device_attribute dev_attr_mode; ++extern struct device_attribute dev_attr_hnpcapable; ++extern struct device_attribute dev_attr_srpcapable; ++extern struct device_attribute dev_attr_hnp; ++extern struct device_attribute dev_attr_srp; ++extern struct device_attribute dev_attr_buspower; ++extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_mode_ch_tim_en; ++extern struct device_attribute dev_attr_fr_interval; ++extern struct device_attribute dev_attr_busconnected; ++extern struct device_attribute dev_attr_gotgctl; ++extern struct device_attribute dev_attr_gusbcfg; ++extern struct device_attribute dev_attr_grxfsiz; ++extern struct device_attribute dev_attr_gnptxfsiz; ++extern struct device_attribute dev_attr_gpvndctl; ++extern struct device_attribute dev_attr_ggpio; ++extern struct device_attribute dev_attr_guid; ++extern struct device_attribute dev_attr_gsnpsid; ++extern struct device_attribute dev_attr_devspeed; ++extern struct device_attribute dev_attr_enumspeed; ++extern struct device_attribute dev_attr_hptxfsiz; ++extern struct device_attribute dev_attr_hprt0; ++#ifdef CONFIG_USB_FH_OTG_LPM ++extern struct device_attribute dev_attr_lpm_response; ++extern struct device_attribute devi_attr_sleep_status; ++#endif ++ ++void fh_otg_attr_create(struct platform_device *dev); ++ ++void fh_otg_attr_remove(struct platform_device *dev); ++ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.c +new file mode 100644 +index 00000000..d4f3cb87 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.c +@@ -0,0 +1,1876 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * This file contains the most of the CFI(Core Feature Interface) ++ * implementation for the OTG. ++ */ ++ ++#ifdef FH_UTE_CFI ++ ++#include "fh_otg_pcd.h" ++#include "fh_otg_cfi.h" ++ ++/** This definition should actually migrate to the Portability Library */ ++#define FH_CONSTANT_CPU_TO_LE16(x) (x) ++ ++extern fh_otg_pcd_ep_t *get_ep_by_addr(fh_otg_pcd_t * pcd, u16 wIndex); ++ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen); ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req); ++static int cfi_set_feature_value(struct fh_otg_pcd *pcd); ++static int cfi_ep_get_sg_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_concat_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_align_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_preproc_reset(struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep); ++ ++static uint16_t get_dfifo_size(fh_otg_core_if_t * core_if); ++static int32_t get_rxfifo_size(fh_otg_core_if_t * core_if, uint16_t wValue); ++static int32_t get_txfifo_size(struct fh_otg_pcd *pcd, uint16_t wValue); ++ ++static uint8_t resize_fifos(fh_otg_core_if_t * core_if); ++ ++/** This is the header of the all features descriptor */ ++static cfi_all_features_header_t all_props_desc_header = { ++ .wVersion = FH_CONSTANT_CPU_TO_LE16(0x100), ++ .wCoreID = FH_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG), ++ .wNumFeatures = FH_CONSTANT_CPU_TO_LE16(9), ++}; ++ ++/** This is an array of statically allocated feature descriptors */ ++static cfi_feature_desc_header_t prop_descs[] = { ++ ++ /* FT_ID_DMA_MODE */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(1), ++ }, ++ ++ /* FT_ID_DMA_BUFFER_SETUP */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_BUFF_ALIGN */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_DMA_CONCAT_SETUP */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ //.wDataLength = FH_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_CIRCULAR */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_THRESHOLD_SETUP */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DFIFO_DEPTH */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RO, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_TX_FIFO_DEPTH */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_RX_FIFO_DEPTH */ ++ { ++ .wFeatureID = FH_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = FH_CONSTANT_CPU_TO_LE16(2), ++ } ++}; ++ ++/** The table of feature names */ ++cfi_string_t prop_name_table[] = { ++ {FT_ID_DMA_MODE, "dma_mode"}, ++ {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"}, ++ {FT_ID_DMA_BUFF_ALIGN, "buffer_align"}, ++ {FT_ID_DMA_CONCAT_SETUP, "concat_setup"}, ++ {FT_ID_DMA_CIRCULAR, "buffer_circular"}, ++ {FT_ID_THRESHOLD_SETUP, "threshold_setup"}, ++ {FT_ID_DFIFO_DEPTH, "dfifo_depth"}, ++ {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"}, ++ {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"}, ++ {} ++}; ++ ++/************************************************************************/ ++ ++/** ++ * Returns the name of the feature by its ID ++ * or NULL if no featute ID matches. ++ * ++ */ ++const uint8_t *get_prop_name(uint16_t prop_id, int *len) ++{ ++ cfi_string_t *pstr; ++ *len = 0; ++ ++ for (pstr = prop_name_table; pstr && pstr->s; pstr++) { ++ if (pstr->id == prop_id) { ++ *len = FH_STRLEN(pstr->s); ++ return pstr->s; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * This function handles all CFI specific control requests. ++ * ++ * Return a negative value to stall the DCE. ++ */ ++int cfi_setup(struct fh_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) ++{ ++ int retval = 0; ++ fh_otg_pcd_ep_t *ep = NULL; ++ cfiobject_t *cfi = pcd->cfi; ++ struct fh_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t wLen = FH_LE16_TO_CPU(&ctrl->wLength); ++ uint16_t wValue = FH_LE16_TO_CPU(&ctrl->wValue); ++ uint16_t wIndex = FH_LE16_TO_CPU(&ctrl->wIndex); ++ uint32_t regaddr = 0; ++ uint32_t regval = 0; ++ ++ /* Save this Control Request in the CFI object. ++ * The data field will be assigned in the data stage completion CB function. ++ */ ++ cfi->ctrl_req = *ctrl; ++ cfi->ctrl_req.data = NULL; ++ ++ cfi->need_gadget_att = 0; ++ cfi->need_status_in_complete = 0; ++ ++ switch (ctrl->bRequest) { ++ case VEN_CORE_GET_FEATURES: ++ retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN); ++ if (retval >= 0) { ++ //dump_msg(cfi->buf_in.buf, retval); ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->fh_ep.dma_addr = cfi->buf_in.addr; ++ ep->fh_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_len = retval; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ fh_otg_ep0_start_transfer(coreif, &ep->fh_ep); ++ } ++ retval = 0; ++ break; ++ ++ case VEN_CORE_GET_FEATURE: ++ CFI_INFO("VEN_CORE_GET_FEATURE\n"); ++ retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN, ++ pcd, ctrl); ++ if (retval >= 0) { ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->fh_ep.dma_addr = cfi->buf_in.addr; ++ ep->fh_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_len = retval; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ fh_otg_ep0_start_transfer(coreif, &ep->fh_ep); ++ } ++ CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval); ++ dump_msg(cfi->buf_in.buf, retval); ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ CFI_INFO("VEN_CORE_SET_FEATURE\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the feature to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->fh_ep.is_in = 0; ++ ep->fh_ep.dma_addr = cfi->buf_out.addr; ++ ep->fh_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->fh_ep.xfer_buff = cfi->buf_out.buf; ++ ep->fh_ep.xfer_len = wLen; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ fh_otg_ep0_start_transfer(coreif, &ep->fh_ep); ++ retval = 0; ++ break; ++ ++ case VEN_CORE_RESET_FEATURES: ++ CFI_INFO("VEN_CORE_RESET_FEATURES\n"); ++ cfi->need_gadget_att = 1; ++ cfi->need_status_in_complete = 1; ++ retval = cfi_preproc_reset(pcd, ctrl); ++ CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval); ++ break; ++ ++ case VEN_CORE_ACTIVATE_FEATURES: ++ CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n"); ++ break; ++ ++ case VEN_CORE_READ_REGISTER: ++ CFI_INFO("VEN_CORE_READ_REGISTER\n"); ++ /* wValue optionally contains the HI WORD of the register offset and ++ * wIndex contains the LOW WORD of the register offset ++ */ ++ if (wValue == 0) { ++ /* @TODO - MAS - fix the access to the base field */ ++ regaddr = 0; ++ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; ++ //GET_CORE_IF(pcd)->co ++ regaddr |= wIndex; ++ } else { ++ regaddr = (wValue << 16) | wIndex; ++ } ++ ++ /* Read a 32-bit value of the memory at the regaddr */ ++ regval = FH_READ_REG32((uint32_t *) regaddr); ++ ++ ep = &pcd->ep0; ++ fh_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); ++ ep->fh_ep.is_in = 1; ++ ep->fh_ep.dma_addr = cfi->buf_in.addr; ++ ep->fh_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_buff = cfi->buf_in.buf; ++ ep->fh_ep.xfer_len = wLen; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ fh_otg_ep0_start_transfer(coreif, &ep->fh_ep); ++ cfi->need_gadget_att = 0; ++ retval = 0; ++ break; ++ ++ case VEN_CORE_WRITE_REGISTER: ++ CFI_INFO("VEN_CORE_WRITE_REGISTER\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the register to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->fh_ep.is_in = 0; ++ ep->fh_ep.dma_addr = cfi->buf_out.addr; ++ ep->fh_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->fh_ep.xfer_buff = cfi->buf_out.buf; ++ ep->fh_ep.xfer_len = wLen; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ fh_otg_ep0_start_transfer(coreif, &ep->fh_ep); ++ retval = 0; ++ break; ++ ++ default: ++ retval = -FH_E_NOT_SUPPORTED; ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function prepares the core features descriptors and copies its ++ * raw representation into the buffer <buf>. ++ * ++ * The buffer structure is as follows: ++ * all_features_header (8 bytes) ++ * features_#1 (8 bytes + feature name string length) ++ * features_#2 (8 bytes + feature name string length) ++ * ..... ++ * features_#n - where n=the total count of feature descriptors ++ */ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen) ++{ ++ cfi_feature_desc_header_t *prop_hdr = prop_descs; ++ cfi_feature_desc_header_t *prop; ++ cfi_all_features_header_t *all_props_hdr = &all_props_desc_header; ++ cfi_all_features_header_t *tmp; ++ uint8_t *tmpbuf = buf; ++ const uint8_t *pname = NULL; ++ int i, j, namelen = 0, totlen; ++ ++ /* Prepare and copy the core features into the buffer */ ++ CFI_INFO("%s:\n", __func__); ++ ++ tmp = (cfi_all_features_header_t *) tmpbuf; ++ *tmp = *all_props_hdr; ++ tmpbuf += CFI_ALL_FEATURES_HDR_LEN; ++ ++ j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t); ++ for (i = 0; i < j; i++, prop_hdr++) { ++ pname = get_prop_name(prop_hdr->wFeatureID, &namelen); ++ prop = (cfi_feature_desc_header_t *) tmpbuf; ++ *prop = *prop_hdr; ++ ++ prop->bNameLen = namelen; ++ prop->wLength = ++ FH_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN + ++ namelen); ++ ++ tmpbuf += CFI_FEATURE_DESC_HDR_LEN; ++ fh_memcpy(tmpbuf, pname, namelen); ++ tmpbuf += namelen; ++ } ++ ++ totlen = tmpbuf - buf; ++ ++ if (totlen > 0) { ++ tmp = (cfi_all_features_header_t *) buf; ++ tmp->wTotalLen = FH_CONSTANT_CPU_TO_LE16(totlen); ++ } ++ ++ return totlen; ++} ++ ++/** ++ * This function releases all the dynamic memory in the CFI object. ++ */ ++static void cfi_release(cfiobject_t * cfiobj) ++{ ++ cfi_ep_t *cfiep; ++ fh_list_link_t *tmp; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ if (cfiobj->buf_in.buf) { ++ FH_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, ++ cfiobj->buf_in.addr); ++ cfiobj->buf_in.buf = NULL; ++ } ++ ++ if (cfiobj->buf_out.buf) { ++ FH_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, ++ cfiobj->buf_out.addr); ++ cfiobj->buf_out.buf = NULL; ++ } ++ ++ /* Free the Buffer Setup values for each EP */ ++ //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) { ++ FH_LIST_FOREACH(tmp, &cfiobj->active_eps) { ++ cfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ cfi_free_ep_bs_dyn_data(cfiep); ++ } ++} ++ ++/** ++ * This function frees the dynamically allocated EP buffer setup data. ++ */ ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) ++{ ++ if (cfiep->bm_sg) { ++ FH_FREE(cfiep->bm_sg); ++ cfiep->bm_sg = NULL; ++ } ++ ++ if (cfiep->bm_align) { ++ FH_FREE(cfiep->bm_align); ++ cfiep->bm_align = NULL; ++ } ++ ++ if (cfiep->bm_concat) { ++ if (NULL != cfiep->bm_concat->wTxBytes) { ++ FH_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ FH_FREE(cfiep->bm_concat); ++ cfiep->bm_concat = NULL; ++ } ++} ++ ++/** ++ * This function initializes the default values of the features ++ * for a specific endpoint and should be called only once when ++ * the EP is enabled first time. ++ */ ++static int cfi_ep_init_defaults(struct fh_otg_pcd *pcd, cfi_ep_t * cfiep) ++{ ++ int retval = 0; ++ ++ cfiep->bm_sg = FH_ALLOC(sizeof(ddma_sg_buffer_setup_t)); ++ if (NULL == cfiep->bm_sg) { ++ CFI_INFO("Failed to allocate memory for SG feature value\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ fh_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ ++ /* For the Concatenation feature's default value we do not allocate ++ * memory for the wTxBytes field - it will be done in the set_feature_value ++ * request handler. ++ */ ++ cfiep->bm_concat = FH_ALLOC(sizeof(ddma_concat_buffer_setup_t)); ++ if (NULL == cfiep->bm_concat) { ++ CFI_INFO ++ ("Failed to allocate memory for CONCATENATION feature value\n"); ++ FH_FREE(cfiep->bm_sg); ++ return -FH_E_NO_MEMORY; ++ } ++ fh_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ ++ cfiep->bm_align = FH_ALLOC(sizeof(ddma_align_buffer_setup_t)); ++ if (NULL == cfiep->bm_align) { ++ CFI_INFO ++ ("Failed to allocate memory for Alignment feature value\n"); ++ FH_FREE(cfiep->bm_sg); ++ FH_FREE(cfiep->bm_concat); ++ return -FH_E_NO_MEMORY; ++ } ++ fh_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); ++ ++ return retval; ++} ++ ++/** ++ * The callback function that notifies the CFI on the activation of ++ * an endpoint in the PCD. The following steps are done in this function: ++ * ++ * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's ++ * active endpoint) ++ * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP ++ * Set the Buffer Mode to standard ++ * Initialize the default values for all EP modes (SG, Circular, Concat, Align) ++ * Add the cfi_ep_t object to the list of active endpoints in the CFI object ++ */ ++static int cfi_ep_enable(struct cfiobject *cfi, struct fh_otg_pcd *pcd, ++ struct fh_otg_pcd_ep *ep) ++{ ++ cfi_ep_t *cfiep; ++ int retval = -FH_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__, ++ "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress); ++ /* MAS - Check whether this endpoint already is in the list */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ ++ if (NULL == cfiep) { ++ /* Allocate a cfi_ep_t object */ ++ cfiep = FH_ALLOC(sizeof(cfi_ep_t)); ++ if (NULL == cfiep) { ++ CFI_INFO ++ ("Unable to allocate memory for <cfiep> in function %s\n", ++ __func__); ++ return -FH_E_NO_MEMORY; ++ } ++ fh_memset(cfiep, 0, sizeof(cfi_ep_t)); ++ ++ /* Save the fh_otg_pcd_ep pointer in the cfiep object */ ++ cfiep->ep = ep; ++ ++ /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ ++ ep->fh_ep.descs = ++ FH_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * ++ sizeof(fh_otg_dma_desc_t), ++ &ep->fh_ep.descs_dma_addr); ++ ++ if (NULL == ep->fh_ep.descs) { ++ FH_FREE(cfiep); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ FH_LIST_INIT(&cfiep->lh); ++ ++ /* Set the buffer mode to BM_STANDARD. It will be modified ++ * when building descriptors for a specific buffer mode */ ++ ep->fh_ep.buff_mode = BM_STANDARD; ++ ++ /* Create and initialize the default values for this EP's Buffer modes */ ++ if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0) ++ return retval; ++ ++ /* Add the cfi_ep_t object to the CFI object's list of active endpoints */ ++ FH_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh); ++ retval = 0; ++ } else { /* The sought EP already is in the list */ ++ CFI_INFO("%s: The sought EP already is in the list\n", ++ __func__); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function is called when the data stage of a 3-stage Control Write request ++ * is complete. ++ * ++ */ ++static int cfi_ctrl_write_complete(struct cfiobject *cfi, ++ struct fh_otg_pcd *pcd) ++{ ++ uint32_t addr, reg_value; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ uint8_t *buf = cfi->buf_out.buf; ++ //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved; ++ struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req; ++ int retval = -FH_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ bRequest = ctrl_req->bRequest; ++ wIndex = FH_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = FH_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* ++ * Save the pointer to the data stage in the ctrl_req's <data> field. ++ * The request should be already saved in the command stage by now. ++ */ ++ ctrl_req->data = cfi->buf_out.buf; ++ cfi->need_status_in_complete = 0; ++ cfi->need_gadget_att = 0; ++ ++ switch (bRequest) { ++ case VEN_CORE_WRITE_REGISTER: ++ /* The buffer contains raw data of the new value for the register */ ++ reg_value = *((uint32_t *) buf); ++ if (wValue == 0) { ++ addr = 0; ++ //addr = (uint32_t) pcd->otg_dev->os_dep.base; ++ addr += wIndex; ++ } else { ++ addr = (wValue << 16) | wIndex; ++ } ++ ++ //writel(reg_value, addr); ++ ++ retval = 0; ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ /* The buffer contains raw data of the new value of the feature */ ++ retval = cfi_set_feature_value(pcd); ++ if (retval < 0) ++ return retval; ++ ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function builds the DMA descriptors for the SG buffer mode. ++ */ ++static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ fh_otg_pcd_request_t * req) ++{ ++ struct fh_otg_pcd_ep *ep = cfiep->ep; ++ ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg; ++ struct fh_otg_dma_desc *desc = cfiep->ep->fh_ep.descs; ++ struct fh_otg_dma_desc *desc_last = cfiep->ep->fh_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint32_t txsize, off; ++ ++ txsize = sgval->wSize; ++ off = sgval->bOffset; ++ ++// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", ++// __func__, cfiep->ep->ep.name, txsize, off); ++ ++ for (i = 0; i < sgval->bCount; i++) { ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->buf = buff_addr; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ /* Set the next address of the buffer */ ++ buff_addr += txsize + off; ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->fh_ep.sent_zlp; ++ /* Save the last DMA descriptor pointer */ ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = sgval->bCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Concatenation buffer mode. ++ */ ++static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ fh_otg_pcd_request_t * req) ++{ ++ struct fh_otg_pcd_ep *ep = cfiep->ep; ++ ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat; ++ struct fh_otg_dma_desc *desc = cfiep->ep->fh_ep.descs; ++ struct fh_otg_dma_desc *desc_last = cfiep->ep->fh_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint16_t *txsize; ++ ++ txsize = concatval->wTxBytes; ++ ++ for (i = 0; i < concatval->hdr.bDescCount; i++) { ++ desc->buf = buff_addr; ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = *txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ txsize++; ++ /* Set the next address of the buffer */ ++ buff_addr += UGETW(ep->desc->wMaxPacketSize); ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->fh_ep.sent_zlp; ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = concatval->hdr.bDescCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Circular buffer mode ++ */ ++static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ fh_otg_pcd_request_t * req) ++{ ++ /* @todo: MAS - add implementation when this feature needs to be tested */ ++} ++ ++/** ++ * This function builds the DMA descriptors for the Alignment buffer mode ++ */ ++static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ fh_otg_pcd_request_t * req) ++{ ++ struct fh_otg_pcd_ep *ep = cfiep->ep; ++ ddma_align_buffer_setup_t *alignval = cfiep->bm_align; ++ struct fh_otg_dma_desc *desc = cfiep->ep->fh_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 1; ++ desc->status.b.ioc = 1; ++ desc->status.b.sp = ep->fh_ep.sent_zlp; ++ desc->status.b.bytes = req->length; ++ /* Adjust the buffer alignment */ ++ desc->buf = (buff_addr + alignval->bAlign); ++ desc->status.b.bs = BS_HOST_READY; ++ cfiep->dma_desc_last = desc; ++ cfiep->desc_count = 1; ++} ++ ++/** ++ * This function builds the DMA descriptors chain for different modes of the ++ * buffer setup of an endpoint. ++ */ ++static void cfi_build_descriptors(struct cfiobject *cfi, ++ struct fh_otg_pcd *pcd, ++ struct fh_otg_pcd_ep *ep, ++ fh_otg_pcd_request_t * req) ++{ ++ cfi_ep_t *cfiep; ++ ++ /* Get the cfiep by the fh_otg_pcd_ep */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Unable to find a matching active endpoint\n", ++ __func__); ++ return; ++ } ++ ++ cfiep->xfer_len = req->length; ++ ++ /* Iterate through all the DMA descriptors */ ++ switch (cfiep->ep->fh_ep.buff_mode) { ++ case BM_SG: ++ cfi_build_sg_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CONCAT: ++ cfi_build_concat_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CIRCULAR: ++ cfi_build_circ_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_ALIGN: ++ cfi_build_align_descs(cfi, cfiep, req); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/** ++ * Allocate DMA buffer for different Buffer modes. ++ */ ++static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct fh_otg_pcd *pcd, ++ struct fh_otg_pcd_ep *ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags) ++{ ++ return FH_DMA_ALLOC(size, dma); ++} ++ ++/** ++ * This function initializes the CFI object. ++ */ ++int init_cfi(cfiobject_t * cfiobj) ++{ ++ CFI_INFO("%s\n", __func__); ++ ++ /* Allocate a buffer for IN XFERs */ ++ cfiobj->buf_in.buf = ++ FH_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); ++ if (NULL == cfiobj->buf_in.buf) { ++ CFI_INFO("Unable to allocate buffer for INs\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ /* Allocate a buffer for OUT XFERs */ ++ cfiobj->buf_out.buf = ++ FH_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); ++ if (NULL == cfiobj->buf_out.buf) { ++ CFI_INFO("Unable to allocate buffer for OUT\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ /* Initialize the callback function pointers */ ++ cfiobj->ops.release = cfi_release; ++ cfiobj->ops.ep_enable = cfi_ep_enable; ++ cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete; ++ cfiobj->ops.build_descriptors = cfi_build_descriptors; ++ cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf; ++ ++ /* Initialize the list of active endpoints in the CFI object */ ++ FH_LIST_INIT(&cfiobj->active_eps); ++ ++ return 0; ++} ++ ++/** ++ * This function reads the required feature's current value into the buffer ++ * ++ * @retval: Returns negative as error, or the data length of the feature ++ */ ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int retval = -FH_E_NOT_SUPPORTED; ++ struct fh_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t dfifo, rxfifo, txfifo; ++ ++ switch (ctrl_req->wIndex) { ++ /* Whether the DDMA is enabled or not */ ++ case FT_ID_DMA_MODE: ++ *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0; ++ retval = 1; ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ retval = cfi_ep_get_align_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ dfifo = get_dfifo_size(coreif); ++ *((uint16_t *) buf) = dfifo; ++ retval = sizeof(uint16_t); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = get_txfifo_size(pcd, ctrl_req->wValue); ++ if (retval >= 0) { ++ txfifo = retval; ++ *((uint16_t *) buf) = txfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = get_rxfifo_size(coreif, ctrl_req->wValue); ++ if (retval >= 0) { ++ rxfifo = retval; ++ *((uint16_t *) buf) = rxfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function resets the SG for the specified EP to its default value ++ */ ++static int cfi_reset_sg_val(cfi_ep_t * cfiep) ++{ ++ fh_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Alignment for the specified EP to its default value ++ */ ++static int cfi_reset_align_val(cfi_ep_t * cfiep) ++{ ++ fh_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Concatenation for the specified EP to its default value ++ * This function will also set the value of the wTxBytes field to NULL after ++ * freeing the memory previously allocated for this field. ++ */ ++static int cfi_reset_concat_val(cfi_ep_t * cfiep) ++{ ++ /* First we need to free the wTxBytes field */ ++ if (cfiep->bm_concat->wTxBytes) { ++ FH_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ ++ fh_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets all the buffer setups of the specified endpoint ++ */ ++static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep) ++{ ++ cfi_reset_sg_val(cfiep); ++ cfi_reset_align_val(cfiep); ++ cfi_reset_concat_val(cfiep); ++ return 0; ++} ++ ++static int cfi_handle_reset_fifo_val(struct fh_otg_pcd *pcd, uint8_t ep_addr, ++ uint8_t rx_rst, uint8_t tx_rst) ++{ ++ int retval = -FH_E_INVALID; ++ uint16_t tx_siz[15]; ++ uint16_t rx_siz = 0; ++ fh_otg_pcd_ep_t *ep = NULL; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ ++ if (rx_rst) { ++ rx_siz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ tx_siz[i] = ++ core_if->core_params->dev_tx_fifo_size[i]; ++ core_if->core_params->dev_tx_fifo_size[i] = ++ core_if->init_txfsiz[i]; ++ } ++ } else { ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ if (NULL == ep) { ++ CFI_INFO ++ ("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -FH_E_INVALID; ++ } ++ ++ tx_siz[0] = ++ params->dev_tx_fifo_size[ep->fh_ep.tx_fifo_num - ++ 1]; ++ params->dev_tx_fifo_size[ep->fh_ep.tx_fifo_num - 1] = ++ GET_CORE_IF(pcd)->init_txfsiz[ep-> ++ fh_ep.tx_fifo_num - ++ 1]; ++ } ++ } ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All(FIFO size)\n", ++ __func__); ++ if (rx_rst) { ++ params->dev_rx_fifo_size = rx_siz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++ i++) { ++ core_if-> ++ core_params->dev_tx_fifo_size[i] = ++ tx_siz[i]; ++ } ++ } else { ++ params->dev_tx_fifo_size[ep-> ++ fh_ep.tx_fifo_num - ++ 1] = tx_siz[0]; ++ } ++ } ++ retval = -FH_E_INVALID; ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_all(struct fh_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ fh_list_link_t *tmp; ++ ++ retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1); ++ if (retval < 0) { ++ return retval; ++ } ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->fh_ep.buff_mode = BM_STANDARD; ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->fh_ep.buff_mode = BM_STANDARD; ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_dma_buff_setup(struct fh_otg_pcd *pcd, ++ uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ fh_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ retval = cfi_reset_sg_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_sg_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Buffer Setup\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_concat_val(struct fh_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ fh_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ retval = cfi_reset_concat_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_concat_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Concatenation Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_align_val(struct fh_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ fh_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ retval = cfi_reset_align_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_align_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Aliignment Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++ ++} ++ ++static int cfi_preproc_reset(struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = 0; ++ ++ switch (req->wIndex) { ++ case 0: ++ /* Reset all features */ ++ retval = cfi_handle_reset_all(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Reset the SG buffer setup */ ++ retval = ++ cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Reset the Concatenation buffer setup */ ++ retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ /* Reset the Alignment buffer setup */ ++ retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = ++ cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ default: ++ break; ++ } ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the SG buffer setup. ++ */ ++static int cfi_ep_set_sg_val(uint8_t * buf, struct fh_otg_pcd *pcd) ++{ ++ uint8_t inaddr, outaddr; ++ cfi_ep_t *epin, *epout; ++ ddma_sg_buffer_setup_t *psgval; ++ uint32_t desccount, size; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ psgval = (ddma_sg_buffer_setup_t *) buf; ++ desccount = (uint32_t) psgval->bCount; ++ size = (uint32_t) psgval->wSize; ++ ++ /* Check the DMA descriptor count */ ++ if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) { ++ CFI_INFO ++ ("%s: The count of DMA Descriptors should be between 1 and %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -FH_E_INVALID; ++ } ++ ++ /* Check the DMA descriptor count */ ++ ++ if (size == 0) { ++ ++ CFI_INFO("%s: The transfer size should be at least 1 byte\n", ++ __func__); ++ ++ return -FH_E_INVALID; ++ ++ } ++ ++ inaddr = psgval->bInEndpointAddress; ++ outaddr = psgval->bOutEndpointAddress; ++ ++ epin = get_cfi_ep_by_addr(pcd->cfi, inaddr); ++ epout = get_cfi_ep_by_addr(pcd->cfi, outaddr); ++ ++ if (NULL == epin || NULL == epout) { ++ CFI_INFO ++ ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n", ++ __func__, inaddr, outaddr); ++ return -FH_E_INVALID; ++ } ++ ++ epin->ep->fh_ep.buff_mode = BM_SG; ++ fh_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ epout->ep->fh_ep.buff_mode = BM_SG; ++ fh_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_alignment_val(uint8_t * buf, struct fh_otg_pcd *pcd) ++{ ++ cfi_ep_t *ep; ++ uint8_t addr; ++ ddma_align_buffer_setup_t *palignval; ++ ++ palignval = (ddma_align_buffer_setup_t *) buf; ++ addr = palignval->bEndpointAddress; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ ++ ep->ep->fh_ep.buff_mode = BM_ALIGN; ++ fh_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the Concatenation buffer setup. ++ */ ++static int cfi_ep_set_concat_val(uint8_t * buf, struct fh_otg_pcd *pcd) ++{ ++ uint8_t addr; ++ cfi_ep_t *ep; ++ struct _ddma_concat_buffer_setup_hdr *pConcatValHdr; ++ uint16_t *pVals; ++ uint32_t desccount; ++ int i; ++ uint16_t mps; ++ ++ pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf; ++ desccount = (uint32_t) pConcatValHdr->bDescCount; ++ pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Check the DMA descriptor count */ ++ if (desccount > MAX_DMA_DESCS_PER_EP) { ++ CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -FH_E_INVALID; ++ } ++ ++ addr = pConcatValHdr->bEndpointAddress; ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -FH_E_INVALID; ++ } ++ ++ mps = UGETW(ep->ep->desc->wMaxPacketSize); ++ ++#if 0 ++ for (i = 0; i < desccount; i++) { ++ CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]); ++ } ++ CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps); ++#endif ++ ++ /* Check the wTxSizes to be less than or equal to the mps */ ++ for (i = 0; i < desccount; i++) { ++ if (pVals[i] > mps) { ++ CFI_INFO ++ ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n", ++ __func__, i, pVals[i]); ++ return -FH_E_INVALID; ++ } ++ } ++ ++ ep->ep->fh_ep.buff_mode = BM_CONCAT; ++ fh_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Free the previously allocated storage for the wTxBytes */ ++ if (ep->bm_concat->wTxBytes) { ++ FH_FREE(ep->bm_concat->wTxBytes); ++ } ++ ++ /* Allocate a new storage for the wTxBytes field */ ++ ep->bm_concat->wTxBytes = ++ FH_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ if (NULL == ep->bm_concat->wTxBytes) { ++ CFI_INFO("%s: Unable to allocate memory\n", __func__); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ /* Copy the new values into the wTxBytes filed */ ++ fh_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN, ++ sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ ++ return 0; ++} ++ ++/** ++ * This function calculates the total of all FIFO sizes ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static uint16_t get_dfifo_size(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_params_t *params = core_if->core_params; ++ uint16_t dfifo_total = 0; ++ int i; ++ ++ /* The shared RxFIFO size */ ++ dfifo_total = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ /* Add up each TxFIFO size to the total */ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_total += params->dev_tx_fifo_size[i]; ++ } ++ ++ return dfifo_total; ++} ++ ++/** ++ * This function returns Rx FIFO size ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_rxfifo_size(fh_otg_core_if_t * core_if, uint16_t wValue) ++{ ++ switch (wValue >> 8) { ++ case 0: ++ return (core_if->pwron_rxfsiz < ++ 32768) ? core_if->pwron_rxfsiz : 32768; ++ break; ++ case 1: ++ return core_if->core_params->dev_rx_fifo_size; ++ break; ++ default: ++ return -FH_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function returns Tx FIFO size for IN EP ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_txfifo_size(struct fh_otg_pcd *pcd, uint16_t wValue) ++{ ++ fh_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_by_addr(pcd, wValue & 0xff); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -FH_E_INVALID; ++ } ++ ++ if (!ep->fh_ep.is_in) { ++ CFI_INFO ++ ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -FH_E_INVALID; ++ } ++ ++ switch (wValue >> 8) { ++ case 0: ++ return (GET_CORE_IF(pcd)->pwron_txfsiz ++ [ep->fh_ep.tx_fifo_num - 1] < ++ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> ++ fh_ep.tx_fifo_num ++ - 1] : 32768; ++ break; ++ case 1: ++ return GET_CORE_IF(pcd)->core_params-> ++ dev_tx_fifo_size[ep->fh_ep.num - 1]; ++ break; ++ default: ++ return -FH_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function checks if the submitted combination of ++ * device mode FIFO sizes is possible or not. ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ * @return 1 if possible, 0 otherwise. ++ * ++ */ ++static uint8_t check_fifo_sizes(fh_otg_core_if_t * core_if) ++{ ++ uint16_t dfifo_actual = 0; ++ fh_otg_core_params_t *params = core_if->core_params; ++ uint16_t start_addr = 0; ++ int i; ++ ++ dfifo_actual = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_actual += params->dev_tx_fifo_size[i]; ++ } ++ ++ if (dfifo_actual > core_if->total_fifo_size) { ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16) ++ return 0; ++ ++ if (params->dev_nperio_tx_fifo_size > 32768 ++ || params->dev_nperio_tx_fifo_size < 16) ++ return 0; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > 768 ++ || params->dev_tx_fifo_size[i] < 4) ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz) ++ return 0; ++ start_addr = params->dev_rx_fifo_size; ++ ++ if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz) ++ return 0; ++ start_addr += params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i]) ++ return 0; ++ start_addr += params->dev_tx_fifo_size[i]; ++ } ++ ++ return 1; ++} ++ ++/** ++ * This function resizes Device mode FIFOs ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ * @return 1 if successful, 0 otherwise ++ * ++ */ ++static uint8_t resize_fifos(fh_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ fh_otg_core_params_t *params = core_if->core_params; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize[15]; ++ ++ uint32_t rx_fsz_bak; ++ uint32_t nptxfsz_bak; ++ uint32_t txfsz_bak[15]; ++ ++ uint16_t start_address; ++ uint8_t retval = 1; ++ ++ if (!check_fifo_sizes(core_if)) { ++ return 0; ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ rx_fsz_bak = FH_READ_REG32(&global_regs->grxfsiz); ++ rx_fifo_size = params->dev_rx_fifo_size; ++ FH_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ nptxfsz_bak = FH_READ_REG32(&global_regs->gnptxfsiz); ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ start_address = params->dev_rx_fifo_size; ++ nptxfifosize.b.startaddr = start_address; ++ ++ FH_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ ++ start_address += nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ txfsz_bak[i] = FH_READ_REG32(&global_regs->dtxfsiz[i]); ++ ++ txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; ++ txfifosize[i].b.startaddr = start_address; ++ FH_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize[i].d32); ++ ++ start_address += txfifosize[i].b.depth; ++ } ++ ++ /** Check if register values are set correctly */ ++ if (rx_fifo_size != FH_READ_REG32(&global_regs->grxfsiz)) { ++ retval = 0; ++ } ++ ++ if (nptxfifosize.d32 != FH_READ_REG32(&global_regs->gnptxfsiz)) { ++ retval = 0; ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ if (txfifosize[i].d32 != ++ FH_READ_REG32(&global_regs->dtxfsiz[i])) { ++ retval = 0; ++ } ++ } ++ ++ /** If register values are not set correctly, reset old values */ ++ if (retval == 0) { ++ FH_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); ++ ++ /* Non-periodic Tx FIFO */ ++ FH_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ FH_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfsz_bak[i]); ++ } ++ } ++ } else { ++ return 0; ++ } ++ ++ /* Flush the FIFOs */ ++ fh_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ fh_otg_flush_rx_fifo(core_if); ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_tx_fifo_val(uint8_t * buf, fh_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ uint16_t ep_addr; ++ fh_otg_pcd_ep_t *ep; ++ fh_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ tx_fifo_size_setup_t *ptxfifoval; ++ ++ ptxfifoval = (tx_fifo_size_setup_t *) buf; ++ ep_addr = ptxfifoval->bEndpointAddress; ++ size = ptxfifoval->wDepth; ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ CFI_INFO ++ ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n", ++ __func__, ep_addr, size, ep->fh_ep.tx_fifo_num); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -FH_E_INVALID; ++ } ++ ++ fsiz = params->dev_tx_fifo_size[ep->fh_ep.tx_fifo_num - 1]; ++ params->dev_tx_fifo_size[ep->fh_ep.tx_fifo_num - 1] = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error setting the feature Tx FIFO Size for EP%d\n", ++ __func__, ep_addr); ++ params->dev_tx_fifo_size[ep->fh_ep.tx_fifo_num - 1] = fsiz; ++ retval = -FH_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_set_rx_fifo_val(uint8_t * buf, fh_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ fh_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ rx_fifo_size_setup_t *prxfifoval; ++ ++ prxfifoval = (rx_fifo_size_setup_t *) buf; ++ size = prxfifoval->wDepth; ++ ++ fsiz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO("%s: Error setting the feature Rx FIFO Size\n", ++ __func__); ++ params->dev_rx_fifo_size = fsiz; ++ retval = -FH_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function reads the SG of an EP's buffer setup into the buffer buf ++ */ ++static int cfi_ep_get_sg_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -FH_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ fh_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN); ++ retval = BS_SG_VAL_DESC_LEN; ++ return retval; ++} ++ ++/** ++ * This function reads the Concatenation value of an EP's buffer mode into ++ * the buffer buf ++ */ ++static int cfi_ep_get_concat_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -FH_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ uint8_t desc_count; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ /* Copy the header to the buffer */ ++ fh_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN); ++ /* Advance the buffer pointer by the header size */ ++ buf += BS_CONCAT_VAL_HDR_LEN; ++ ++ desc_count = ep->bm_concat->hdr.bDescCount; ++ /* Copy alll the wTxBytes to the buffer */ ++ fh_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count); ++ ++ retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count; ++ return retval; ++} ++ ++/** ++ * This function reads the buffer Alignment value of an EP's buffer mode into ++ * the buffer buf ++ * ++ * @return The total number of bytes copied to the buffer or negative error code. ++ */ ++static int cfi_ep_get_align_val(uint8_t * buf, struct fh_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -FH_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ fh_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN); ++ retval = BS_ALIGN_VAL_HDR_LEN; ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the specified feature ++ * ++ * @param pcd A pointer to the PCD object ++ * ++ * @return 0 if successful, negative error code otherwise to stall the DCE. ++ */ ++static int cfi_set_feature_value(struct fh_otg_pcd *pcd) ++{ ++ int retval = -FH_E_NOT_SUPPORTED; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ struct fh_otg_core_if *coreif; ++ cfiobject_t *cfi = pcd->cfi; ++ struct cfi_usb_ctrlrequest *ctrl_req; ++ uint8_t *buf; ++ ctrl_req = &cfi->ctrl_req; ++ ++ buf = pcd->cfi->ctrl_req.data; ++ ++ coreif = GET_CORE_IF(pcd); ++ bRequest = ctrl_req->bRequest; ++ wIndex = FH_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = FH_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* See which feature is to be modified */ ++ switch (wIndex) { ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0) ++ return retval; ++ ++ /* And send this request to the gadget */ ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("FT_ID_DMA_CIRCULAR\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("FT_ID_THRESHOLD_SETUP\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ CFI_INFO("FT_ID_DFIFO_DEPTH\n"); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_TX_FIFO_DEPTH\n"); ++ if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_RX_FIFO_DEPTH\n"); ++ if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif //FH_UTE_CFI +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.h +new file mode 100644 +index 00000000..97a05fa5 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cfi.h +@@ -0,0 +1,320 @@ ++/* ========================================================================== ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__FH_OTG_CFI_H__) ++#define __FH_OTG_CFI_H__ ++ ++#include "fh_otg_pcd.h" ++#include "fh_cfi_common.h" ++ ++/** ++ * @file ++ * This file contains the CFI related OTG PCD specific common constants, ++ * interfaces(functions and macros) and data structures.The CFI Protocol is an ++ * optional interface for internal testing purposes that a DUT may implement to ++ * support testing of configurable features. ++ * ++ */ ++ ++struct fh_otg_pcd; ++struct fh_otg_pcd_ep; ++ ++/** OTG CFI Features (properties) ID constants */ ++/** This is a request for all Core Features */ ++#define FT_ID_DMA_MODE 0x0001 ++#define FT_ID_DMA_BUFFER_SETUP 0x0002 ++#define FT_ID_DMA_BUFF_ALIGN 0x0003 ++#define FT_ID_DMA_CONCAT_SETUP 0x0004 ++#define FT_ID_DMA_CIRCULAR 0x0005 ++#define FT_ID_THRESHOLD_SETUP 0x0006 ++#define FT_ID_DFIFO_DEPTH 0x0007 ++#define FT_ID_TX_FIFO_DEPTH 0x0008 ++#define FT_ID_RX_FIFO_DEPTH 0x0009 ++ ++/**********************************************************/ ++#define CFI_INFO_DEF ++ ++#ifdef CFI_INFO_DEF ++#define CFI_INFO(fmt...) FH_PRINTF("CFI: " fmt); ++#else ++#define CFI_INFO(fmt...) ++#endif ++ ++#define min(x,y) ({ \ ++ x < y ? x : y; }) ++ ++#define max(x,y) ({ \ ++ x > y ? x : y; }) ++ ++/** ++ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is ++ * also used for setting up a buffer for Circular DDMA. ++ */ ++struct _ddma_sg_buffer_setup { ++#define BS_SG_VAL_DESC_LEN 6 ++ /* The OUT EP address */ ++ uint8_t bOutEndpointAddress; ++ /* The IN EP address */ ++ uint8_t bInEndpointAddress; ++ /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ ++ uint8_t bOffset; ++ /* The number of transfer segments (a DMA descriptors per each segment) */ ++ uint8_t bCount; ++ /* Size (in byte) of each transfer segment */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup_hdr { ++#define BS_CONCAT_VAL_HDR_LEN 4 ++ /* The endpoint for which the buffer is to be set up */ ++ uint8_t bEndpointAddress; ++ /* The count of descriptors to be used */ ++ uint8_t bDescCount; ++ /* The total size of the transfer */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup { ++ /* The SG header */ ++ ddma_concat_buffer_setup_hdr_t hdr; ++ ++ /* The XFER sizes pointer (allocated dynamically) */ ++ uint16_t *wTxBytes; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; ++ ++/** Descriptor DMA Alignment Buffer setup structure */ ++struct _ddma_align_buffer_setup { ++#define BS_ALIGN_VAL_HDR_LEN 2 ++ uint8_t bEndpointAddress; ++ uint8_t bAlign; ++} __attribute__ ((packed)); ++typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _tx_fifo_size_setup { ++ uint8_t bEndpointAddress; ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _rx_fifo_size_setup { ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; ++ ++/** ++ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest ++ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer ++ * to the data returned in the data stage of a 3-stage Control Write requests. ++ */ ++struct cfi_usb_ctrlrequest { ++ uint8_t bRequestType; ++ uint8_t bRequest; ++ uint16_t wValue; ++ uint16_t wIndex; ++ uint16_t wLength; ++ uint8_t *data; ++} UPACKED; ++ ++/*---------------------------------------------------------------------------*/ ++ ++/** ++ * The CFI wrapper of the enabled and activated fh_otg_pcd_ep structures. ++ * This structure is used to store the buffer setup data for any ++ * enabled endpoint in the PCD. ++ */ ++struct cfi_ep { ++ /* Entry for the list container */ ++ fh_list_link_t lh; ++ /* Pointer to the active PCD endpoint structure */ ++ struct fh_otg_pcd_ep *ep; ++ /* The last descriptor in the chain of DMA descriptors of the endpoint */ ++ struct fh_otg_dma_desc *dma_desc_last; ++ /* The SG feature value */ ++ ddma_sg_buffer_setup_t *bm_sg; ++ /* The Circular feature value */ ++ ddma_sg_buffer_setup_t *bm_circ; ++ /* The Concatenation feature value */ ++ ddma_concat_buffer_setup_t *bm_concat; ++ /* The Alignment feature value */ ++ ddma_align_buffer_setup_t *bm_align; ++ /* XFER length */ ++ uint32_t xfer_len; ++ /* ++ * Count of DMA descriptors currently used. ++ * The total should not exceed the MAX_DMA_DESCS_PER_EP value ++ * defined in the fh_otg_cil.h ++ */ ++ uint32_t desc_count; ++}; ++typedef struct cfi_ep cfi_ep_t; ++ ++typedef struct cfi_dma_buff { ++#define CFI_IN_BUF_LEN 1024 ++#define CFI_OUT_BUF_LEN 1024 ++ dma_addr_t addr; ++ uint8_t *buf; ++} cfi_dma_buff_t; ++ ++struct cfiobject; ++ ++/** ++ * This is the interface for the CFI operations. ++ * ++ * @param ep_enable Called when any endpoint is enabled and activated. ++ * @param release Called when the CFI object is released and it needs to correctly ++ * deallocate the dynamic memory ++ * @param ctrl_write_complete Called when the data stage of the request is complete ++ */ ++typedef struct cfi_ops { ++ int (*ep_enable) (struct cfiobject * cfi, struct fh_otg_pcd * pcd, ++ struct fh_otg_pcd_ep * ep); ++ void *(*ep_alloc_buf) (struct cfiobject * cfi, struct fh_otg_pcd * pcd, ++ struct fh_otg_pcd_ep * ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags); ++ void (*release) (struct cfiobject * cfi); ++ int (*ctrl_write_complete) (struct cfiobject * cfi, ++ struct fh_otg_pcd * pcd); ++ void (*build_descriptors) (struct cfiobject * cfi, ++ struct fh_otg_pcd * pcd, ++ struct fh_otg_pcd_ep * ep, ++ fh_otg_pcd_request_t * req); ++} cfi_ops_t; ++ ++struct cfiobject { ++ cfi_ops_t ops; ++ struct fh_otg_pcd *pcd; ++ struct usb_gadget *gadget; ++ ++ /* Buffers used to send/receive CFI-related request data */ ++ cfi_dma_buff_t buf_in; ++ cfi_dma_buff_t buf_out; ++ ++ /* CFI specific Control request wrapper */ ++ struct cfi_usb_ctrlrequest ctrl_req; ++ ++ /* The list of active EP's in the PCD of type cfi_ep_t */ ++ fh_list_link_t active_eps; ++ ++ /* This flag shall control the propagation of a specific request ++ * to the gadget's processing routines. ++ * 0 - no gadget handling ++ * 1 - the gadget needs to know about this request (w/o completing a status ++ * phase - just return a 0 to the _setup callback) ++ */ ++ uint8_t need_gadget_att; ++ ++ /* Flag indicating whether the status IN phase needs to be ++ * completed by the PCD ++ */ ++ uint8_t need_status_in_complete; ++}; ++typedef struct cfiobject cfiobject_t; ++ ++#define DUMP_MSG ++ ++#if defined(DUMP_MSG) ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ ++ start = 0; ++ while (length > 0) { ++ num = min(length, 16u); ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ FH_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ FH_DEBUG("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function returns a pointer to cfi_ep_t object with the addr address. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, ++ uint8_t addr) ++{ ++ struct cfi_ep *pcfiep; ++ fh_list_link_t *tmp; ++ ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ ++ if (pcfiep->ep->desc->bEndpointAddress == addr) { ++ return pcfiep; ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function returns a pointer to cfi_ep_t object that matches ++ * the fh_otg_pcd_ep object. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, ++ struct fh_otg_pcd_ep *ep) ++{ ++ struct cfi_ep *pcfiep = NULL; ++ fh_list_link_t *tmp; ++ ++ FH_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = FH_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ if (pcfiep->ep == ep) { ++ return pcfiep; ++ } ++ } ++ return NULL; ++} ++ ++int cfi_setup(struct fh_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); ++ ++#endif /* (__FH_OTG_CFI_H__) */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.c +new file mode 100644 +index 00000000..04ba1ad2 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.c +@@ -0,0 +1,7595 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_cil.c $ ++ * $Revision: #216 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the FH_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * The CIL manages the memory map for the core so that the HCD and PCD ++ * don't have to do this separately. It also handles basic tasks like ++ * reading/writing the registers and data FIFOs in the controller. ++ * Some of the data access functions provide encapsulation of several ++ * operations required to perform a task, such as writing multiple ++ * registers to start a transfer. Finally, the CIL performs basic ++ * services that are not specific to either the host or device modes ++ * of operation. These services include management of the OTG Host ++ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A ++ * Diagnostic API is also provided to allow testing of the controller ++ * hardware. ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <mach/gpio.h> ++#include <mach/board_config.h> ++#include <mach/pmu.h> ++#include "../fh_common_port/fh_os.h" ++#include "fh_otg_regs.h" ++#include "fh_otg_cil.h" ++ ++static int fh_otg_setup_params(fh_otg_core_if_t * core_if); ++ ++/** ++ * This function is called to initialize the FH_otg CSR data ++ * structures. The register addresses in the device and host ++ * structures are initialized from the base address supplied by the ++ * caller. The calling function must make the OS calls to get the ++ * base address of the FH_otg controller registers. The core_params ++ * argument holds the parameters that specify how the core should be ++ * configured. ++ * ++ * @param reg_base_addr Base address of FH_otg core registers ++ * ++ */ ++fh_otg_core_if_t *fh_otg_cil_init(const uint32_t * reg_base_addr, ++ struct fh_usb_platform_data *fh_usb_data) ++{ ++ fh_otg_core_if_t *core_if = 0; ++ fh_otg_dev_if_t *dev_if = 0; ++ fh_otg_host_if_t *host_if = 0; ++ uint8_t *reg_base = (uint8_t *) reg_base_addr; ++ int i = 0; ++ ++ FH_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); ++ ++ core_if = FH_ALLOC(sizeof(fh_otg_core_if_t)); ++ ++ if (core_if == NULL) { ++ FH_DEBUGPL(DBG_CIL, ++ "Allocation of fh_otg_core_if_t failed\n"); ++ return 0; ++ } ++ core_if->core_global_regs = (fh_otg_core_global_regs_t *) reg_base; ++ ++ /* ++ * Allocate the Device Mode structures. ++ */ ++ dev_if = FH_ALLOC(sizeof(fh_otg_dev_if_t)); ++ ++ if (dev_if == NULL) { ++ FH_DEBUGPL(DBG_CIL, "Allocation of fh_otg_dev_if_t failed\n"); ++ FH_FREE(core_if); ++ return 0; ++ } ++ ++ dev_if->dev_global_regs = ++ (fh_otg_device_global_regs_t *) (reg_base + ++ FH_DEV_GLOBAL_REG_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dev_if->in_ep_regs[i] = (fh_otg_dev_in_ep_regs_t *) ++ (reg_base + FH_DEV_IN_EP_REG_OFFSET + ++ (i * FH_EP_REG_OFFSET)); ++ ++ dev_if->out_ep_regs[i] = (fh_otg_dev_out_ep_regs_t *) ++ (reg_base + FH_DEV_OUT_EP_REG_OFFSET + ++ (i * FH_EP_REG_OFFSET)); ++ FH_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", ++ i, &dev_if->in_ep_regs[i]->diepctl); ++ FH_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", ++ i, &dev_if->out_ep_regs[i]->doepctl); ++ } ++ ++ dev_if->speed = 0; // unknown ++ ++ core_if->dev_if = dev_if; ++ ++ /* ++ * Allocate the Host Mode structures. ++ */ ++ host_if = FH_ALLOC(sizeof(fh_otg_host_if_t)); ++ ++ if (host_if == NULL) { ++ FH_DEBUGPL(DBG_CIL, ++ "Allocation of fh_otg_host_if_t failed\n"); ++ FH_FREE(dev_if); ++ FH_FREE(core_if); ++ return 0; ++ } ++ ++ host_if->host_global_regs = (fh_otg_host_global_regs_t *) ++ (reg_base + FH_OTG_HOST_GLOBAL_REG_OFFSET); ++ ++ host_if->hprt0 = ++ (uint32_t *) (reg_base + FH_OTG_HOST_PORT_REGS_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ host_if->hc_regs[i] = (fh_otg_hc_regs_t *) ++ (reg_base + FH_OTG_HOST_CHAN_REGS_OFFSET + ++ (i * FH_OTG_CHAN_REGS_OFFSET)); ++ FH_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n", ++ i, &host_if->hc_regs[i]->hcchar); ++ } ++ ++ host_if->num_host_channels = MAX_EPS_CHANNELS; ++ core_if->host_if = host_if; ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ core_if->data_fifo[i] = ++ (uint32_t *) (reg_base + FH_OTG_DATA_FIFO_OFFSET + ++ (i * FH_OTG_DATA_FIFO_SIZE)); ++ FH_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", ++ i, (unsigned long)core_if->data_fifo[i]); ++ } ++ ++ core_if->pcgcctl = (uint32_t *) (reg_base + FH_OTG_PCGCCTL_OFFSET); ++ ++ /* Initiate lx_state to L3 disconnected state */ ++ core_if->lx_state = FH_OTG_L3; ++ /* ++ * Store the contents of the hardware configuration registers here for ++ * easy access later. ++ */ ++ core_if->hwcfg1.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->ghwcfg1); ++ core_if->hwcfg2.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ core_if->hwcfg3.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->ghwcfg3); ++ core_if->hwcfg4.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ /* Force host mode to get HPTXFSIZ exact power on value */ ++ { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ gusbcfg.d32); ++ fh_mdelay(100); ++ ++ /*get host period tx fifo size*/ ++ core_if->hptxfsiz.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++ /*restore host rx fifo size*/ ++ FH_WRITE_REG32(&core_if->core_global_regs->grxfsiz, ++ fh_usb_data->grxfsiz_pwron_val); ++ /*restore host none period tx fifo size*/ ++ FH_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ fh_usb_data->gnptxfsiz_pwron_val); ++ ++#ifndef FH_HOST_ONLY ++ gusbcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 0; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ gusbcfg.d32); ++ fh_mdelay(100); ++ ++ /*restore device rx fifo size*/ ++ FH_WRITE_REG32(&core_if->core_global_regs->grxfsiz, ++ fh_usb_data->grxfsiz_pwron_val); ++ /*restore device none period tx fifo size*/ ++ FH_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ fh_usb_data->gnptxfsiz_pwron_val); ++#endif ++ } ++ ++ FH_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); ++ FH_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); ++ FH_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); ++ FH_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); ++ ++ core_if->hcfg.d32 = ++ FH_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ core_if->dcfg.d32 = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ ++ FH_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); ++ FH_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); ++ ++ FH_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); ++ FH_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); ++ FH_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); ++ FH_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", ++ core_if->hwcfg2.b.num_host_chan); ++ FH_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.nonperio_tx_q_depth); ++ FH_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.host_perio_tx_q_depth); ++ FH_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.dev_token_q_depth); ++ ++ FH_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", ++ core_if->hwcfg3.b.dfifo_depth); ++ FH_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", ++ core_if->hwcfg3.b.xfer_size_cntr_width); ++ ++ /* ++ * Set the SRP sucess bit for FS-I2c ++ */ ++ core_if->srp_success = 0; ++ core_if->srp_timer_started = 0; ++ ++ /* ++ * Create new workqueue and init works ++ */ ++ core_if->wq_otg = FH_WORKQ_ALLOC("fh_otg"); ++ if (core_if->wq_otg == 0) { ++ FH_WARN("FH_WORKQ_ALLOC failed\n"); ++ FH_FREE(host_if); ++ FH_FREE(dev_if); ++ FH_FREE(core_if); ++ return 0; ++ } ++ ++ /* ++ * Allocates hibernation backup registers ++ */ ++ if (core_if->hwcfg4.b.hiber==1 || core_if->hwcfg4.b.xhiber==1) { ++ if(!core_if->gr_backup){ ++ core_if->gr_backup = FH_ALLOC(sizeof(*core_if->gr_backup)); ++ if(!core_if->gr_backup){ ++ FH_WARN("can't alloc mem for gr_backup register \n"); ++ FH_FREE(host_if); ++ FH_FREE(dev_if); ++ FH_WORKQ_FREE(core_if->wq_otg); ++ FH_FREE(core_if); ++ return 0; ++ } ++ } ++ if(!core_if->dr_backup){ ++ core_if->dr_backup = FH_ALLOC(sizeof(*core_if->dr_backup)); ++ if(!core_if->dr_backup){ ++ FH_WARN("can't alloc mem for dr_backup register \n"); ++ FH_FREE(host_if); ++ FH_FREE(dev_if); ++ FH_WORKQ_FREE(core_if->wq_otg); ++ FH_FREE(core_if); ++ FH_FREE(core_if->gr_backup); ++ return 0; ++ } ++ } ++ if(!core_if->hr_backup){ ++ core_if->hr_backup = FH_ALLOC(sizeof(*core_if->hr_backup)); ++ if(!core_if->hr_backup){ ++ FH_WARN("can't alloc mem for hr_backup register \n"); ++ FH_FREE(host_if); ++ FH_FREE(dev_if); ++ FH_WORKQ_FREE(core_if->wq_otg); ++ FH_FREE(core_if); ++ FH_FREE(core_if->gr_backup); ++ FH_FREE(core_if->dr_backup); ++ return 0; ++ } ++ } ++ } ++ ++ core_if->snpsid = FH_READ_REG32(&core_if->core_global_regs->gsnpsid); ++ ++ FH_PRINTF("Core Release: %x.%x%x%x\n", ++ (core_if->snpsid >> 12 & 0xF), ++ (core_if->snpsid >> 8 & 0xF), ++ (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF)); ++ ++ core_if->wkp_timer = FH_TIMER_ALLOC("Wake Up Timer", ++ w_wakeup_detected, core_if); ++ if (core_if->wkp_timer == 0) { ++ FH_WARN("FH_TIMER_ALLOC failed\n"); ++ FH_FREE(host_if); ++ FH_FREE(dev_if); ++ FH_WORKQ_FREE(core_if->wq_otg); ++ FH_FREE(core_if); ++ return 0; ++ } ++ ++ if (fh_otg_setup_params(core_if)) ++ FH_WARN("Error while setting core params\n"); ++ ++ core_if->hibernation_suspend = 0; ++ if (core_if->otg_ver) ++ core_if->test_mode = 0; ++ ++ /** ADP initialization */ ++ fh_otg_adp_init(core_if); ++ ++ return core_if; ++} ++ ++/** ++ * This function frees the structures allocated by fh_otg_cil_init(). ++ * ++ * @param core_if The core interface pointer returned from ++ * fh_otg_cil_init(). ++ * ++ */ ++void fh_otg_cil_remove(fh_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl = {.d32 = 0 }; ++ /* Disable all interrupts */ ++ FH_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ dctl.b.sftdiscon = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, ++ dctl.d32); ++ } ++ ++ if (core_if->wq_otg) { ++ FH_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); ++ FH_WORKQ_FREE(core_if->wq_otg); ++ } ++ if (core_if->dev_if) { ++ FH_FREE(core_if->dev_if); ++ } ++ if (core_if->host_if) { ++ FH_FREE(core_if->host_if); ++ } ++ ++ /** Remove hibernation recovery registers **/ ++ if(core_if->gr_backup){ ++ FH_FREE(core_if->gr_backup); ++ } ++ if(core_if->dr_backup){ ++ FH_FREE(core_if->dr_backup); ++ } ++ if(core_if->hr_backup){ ++ FH_FREE(core_if->hr_backup); ++ } ++ ++ /** Remove ADP Stuff */ ++ fh_otg_adp_remove(core_if); ++ if (core_if->core_params) { ++ FH_FREE(core_if->core_params); ++ } ++ if (core_if->wkp_timer) { ++ FH_TIMER_FREE(core_if->wkp_timer); ++ } ++ if (core_if->srp_timer) { ++ FH_TIMER_FREE(core_if->srp_timer); ++ } ++ FH_FREE(core_if); ++} ++ ++/** ++ * This function enables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_enable_global_interrupts(fh_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ FH_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++} ++ ++/** ++ * This function disables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_disable_global_interrupts(fh_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ ++ FH_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++} ++ ++/** ++ * This function initializes the commmon interrupts, used in both ++ * device and host modes. ++ * ++ * @param core_if Programming view of the FH_otg controller ++ * ++ */ ++static void fh_otg_enable_common_interrupts(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ /* Clear any pending OTG Interrupts */ ++ FH_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); ++ ++ /* Clear any pending interrupts */ ++ FH_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* ++ * Enable the interrupts in the GINTMSK. ++ */ ++ if (!core_if->core_params->otg_ver) ++ /* To avoid system hang during OTG 2.0 role switch */ ++ intr_mask.b.modemismatch = 1; ++ intr_mask.b.otgintr = 1; ++ ++ if (!core_if->dma_enable) { ++ intr_mask.b.rxstsqlvl = 1; ++ } ++ ++ intr_mask.b.conidstschng = 1; ++ intr_mask.b.wkupintr = 1; ++ intr_mask.b.disconnect = 0; ++ intr_mask.b.usbsuspend = 1; ++ intr_mask.b.sessreqintr = 1; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ intr_mask.b.lpmtranrcvd = 1; ++ } ++#endif ++ FH_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Device mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of FH_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int fh_otg_device_hibernation_restore(fh_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (rem_wakeup) { ++ fh_udelay(70); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Mask interrupts from gpwrdn */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* ++ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 ++ * indicates restore from remote_wakeup ++ */ ++ restore_essential_regs(core_if, rem_wakeup, 0); ++ ++ /* ++ * Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling ++ */ ++ fh_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* ++ * Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ FH_PRINTF("Restore Done Interrupt seen\n"); ++ break; ++ } ++ fh_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ FH_PRINTF("Restore Done interrupt wasn't generated here\n"); ++ } ++ } ++ /* Clear all pending interupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ if (!rem_wakeup) { ++ pcgcctl.d32 = 0; ++ pcgcctl.b.rstpdwnmodule = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ ++ /* Restore GUSBCFG,DCFG and DCTL */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ core_if->dr_backup->dctl); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ if (!rem_wakeup) { ++ /* Set Device programming done bit */ ++ dctl.b.pwronprgdone = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ /* Start Remote Wakeup Signaling */ ++ dctl.d32 = core_if->dr_backup->dctl; ++ dctl.b.rmtwkupsig = 1; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ ++ fh_mdelay(2); ++ /* Clear all pending interupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ fh_otg_restore_global_regs(core_if); ++ /* Restore device global registers */ ++ fh_otg_restore_dev_regs(core_if, rem_wakeup); ++ ++ if (rem_wakeup) { ++ fh_mdelay(7); ++ dctl.d32 = 0; ++ dctl.b.rmtwkupsig = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ /* The core will be in ON STATE */ ++ core_if->lx_state = FH_OTG_L0; ++ FH_PRINTF("Hibernation recovery completes here\n"); ++ ++ return 1; ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Host mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of FH_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int fh_otg_host_hibernation_restore(fh_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ FH_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (!rem_wakeup) { ++ fh_udelay(50); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Set Restore Essential Regs bit in PCGCCTL register */ ++ restore_essential_regs(core_if, rem_wakeup, 1); ++ ++ /* Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling */ ++ fh_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ FH_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); ++ break; ++ } ++ fh_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ FH_WARN("Restore Done interrupt wasn't generated\n"); ++ } ++ } ++ ++ /* Set the flag's value to 0 again after receiving restore done interrupt */ ++ core_if->hibernation_suspend = 0; ++ ++ /* This step is not described in functional spec but if not wait for this ++ * delay, mismatch interrupts occurred because just after restore core is ++ * in Device mode(gintsts.curmode == 0) */ ++ fh_mdelay(100); ++ ++ /* Clear all pending interrupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Restore GUSBCFG and HCFG */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ core_if->hr_backup->hcfg_local); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Start the Resume operation by programming HPRT0 */ ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ FH_PRINTF("Resume Starts Now\n"); ++ if (!reset) { // Indicates it is Resume Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtres = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ if (!rem_wakeup) ++ hprt0.b.prtres = 0; ++ /* Wait for Resume time and then program HPRT again */ ++ fh_mdelay(100); ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ } else { // Indicates it is Reset Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtrst = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Wait for Reset time and then program HPRT again */ ++ fh_mdelay(60); ++ hprt0.b.prtrst = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ /* Clear all interrupt status */ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtconndet = 1; ++ hprt0.b.prtenchng = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Clear all pending interupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ ++ /* Restore global registers */ ++ fh_otg_restore_global_regs(core_if); ++ /* Restore host global registers */ ++ fh_otg_restore_host_regs(core_if, reset); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = FH_OTG_L0; ++ FH_PRINTF("Hibernation recovery is complete here\n"); ++ return 0; ++} ++ ++/** Saves some register values into system memory. */ ++int fh_otg_save_global_regs(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ FH_WARN("gr_backup is not allocated!\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ gr->gotgctl_local = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ gr->gintmsk_local = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gr->gahbcfg_local = FH_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ gr->gusbcfg_local = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gr->grxfsiz_local = FH_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ gr->gnptxfsiz_local = FH_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++ gr->hptxfsiz_local = FH_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ gr->glpmcfg_local = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++#endif ++ gr->gi2cctl_local = FH_READ_REG32(&core_if->core_global_regs->gi2cctl); ++ gr->pcgcctl_local = FH_READ_REG32(core_if->pcgcctl); ++ gr->gdfifocfg_local = ++ FH_READ_REG32(&core_if->core_global_regs->gdfifocfg); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ gr->dtxfsiz_local[i] = ++ FH_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); ++ } ++ ++ FH_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); ++ FH_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", ++ gr->gnptxfsiz_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", ++ gr->hptxfsiz_local); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ FH_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); ++#endif ++ FH_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); ++ FH_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); ++ ++ return 0; ++} ++ ++/** Saves GINTMSK register before setting the msk bits. */ ++int fh_otg_save_gintmsk_reg(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ FH_WARN("gr_backup is not allocated!\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ gr->gintmsk_local = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ FH_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); ++ FH_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ ++ return 0; ++} ++ ++int fh_otg_save_dev_regs(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ if (!dr) { ++ FH_WARN("dr_backup is not allocated!\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ dr->dcfg = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dr->dctl = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dr->daintmsk = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ dr->diepmsk = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); ++ dr->doepmsk = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ dr->diepctl[i] = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ dr->dieptsiz[i] = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); ++ dr->diepdma[i] = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; ++i) { ++ dr->doepctl[i] = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl); ++ dr->doeptsiz[i] = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[i]->doeptsiz); ++ dr->doepdma[i] = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[i]->doepdma); ++ } ++ ++ ++ ++ FH_DEBUGPL(DBG_ANY, ++ "=============Backing Device registers==============\n"); ++ FH_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); ++ FH_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); ++ FH_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", ++ dr->daintmsk); ++ FH_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); ++ FH_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ FH_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, ++ dr->diepctl[i]); ++ FH_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", ++ i, dr->dieptsiz[i]); ++ FH_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, ++ dr->diepdma[i]); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; ++i) { ++ FH_DEBUGPL(DBG_ANY, "Backed up doepctl[%d] = %08x\n", i, ++ dr->doepctl[i]); ++ FH_DEBUGPL(DBG_ANY, "Backed up doeptsiz[%d] = %08x\n", ++ i, dr->doeptsiz[i]); ++ FH_DEBUGPL(DBG_ANY, "Backed up doepdma[%d] = %08x\n", i, ++ dr->doepdma[i]); ++ } ++ ++ return 0; ++} ++ ++int fh_otg_save_host_regs(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_host_regs_backup *hr; ++ int i; ++ ++ hr = core_if->hr_backup; ++ if (!hr) { ++ FH_WARN("hr_backup is not allocated!\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ hr->hcfg_local = ++ FH_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hr->haintmsk_local = ++ FH_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ for (i = 0; i < fh_otg_get_param_host_channels(core_if); ++i) { ++ hr->hcintmsk_local[i] = ++ FH_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); ++ } ++ hr->hprt0_local = FH_READ_REG32(core_if->host_if->hprt0); ++ hr->hfir_local = ++ FH_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ ++ FH_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers===============\n"); ++ FH_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", ++ hr->hcfg_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); ++ for (i = 0; i <= fh_otg_get_param_host_channels(core_if); ++i) { ++ FH_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, ++ hr->hcintmsk_local[i]); ++ } ++ FH_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", ++ hr->hprt0_local); ++ FH_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", ++ hr->hfir_local); ++ ++ return 0; ++} ++ ++int fh_otg_restore_global_regs(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ return -FH_E_INVALID; ++ } ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, gr->gnptxfsiz_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, gr->hptxfsiz_local); ++ FH_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, gr->gdfifocfg_local); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ FH_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], gr->dtxfsiz_local[i]); ++ } ++ ++// FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++// FH_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); Done in fh_otg_host_hibernation_restore no need here //mvardan ++ FH_WRITE_REG32(&core_if->core_global_regs->gahbcfg, (gr->gahbcfg_local)); ++ return 0; ++} ++ ++int fh_otg_restore_dev_regs(fh_otg_core_if_t * core_if, int rem_wakeup) ++{ ++ struct fh_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ ++ if (!dr) { ++ return -FH_E_INVALID; ++ } ++ ++ if (!rem_wakeup) { ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dr->dctl); ++ } ++ ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; ++i) { ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doeptsiz, dr->doeptsiz[i]); ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepdma, dr->doepdma[i]); ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, dr->doepctl[i]); ++ } ++ ++ return 0; ++} ++ ++int fh_otg_restore_host_regs(fh_otg_core_if_t * core_if, int reset) ++{ ++ struct fh_otg_host_regs_backup *hr; ++ int i; ++ hr = core_if->hr_backup; ++ ++ if (!hr) { ++ return -FH_E_INVALID; ++ } ++ ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); ++ //if (!reset) ++ //{ ++ // FH_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); ++ //} ++ ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, ++ hr->haintmsk_local); ++ for (i = 0; i < fh_otg_get_param_host_channels(core_if); ++i) { ++ FH_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, ++ hr->hcintmsk_local[i]); ++ } ++ ++ return 0; ++} ++ ++int restore_lpm_i2c_regs(fh_otg_core_if_t * core_if) ++{ ++ struct fh_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ ++ /* Restore values for LPM and I2C */ ++#ifdef CONFIG_USB_FH_OTG_LPM ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); ++#endif ++ FH_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); ++ ++ return 0; ++} ++ ++int restore_essential_regs(fh_otg_core_if_t * core_if, int rmode, int is_host) ++{ ++ struct fh_otg_global_regs_backup *gr; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ /* Restore LPM and I2C registers */ ++ restore_lpm_i2c_regs(core_if); ++ ++ /* Set PCGCCTL to 0 */ ++ FH_WRITE_REG32(core_if->pcgcctl, 0x00000000); ++ ++ gr = core_if->gr_backup; ++ /* Load restore values for [31:14] bits */ ++ FH_WRITE_REG32(core_if->pcgcctl, ++ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); ++ ++ /* Umnask global Interrupt in GAHBCFG and restore it */ ++ gahbcfg.d32 = gr->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ /* Clear all pending interupts */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Unmask restore done interrupt */ ++ gintmsk.b.restoredone = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ ++ /* Restore GUSBCFG and HCFG/DCFG */ ++ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ ++ if (is_host) { ++ hcfg_data_t hcfg = {.d32 = 0 }; ++ hcfg.d32 = core_if->hr_backup->hcfg_local; ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ fh_udelay(10); ++ ++ /* Load restore values for [31:14] bits and set EssRegRestored bit */ ++ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } else { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ dcfg.d32 = core_if->dr_backup->dcfg; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ if (!rmode) { ++ pcgcctl.d32 |= 0x208; ++ } ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ fh_udelay(10); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (!rmode) ++ pcgcctl.d32 |= 0x208; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY ++ * type. ++ */ ++static void init_fslspclksel(fh_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ hcfg_data_t hcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == FH_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = FH_HCFG_48_MHZ; ++ } else { ++ /* High speed PHY running at full speed or high speed */ ++ val = FH_HCFG_30_60_MHZ; ++ } ++ ++ FH_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); ++ hcfg.d32 = FH_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.fslspclksel = val; ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/** ++ * Initializes the DevSpd field of the DCFG register depending on the PHY type ++ * and the enumeration speed of the device. ++ */ ++static void init_devspd(fh_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ dcfg_data_t dcfg; ++ ++ if (((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) || ++ (core_if->core_params->phy_type == FH_PHY_TYPE_PARAM_FS)) { ++ /* Full speed PHY */ ++ val = 0x3; ++ } else if (core_if->core_params->speed == FH_SPEED_PARAM_FULL) { ++ /* High speed PHY running at full speed */ ++ val = 0x1; ++ } else { ++ /* High speed PHY running at high speed */ ++ val = 0x0; ++ } ++ ++ FH_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); ++ ++ dcfg.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++/** ++ * This function calculates the number of IN EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the FH_otg controller ++ */ ++static uint32_t calc_num_in_eps(fh_otg_core_if_t * core_if) ++{ ++ uint32_t num_in_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3; ++ uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_in_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ num_in_eps = ++ (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps; ++ } ++ ++ return num_in_eps; ++} ++ ++/** ++ * This function calculates the number of OUT EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the FH_otg controller ++ */ ++static uint32_t calc_num_out_eps(fh_otg_core_if_t * core_if) ++{ ++ uint32_t num_out_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_out_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ return num_out_eps; ++} ++ ++/** ++ * This function initializes the FH_otg controller registers and ++ * prepares the core for device mode or host mode operation. ++ * ++ * @param core_if Programming view of the FH_otg controller ++ * ++ */ ++void fh_otg_core_init(fh_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ gi2cctl_data_t i2cctl = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_CILV, "fh_otg_core_init(%p)\n", core_if); ++ ++ /* Common Initialization */ ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ ++ /* Program the ULPI External VBUS bit if needed */ ++ usbcfg.b.ulpi_ext_vbus_drv = ++ (core_if->core_params->phy_ulpi_ext_vbus == ++ FH_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0; ++ ++ /* Set external TS Dline pulsing */ ++ usbcfg.b.term_sel_dl_pulse = ++ (core_if->core_params->ts_dline == 1) ? 1 : 0; ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset the Controller */ ++ fh_otg_core_reset(core_if); ++ ++ core_if->adp_enable = core_if->core_params->adp_supp_enable; ++ core_if->power_down = core_if->core_params->power_down; ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev_if->num_in_eps = calc_num_in_eps(core_if); ++ dev_if->num_out_eps = calc_num_out_eps(core_if); ++ ++ FH_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", ++ core_if->hwcfg4.b.num_dev_perio_in_ep); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ dev_if->perio_tx_fifo_size[i] = ++ FH_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ FH_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->perio_tx_fifo_size[i]); ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dev_if->tx_fifo_size[i] = ++ FH_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ FH_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->tx_fifo_size[i]); ++ } ++ ++ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; ++ core_if->rx_fifo_size = FH_READ_REG32(&global_regs->grxfsiz); ++ core_if->nperio_tx_fifo_size = ++ FH_READ_REG32(&global_regs->gnptxfsiz) >> 16; ++ ++ FH_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n", ++ core_if->nperio_tx_fifo_size); ++ ++ /* ++ fh_otg_dump_global_registers(core_if); ++ fh_otg_dump_dev_registers(core_if); ++ */ ++ ++ ++ /* This programming sequence needs to happen in FS mode before any other ++ * programming occurs */ ++ if ((core_if->core_params->speed == FH_SPEED_PARAM_FULL) && ++ (core_if->core_params->phy_type == FH_PHY_TYPE_PARAM_FS)) { ++ /* If FS mode with FS PHY */ ++ ++ /* core_init() is now called on every switch so only call the ++ * following for the first time through. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ FH_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.physel = 1; ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Reset after a PHY select */ ++ fh_otg_core_reset(core_if); ++ } ++ ++ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also ++ * do this on HNP Dev/Host mode switches (done in dev_init and ++ * host_init). */ ++ if (fh_otg_is_host_mode(core_if)) { ++ init_fslspclksel(core_if); ++ } else { ++ init_devspd(core_if); ++ } ++ ++ if (core_if->core_params->i2c_enable) { ++ FH_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); ++ /* Program GUSBCFG.OtgUtmifsSel to I2C */ ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.otgutmifssel = 1; ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++ /* Program GI2CCTL.I2CEn */ ++ i2cctl.d32 = FH_READ_REG32(&global_regs->gi2cctl); ++ i2cctl.b.i2cdevaddr = 1; ++ i2cctl.b.i2cen = 0; ++ FH_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ i2cctl.b.i2cen = 1; ++ FH_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); ++ } ++ ++ } /* endif speed == FH_SPEED_PARAM_FULL */ ++ else { ++ /* High speed PHY. */ ++ if (!core_if->phy_init_done) { ++ core_if->phy_init_done = 1; ++ /* HS PHY parameters. These parameters are preserved ++ * during soft reset so only program the first time. Do ++ * a soft reset immediately after setting phyif. */ ++ ++ if (core_if->core_params->phy_type == 2) { ++ /* ULPI interface */ ++ usbcfg.b.ulpi_utmi_sel = 1; ++ usbcfg.b.phyif = 0; ++ usbcfg.b.ddrsel = ++ core_if->core_params->phy_ulpi_ddr; ++ } else if (core_if->core_params->phy_type == 1) { ++ /* UTMI+ interface */ ++ usbcfg.b.ulpi_utmi_sel = 0; ++ if (core_if->core_params->phy_utmi_width == 16) { ++ usbcfg.b.phyif = 1; ++ ++ } else { ++ usbcfg.b.phyif = 0; ++ } ++ } else { ++ FH_ERROR("FS PHY TYPE\n"); ++ } ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ /* Reset after setting the PHY parameters */ ++ fh_otg_core_reset(core_if); ++ } ++ } ++ ++ if ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls)) { ++ FH_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 1; ++ usbcfg.b.ulpi_clk_sus_m = 1; ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } else { ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ usbcfg.b.ulpi_fsls = 0; ++ usbcfg.b.ulpi_clk_sus_m = 0; ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ } ++ ++ /* Program the GAHBCFG Register. */ ++ switch (core_if->hwcfg2.b.architecture) { ++ ++ case FH_SLAVE_ONLY_ARCH: ++ FH_DEBUGPL(DBG_CIL, "Slave Only Mode\n"); ++ ahbcfg.b.nptxfemplvl_txfemplvl = ++ FH_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ ahbcfg.b.ptxfemplvl = FH_GAHBCFG_TXFEMPTYLVL_HALFEMPTY; ++ core_if->dma_enable = 0; ++ core_if->dma_desc_enable = 0; ++ break; ++ ++ case FH_EXT_DMA_ARCH: ++ FH_DEBUGPL(DBG_CIL, "External DMA Mode\n"); ++ { ++ uint8_t brst_sz = core_if->core_params->dma_burst_size; ++ ahbcfg.b.hburstlen = 0; ++ while (brst_sz > 1) { ++ ahbcfg.b.hburstlen++; ++ brst_sz >>= 1; ++ } ++ } ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ case FH_INT_DMA_ARCH: ++ FH_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); ++ /* Old value was FH_GAHBCFG_INT_DMA_BURST_INCR - done for ++ Host mode ISOC in issue fix - vahrama */ ++ ahbcfg.b.hburstlen = FH_GAHBCFG_INT_DMA_BURST_INCR4; ++ core_if->dma_enable = (core_if->core_params->dma_enable != 0); ++ core_if->dma_desc_enable = ++ (core_if->core_params->dma_desc_enable != 0); ++ break; ++ ++ } ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ FH_PRINTF("Using Descriptor DMA mode\n"); ++ } else { ++ FH_PRINTF("Using Buffer DMA mode\n"); ++ } ++ } else { ++ FH_PRINTF("Using Slave mode\n"); ++ core_if->dma_desc_enable = 0; ++ } ++ ++ if (core_if->core_params->ahb_single) { ++ ahbcfg.b.ahbsingle = 1; ++ } ++ ++ ahbcfg.b.dmaenable = core_if->dma_enable; ++ FH_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32); ++ ++ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en; ++ ++ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0; ++ core_if->multiproc_int_enable = core_if->core_params->mpi_enable; ++ FH_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n", ++ ((core_if->pti_enh_enable) ? "enabled" : "disabled")); ++ FH_PRINTF("Multiprocessor Interrupt Enhancement - %s\n", ++ ((core_if->multiproc_int_enable) ? "enabled" : "disabled")); ++ ++ /* ++ * Program the GUSBCFG register. ++ */ ++ usbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ ++ switch (core_if->hwcfg2.b.op_mode) { ++ case FH_MODE_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = (core_if->core_params->otg_cap == ++ FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case FH_MODE_SRP_ONLY_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case FH_MODE_NO_HNP_SRP_CAPABLE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case FH_MODE_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case FH_MODE_NO_SRP_CAPABLE_DEVICE: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ ++ case FH_MODE_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = (core_if->core_params->otg_cap != ++ FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ break; ++ ++ case FH_MODE_NO_SRP_CAPABLE_HOST: ++ usbcfg.b.hnpcap = 0; ++ usbcfg.b.srpcap = 0; ++ break; ++ } ++ ++ FH_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ /* To enable LPM support set lpm_cap_en bit */ ++ lpmcfg.b.lpm_cap_en = 1; ++ ++ /* Make AppL1Res ACK */ ++ lpmcfg.b.appl_resp = 1; ++ ++ /* Retry 3 times */ ++ lpmcfg.b.retry_count = 3; ++ ++ FH_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, ++ 0, lpmcfg.d32); ++ ++ } ++#endif ++ if (core_if->core_params->ic_usb_cap) { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.b.ic_usb_cap = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gusbcfg, ++ 0, gusbcfg.d32); ++ } ++ { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.otgver = core_if->core_params->otg_ver; ++#ifdef FH_HOST_ONLY ++ gotgctl.b.vbvalidoven = 1; ++ gotgctl.b.vbvalidovval = 1; ++#endif ++ FH_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, ++ gotgctl.d32); ++ /* Set OTG version supported */ ++ core_if->otg_ver = core_if->core_params->otg_ver; ++ FH_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n", ++ core_if->core_params->otg_ver, core_if->otg_ver); ++ } ++ ++ /* Enable common interrupts */ ++ fh_otg_enable_common_interrupts(core_if); ++ ++ /* Do device or host intialization based on mode during PCD ++ * and HCD initialization */ ++ if (fh_otg_is_host_mode(core_if)) { ++ FH_DEBUGPL(DBG_ANY, "Host Mode\n"); ++ core_if->op_state = A_HOST; ++ } else { ++ FH_DEBUGPL(DBG_ANY, "Device Mode\n"); ++ core_if->op_state = B_PERIPHERAL; ++#ifdef FH_DEVICE_ONLY ++ fh_otg_core_dev_init(core_if); ++#endif ++ } ++} ++ ++ ++/** ++ * This function enables the Device mode interrupts. ++ * ++ * @param core_if Programming view of FH_otg controller ++ */ ++void fh_otg_enable_device_interrupts(fh_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ ++ FH_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ FH_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ FH_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ fh_otg_enable_common_interrupts(core_if); ++ ++ /* Enable interrupts */ ++ intr_mask.b.usbreset = 1; ++ intr_mask.b.enumdone = 1; ++ /* Disable Disconnect interrupt in Device mode */ ++ intr_mask.b.disconnect = 0; ++ ++ if (!core_if->multiproc_int_enable) { ++ intr_mask.b.inepintr = 1; ++ intr_mask.b.outepintr = 1; ++ } ++ ++ intr_mask.b.erlysuspend = 1; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.epmismatch = 1; ++ } ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dctl_data_t dctl1 = {.d32 = 0 }; ++ dctl1.b.ifrmnum = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl1.d32); ++ } ++ } ++ ++ //intr_mask.b.incomplisoout = 1; ++ if (!core_if->dma_desc_enable) ++ intr_mask.b.incomplisoin = 1; ++ ++/* Enable the ignore frame number for ISOC xfers - MAS */ ++/* Disable to support high bandwith ISOC transfers - manukz */ ++#if 0 ++#ifdef FH_UTE_PER_IO ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dctl_data_t dctl1 = {.d32 = 0 }; ++ dctl1.b.ifrmnum = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl1.d32); ++ FH_DEBUG("----Enabled Ignore frame number (0x%08x)", ++ FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl)); ++ } ++ } ++#endif ++#endif ++#ifdef FH_EN_ISOC ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (core_if->pti_enh_enable) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.ifrmnum = 1; ++ FH_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++ } ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++#endif /* FH_EN_ISOC */ ++ ++ /** @todo NGS: Should this be a module parameter? */ ++#ifdef USE_PERIODIC_EP ++ intr_mask.b.isooutdrop = 1; ++ intr_mask.b.eopframe = 1; ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++#endif ++ ++ FH_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ ++ FH_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ++ FH_READ_REG32(&global_regs->gintmsk)); ++} ++ ++/** ++ * This function initializes the FH_otg controller registers for ++ * device mode. ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ */ ++void fh_otg_core_dev_init(fh_otg_core_if_t * core_if) ++{ ++ int i; ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ fh_otg_core_params_t *params = core_if->core_params; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize; ++ dthrctl_data_t dthrctl; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ fh_udelay(10); ++ ++ /* Device configuration register */ ++ init_devspd(core_if); ++ dcfg.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; ++ dcfg.b.perfrint = FH_DCFG_FRAME_INTERVAL_80; ++ /* Enable Device OUT NAK in case of DDMA mode */ ++ if (core_if->core_params->dev_out_nak) { ++ dcfg.b.endevoutnak = 1; ++ } ++ ++ if (core_if->core_params->cont_on_bna) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.encontonbna = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ /** should be done before every reset */ ++ if (core_if->otg_ver) { ++ core_if->otg_sts = 0; ++ gotgctl.b.devhnpen = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ FH_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->dev_rx_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->dev_nperio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->grxfsiz)); ++ ++#ifdef FH_UTE_CFI ++ core_if->pwron_rxfsiz = FH_READ_REG32(&global_regs->grxfsiz); ++ core_if->init_rxfsiz = params->dev_rx_fifo_size; ++#endif ++ rx_fifo_size = params->dev_rx_fifo_size; ++ FH_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ FH_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->grxfsiz)); ++ ++ /** Set Periodic Tx FIFO Mask all bits 0 */ ++ core_if->p_tx_msk = 0; ++ ++ /** Set Tx FIFO Mask all bits 0 */ ++ core_if->tx_msk = 0; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* Non-periodic Tx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ FH_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ FH_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /**@todo NGS: Fix Periodic FIFO Sizing! */ ++ /* ++ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_perio_tx_fifo_size array and the FIFO size registers in ++ * the dptxfsiz array run from 0 to 14. ++ */ ++ /** @todo Finish debug of this */ ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ ptxfifosize.b.depth = ++ params->dev_perio_tx_fifo_size[i]; ++ FH_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", i, ++ FH_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ FH_WRITE_REG32(&global_regs->dtxfsiz[i], ++ ptxfifosize.d32); ++ FH_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", ++ i, ++ FH_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ptxfifosize.b.startaddr += ptxfifosize.b.depth; ++ } ++ } else { ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ ++#ifdef FH_UTE_CFI ++ core_if->pwron_gnptxfsiz = ++ (FH_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ core_if->init_gnptxfsiz = ++ params->dev_nperio_tx_fifo_size; ++#endif ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ FH_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ FH_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ txfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ txfifosize.b.depth = ++ params->dev_tx_fifo_size[i]; ++ ++#ifdef FH_UTE_CFI ++ core_if->pwron_txfsiz[i] = ++ (FH_READ_REG32 ++ (&global_regs->dtxfsiz[i]) >> 16); ++ core_if->init_txfsiz[i] = ++ params->dev_tx_fifo_size[i]; ++#endif ++ FH_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize.d32); ++ ++ FH_DEBUGPL(DBG_CIL, ++ "new dtxfsiz[%d]=%08x\n", ++ i, ++ FH_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++ txfifosize.b.startaddr += txfifosize.b.depth; ++ } ++ ++ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO ++ * Before 3.00a EpInfoBase was being configured in ep enable/disable ++ * routine as well. Starting from 3.00a it will be set to the end of ++ * allocated FIFO space here due to ep 0 OUT always keeping enabled ++ */ ++ gdfifocfg.d32 = FH_READ_REG32(&global_regs->gdfifocfg); ++ hwcfg3.d32 = FH_READ_REG32(&global_regs->ghwcfg3); ++ gdfifocfg.b.gdfifocfg = (FH_READ_REG32(&global_regs->ghwcfg3) >> 16); ++ FH_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ rxfsiz = (FH_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (FH_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; ++ } else { ++ gdfifocfg.b.epinfobase = txfifosize.b.startaddr; ++ } ++ FH_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* Flush the FIFOs */ ++ fh_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ fh_otg_flush_rx_fifo(core_if); ++ ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ FH_DEBUGPL(DBG_CILV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); ++ } ++ FH_DEBUGPL(DBG_CILV, "\n"); ++ } ++ ++ /* Clear all pending Device Interrupts */ ++ /** @todo - if the condition needed to be checked ++ * or in any case all pending interrutps should be cleared? ++ */ ++ if (core_if->multiproc_int_enable) { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ FH_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ FH_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ } ++ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); ++ FH_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); ++ } else { ++ FH_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); ++ FH_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); ++ FH_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ FH_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); ++ } ++ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ } ++ ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ } ++ ++ for (i = 1; i <= dev_if->num_out_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = FH_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (depctl.b.epena) { ++ int j = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintsts = {.d32 = 0 }; ++ doepint_data_t doepint = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dctl.b.sgoutnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ if (!core_if->dma_enable) { ++ do { ++ j++; ++ fh_udelay(10); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ FH_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.rxstsqlvl); ++ status.d32 = FH_READ_REG32(&global_regs->grxstsp); ++ if (status.b.pktsts == FH_DSTS_GOUT_NAK) ++ FH_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ } ++ j = 0; ++ do { ++ j++; ++ fh_udelay(10); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ FH_ERROR("SNAK is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ j = 0; ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ do { ++ fh_udelay(10); ++ doepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[i]->doepint); ++ if (j == 100000) { ++ FH_ERROR("EPDIS was not set during 10s\n"); ++ break; ++ } ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ depctl.d32 = 0; ++ } ++ ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ } ++ ++ if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1; ++ dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1; ++ dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1; ++ ++ dev_if->rx_thr_length = params->rx_thr_length; ++ dev_if->tx_thr_length = params->tx_thr_length; ++ ++ dev_if->setup_desc_index = 0; ++ ++ dthrctl.d32 = 0; ++ dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; ++ dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; ++ dthrctl.b.tx_thr_len = dev_if->tx_thr_length; ++ dthrctl.b.rx_thr_en = dev_if->rx_thr_en; ++ dthrctl.b.rx_thr_len = dev_if->rx_thr_length; ++ dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; ++ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, ++ dthrctl.d32); ++ ++ FH_DEBUGPL(DBG_CIL, ++ "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", ++ dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, ++ dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, ++ dthrctl.b.rx_thr_len); ++ ++ } ++ ++ fh_otg_enable_device_interrupts(core_if); ++ ++ { ++ diepmsk_data_t msk = {.d32 = 0 }; ++ msk.b.txfifoundrn = 1; ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[0], msk.d32, msk.d32); ++ } else { ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, ++ msk.d32, msk.d32); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ /* Set NAK on Babble */ ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.nakonbble = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.sftdiscon = 0; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++} ++ ++/** ++ * This function enables the Host mode interrupts. ++ * ++ * @param core_if Programming view of FH_otg controller ++ */ ++void fh_otg_enable_host_interrupts(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ FH_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts. */ ++ FH_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ fh_otg_enable_common_interrupts(core_if); ++ ++ /* ++ * Enable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ ++ intr_mask.b.disconnect = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ ++ FH_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++} ++ ++/** ++ * This function disables the Host Mode interrupts. ++ * ++ * @param core_if Programming view of FH_otg controller ++ */ ++void fh_otg_disable_host_interrupts(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_CILV, "%s()\n", __func__); ++ ++ /* ++ * Disable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ intr_mask.b.ptxfempty = 1; ++ intr_mask.b.nptxfempty = 1; ++ ++ FH_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); ++} ++ ++/** ++ * This function initializes the FH_otg controller registers for ++ * host mode. ++ * ++ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the ++ * request queues. Host channels are reset to ensure that they are ready for ++ * performing transfers. ++ * ++ * @param core_if Programming view of FH_otg controller ++ * ++ */ ++void fh_otg_core_host_init(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ fh_otg_host_if_t *host_if = core_if->host_if; ++ fh_otg_core_params_t *params = core_if->core_params; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz, hptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ int i; ++ hcchar_data_t hcchar; ++ hcfg_data_t hcfg; ++ hfir_data_t hfir; ++ fh_otg_hc_regs_t *hc_regs; ++ int num_channels; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ FH_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ fh_udelay(10); ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_HOST)) { ++ FH_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state); ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ FH_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ FH_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ /* Initialize Host Configuration Register */ ++ init_fslspclksel(core_if); ++ if (core_if->core_params->speed == FH_SPEED_PARAM_FULL) { ++ hcfg.d32 = FH_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.fslssupp = 1; ++ FH_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ ++ } ++ ++ /* This bit allows dynamic reloading of the HFIR register ++ * during runtime. This bit needs to be programmed during ++ * initial configuration and its value must not be changed ++ * during runtime.*/ ++ if (core_if->core_params->reload_ctl == 1) { ++ hfir.d32 = FH_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.hfirrldctrl = 1; ++ FH_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ } ++ ++ if (core_if->core_params->dma_desc_enable) { ++ uint8_t op_mode = core_if->hwcfg2.b.op_mode; ++ if (! ++ (core_if->hwcfg4.b.desc_dma ++ && (core_if->snpsid >= OTG_CORE_REV_2_90a) ++ && ((op_mode == FH_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == FH_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (op_mode == ++ FH_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == FH_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ++ || (op_mode == ++ FH_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) { ++ ++ FH_ERROR("Host can't operate in Descriptor DMA mode.\n" ++ "Either core version is below 2.90a or " ++ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n" ++ "To run the driver in Buffer DMA host mode set dma_desc_enable " ++ "module parameter to 0.\n"); ++ return; ++ } ++ hcfg.d32 = FH_READ_REG32(&host_if->host_global_regs->hcfg); ++ hcfg.b.descdma = 1; ++ FH_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ FH_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->host_rx_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->host_nperio_tx_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", ++ params->host_perio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->grxfsiz)); ++ FH_WRITE_REG32(&global_regs->grxfsiz, ++ params->host_rx_fifo_size); ++ FH_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ nptxfifosize.b.depth = params->host_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->host_rx_fifo_size; ++ FH_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ FH_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /* Periodic Tx FIFO */ ++ FH_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->hptxfsiz)); ++ ptxfifosize.b.depth = params->host_perio_tx_fifo_size; ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ FH_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32); ++ FH_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", ++ FH_READ_REG32(&global_regs->hptxfsiz)); ++ ++ if (core_if->en_multiple_tx_fifo) { ++ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ ++ gdfifocfg.d32 = FH_READ_REG32(&global_regs->gdfifocfg); ++ rxfsiz = (FH_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (FH_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ hptxfsiz = (FH_READ_REG32(&global_regs->hptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; ++ FH_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* TODO - check this */ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ /* Make sure the FIFOs are flushed. */ ++ fh_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ ); ++ fh_otg_flush_rx_fifo(core_if); ++ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ ++ if (!core_if->core_params->dma_desc_enable) { ++ /* Flush out any leftover queued requests. */ ++ num_channels = core_if->core_params->host_channels; ++ ++ for (i = 0; i < num_channels; i++) { ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ } ++ ++ ++ /* Halt all channels to put them into a known state. */ ++ for (i = 0; i < num_channels; i++) { ++ int count = 0; ++ hc_regs = core_if->host_if->hc_regs[i]; ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ if(!core_if->core_params->dma_enable) { ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ if (++count > 1000) { ++ FH_ERROR ++ ("%s: RxSTSQLVL interrupt wasn't seen for channel %d\n", ++ __func__, i); ++ break; ++ } ++ fh_udelay(1); ++ } while (!gintsts.b.rxstsqlvl); ++ ++ if (count<=1000) ++ FH_READ_REG32(&core_if->core_global_regs->grxstsp); ++ count=0; ++ } ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i); ++ do { ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (++count > 1000) { ++ FH_ERROR ++ ("%s: Unable to clear halt on channel %d\n", ++ __func__, i); ++ break; ++ } ++ fh_udelay(1); ++ } while (hcchar.b.chen); ++ } ++ ++ } ++ ++ /* Turn on the vbus power. */ ++ if ((core_if->otg_ver == 0) && (core_if->op_state == A_HOST)) { ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ FH_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ FH_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ fh_otg_enable_host_interrupts(core_if); ++} ++ ++/** ++ * Prepares a host channel for transferring packets to/from a specific ++ * endpoint. The HCCHARn register is set up with the characteristics specified ++ * in _hc. Host channel interrupts that may need to be serviced while this ++ * transfer is in progress are enabled. ++ * ++ * @param core_if Programming view of FH_otg controller ++ * @param hc Information needed to initialize the host channel ++ */ ++void fh_otg_hc_init(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ uint32_t intr_enable; ++ hcintmsk_data_t hc_intr_mask; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ ++ uint8_t hc_num = hc->hc_num; ++ fh_otg_host_if_t *host_if = core_if->host_if; ++ fh_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num]; ++ ++ /* Clear old interrupt conditions for this host channel. */ ++ hc_intr_mask.d32 = 0xFFFFFFFF; ++ hc_intr_mask.b.reserved14_31 = 0; ++ FH_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32); ++ ++ /* Enable channel interrupts required for this transfer. */ ++ hc_intr_mask.d32 = 0; ++ hc_intr_mask.b.chhltd = 1; ++ if (core_if->dma_enable) { ++ /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */ ++ if (!core_if->dma_desc_enable) ++ hc_intr_mask.b.ahberr = 1; ++ else { ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC) ++ hc_intr_mask.b.xfercompl = 1; ++ } ++ ++ if (hc->error_state && !hc->do_split && ++ hc->ep_type != FH_OTG_EP_TYPE_ISOC) { ++ hc_intr_mask.b.ack = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_type != FH_OTG_EP_TYPE_INTR) { ++ hc_intr_mask.b.nak = 1; ++ } ++ } ++ } ++ } else { ++ switch (hc->ep_type) { ++ case FH_OTG_EP_TYPE_CONTROL: ++ case FH_OTG_EP_TYPE_BULK: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } else { ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.nyet = 1; ++ if (hc->do_ping) { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ hc_intr_mask.b.nak = 1; ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ break; ++ case FH_OTG_EP_TYPE_INTR: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ break; ++ case FH_OTG_EP_TYPE_ISOC: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ hc_intr_mask.b.ack = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.bblerr = 1; ++ } ++ break; ++ } ++ } ++ FH_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ ++ /* Enable the top level host channel interrupt. */ ++ intr_enable = (1 << hc_num); ++ FH_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ ++ /* Make sure host channel interrupts are enabled. */ ++ gintmsk.b.hcintr = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ ++ /* ++ * Program the HCCHARn register with the endpoint characteristics for ++ * the current transfer. ++ */ ++ hcchar.d32 = 0; ++ hcchar.b.devaddr = hc->dev_addr; ++ hcchar.b.epnum = hc->ep_num; ++ hcchar.b.epdir = hc->ep_is_in; ++ hcchar.b.lspddev = (hc->speed == FH_OTG_EP_SPEED_LOW); ++ hcchar.b.eptype = hc->ep_type; ++ hcchar.b.mps = hc->max_packet; ++ ++ FH_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); ++ FH_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); ++ FH_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); ++ FH_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); ++ FH_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); ++ FH_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ FH_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); ++ ++ /* ++ * Program the HCSPLIT register for SPLITs ++ */ ++ hcsplt.d32 = 0; ++ if (hc->do_split) { ++ FH_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ++ hc->hc_num, ++ hc->complete_split ? "CSPLIT" : "SSPLIT"); ++ hcsplt.b.compsplt = hc->complete_split; ++ hcsplt.b.xactpos = hc->xact_pos; ++ hcsplt.b.hubaddr = hc->hub_addr; ++ hcsplt.b.prtaddr = hc->port_addr; ++ FH_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); ++ FH_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); ++ FH_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); ++ FH_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); ++ FH_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); ++ FH_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); ++ FH_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); ++ } ++ FH_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ ++} ++ ++/** ++ * Attempts to halt a host channel. This function should only be called in ++ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under ++ * normal circumstances in DMA mode, the controller halts the channel when the ++ * transfer is complete or a condition occurs that requires application ++ * intervention. ++ * ++ * In slave mode, checks for a free request queue entry, then sets the Channel ++ * Enable and Channel Disable bits of the Host Channel Characteristics ++ * register of the specified channel to intiate the halt. If there is no free ++ * request queue entry, sets only the Channel Disable bit of the HCCHARn ++ * register to flush requests for this channel. In the latter case, sets a ++ * flag to indicate that the host channel needs to be halted when a request ++ * queue slot is open. ++ * ++ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the ++ * HCCHARn register. The controller ensures there is space in the request ++ * queue before submitting the halt request. ++ * ++ * Some time may elapse before the core flushes any posted requests for this ++ * host channel and halts. The Channel Halted interrupt handler completes the ++ * deactivation of the host channel. ++ * ++ * @param core_if Controller register interface. ++ * @param hc Host channel to halt. ++ * @param halt_status Reason for halting the channel. ++ */ ++void fh_otg_hc_halt(fh_otg_core_if_t * core_if, ++ fh_hc_t * hc, fh_otg_halt_status_e halt_status) ++{ ++ gnptxsts_data_t nptxsts; ++ hptxsts_data_t hptxsts; ++ hcchar_data_t hcchar; ++ fh_otg_hc_regs_t *hc_regs; ++ fh_otg_core_global_regs_t *global_regs; ++ fh_otg_host_global_regs_t *host_global_regs; ++ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ global_regs = core_if->core_global_regs; ++ host_global_regs = core_if->host_if->host_global_regs; ++ ++ FH_ASSERT(!(halt_status == FH_OTG_HC_XFER_NO_HALT_STATUS), ++ "halt_status = %d\n", halt_status); ++ ++ if (halt_status == FH_OTG_HC_XFER_URB_DEQUEUE || ++ halt_status == FH_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Disable all channel interrupts except Ch Halted. The QTD ++ * and QH state associated with this transfer has been cleared ++ * (in the case of URB_DEQUEUE), so the channel needs to be ++ * shut down carefully to prevent crashes. ++ */ ++ int wtd = 10000; ++ hcintmsk_data_t hcintmsk; ++ hcintmsk.d32 = 0; ++ hcintmsk.b.chhltd = 1; ++ FH_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); ++ ++ /* ++ * Make sure no other interrupts besides halt are currently ++ * pending. Handling another interrupt could cause a crash due ++ * to the QTD and QH state. ++ */ ++ FH_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); ++ ++ /* ++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR ++ * even if the channel was already halted for some other ++ * reason. ++ */ ++ hc->halt_status = halt_status; ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ while (wtd--) { ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen == 0) ++ break; ++ } ++ ++ if (hcchar.b.chen == 0) { ++ /* ++ * The channel is either already halted or it hasn't ++ * started yet. In DMA mode, the transfer may halt if ++ * it finishes normally or a condition occurs that ++ * requires driver intervention. Don't want to halt ++ * the channel again. In either Slave or DMA mode, ++ * it's possible that the transfer has been assigned ++ * to a channel, but not started yet when an URB is ++ * dequeued. Don't want to halt a channel that hasn't ++ * started yet. ++ */ ++ return; ++ } ++ } ++ if (hc->halt_pending) { ++ /* ++ * A halt has already been issued for this channel. This might ++ * happen when a transfer is aborted by a higher level in ++ * the stack. ++ */ ++#ifdef DEBUG ++ FH_PRINTF ++ ("*** %s: Channel %d, _hc->halt_pending already set ***\n", ++ __func__, hc->hc_num); ++ ++#endif ++ return; ++ } ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* No need to set the bit in DDMA for disabling the channel */ ++ //TODO check it everywhere channel is disabled ++ if (!core_if->core_params->dma_desc_enable) ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ ++ if (!core_if->dma_enable) { ++ /* Check for space in the request queue to issue the halt. */ ++ if (hc->ep_type == FH_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == FH_OTG_EP_TYPE_BULK) { ++ nptxsts.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ if (nptxsts.b.nptxqspcavail == 0) { ++ hcchar.b.chen = 0; ++ } ++ } else { ++ hptxsts.d32 = ++ FH_READ_REG32(&host_global_regs->hptxsts); ++ if ((hptxsts.b.ptxqspcavail == 0) ++ || (core_if->queuing_high_bandwidth)) { ++ hcchar.b.chen = 0; ++ } ++ } ++ } ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->halt_status = halt_status; ++ ++ if (hcchar.b.chen) { ++ hc->halt_pending = 1; ++ hc->halt_on_queue = 0; ++ } else { ++ hc->halt_on_queue = 1; ++ } ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); ++ FH_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); ++ FH_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); ++ FH_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); ++ ++ return; ++} ++ ++/** ++ * Clears the transfer state for a host channel. This function is normally ++ * called after a transfer is done and the host channel is being released. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param hc Identifies the host channel to clean up. ++ */ ++void fh_otg_hc_cleanup(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ fh_otg_hc_regs_t *hc_regs; ++ ++ hc->xfer_started = 0; ++ ++ /* ++ * Clear channel interrupt enables and any unhandled channel interrupt ++ * conditions. ++ */ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ FH_WRITE_REG32(&hc_regs->hcintmsk, 0); ++ FH_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); ++#ifdef DEBUG ++ FH_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); ++#endif ++} ++ ++/** ++ * Sets the channel property that indicates in which frame a periodic transfer ++ * should occur. This is always set to the _next_ frame. This function has no ++ * effect on non-periodic transfers. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param hc Identifies the host channel to set up and its properties. ++ * @param hcchar Current value of the HCCHAR register for the specified host ++ * channel. ++ */ ++static inline void hc_set_even_odd_frame(fh_otg_core_if_t * core_if, ++ fh_hc_t * hc, hcchar_data_t * hcchar) ++{ ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ FH_READ_REG32(&core_if->host_if->host_global_regs->hfnum); ++ ++ /* 1 if _next_ frame is odd, 0 if it's even */ ++ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++#ifdef DEBUG ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR && hc->do_split ++ && !hc->complete_split) { ++ switch (hfnum.b.frnum & 0x7) { ++ case 7: ++ core_if->hfnum_7_samples++; ++ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; ++ break; ++ case 0: ++ core_if->hfnum_0_samples++; ++ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; ++ break; ++ default: ++ core_if->hfnum_other_samples++; ++ core_if->hfnum_other_frrem_accum += ++ hfnum.b.frrem; ++ break; ++ } ++ } ++#endif ++ } ++} ++ ++#ifdef DEBUG ++void hc_xfer_timeout(void *ptr) ++{ ++ hc_xfer_info_t *xfer_info = NULL; ++ int hc_num = 0; ++ ++ if (ptr) ++ xfer_info = (hc_xfer_info_t *) ptr; ++ ++ if (!xfer_info->hc) { ++ FH_ERROR("xfer_info->hc = %p\n", xfer_info->hc); ++ return; ++ } ++ ++ hc_num = xfer_info->hc->hc_num; ++ FH_WARN("%s: timeout on channel %d\n", __func__, hc_num); ++ FH_WARN(" start_hcchar_val 0x%08x\n", ++ xfer_info->core_if->start_hcchar_val[hc_num]); ++} ++#endif ++ ++void ep_xfer_timeout(void *ptr) ++{ ++ ep_xfer_info_t *xfer_info = NULL; ++ int ep_num = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (ptr) ++ xfer_info = (ep_xfer_info_t *) ptr; ++ ++ if (!xfer_info->ep) { ++ FH_ERROR("xfer_info->ep = %p\n", xfer_info->ep); ++ return; ++ } ++ ++ ep_num = xfer_info->ep->num; ++ FH_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); ++ /* Put the sate to 2 as it was time outed */ ++ xfer_info->state = 2; ++ ++ dctl.d32 = ++ FH_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = ++ FH_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); ++ gintmsk.d32 = ++ FH_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); ++ ++ if (!gintmsk.b.goutnakeff) { ++ /* Unmask it */ ++ gintmsk.b.goutnakeff = 1; ++ FH_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, ++ gintmsk.d32); ++ ++ } ++ ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ FH_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++} ++ ++void set_pid_isoc(fh_hc_t * hc) ++{ ++ /* Set up the initial PID for the transfer. */ ++ if (hc->speed == FH_OTG_EP_SPEED_HIGH) { ++ if (hc->ep_is_in) { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = FH_OTG_HC_PID_DATA0; ++ } else if (hc->multi_count == 2) { ++ hc->data_pid_start = FH_OTG_HC_PID_DATA1; ++ } else { ++ hc->data_pid_start = FH_OTG_HC_PID_DATA2; ++ } ++ } else { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = FH_OTG_HC_PID_DATA0; ++ } else { ++ hc->data_pid_start = FH_OTG_HC_PID_MDATA; ++ } ++ } ++ } else { ++ hc->data_pid_start = FH_OTG_HC_PID_DATA0; ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel and ++ * starts the transfer. May be called in either Slave mode or DMA mode. In ++ * Slave mode, the caller must ensure that there is sufficient space in the ++ * request queue and Tx Data FIFO. ++ * ++ * For an OUT transfer in Slave mode, it loads a data packet into the ++ * appropriate FIFO. If necessary, additional data packets will be loaded in ++ * the Host ISR. ++ * ++ * For an IN transfer in Slave mode, a data packet is requested. The data ++ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, ++ * additional data packets are requested in the Host ISR. ++ * ++ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ ++ * register along with a packet count of 1 and the channel is enabled. This ++ * causes a single PING transaction to occur. Other fields in HCTSIZ are ++ * simply set to 0 since no data transfer occurs in this case. ++ * ++ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with ++ * all the information required to perform the subsequent data transfer. In ++ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the ++ * controller performs the entire PING protocol, then starts the data ++ * transfer. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param hc Information needed to initialize the host channel. The xfer_len ++ * value may be reduced to accommodate the max widths of the XferSize and ++ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed ++ * to reflect the final xfer_len value. ++ */ ++void fh_otg_hc_start_transfer(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ uint16_t num_packets; ++ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; ++ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; ++ fh_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) { ++ if (!core_if->dma_enable) { ++ fh_otg_hc_do_ping(core_if, hc); ++ hc->xfer_started = 1; ++ return; ++ } else { ++ hctsiz.b.dopng = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ num_packets = 1; ++ ++ if (hc->complete_split && !hc->ep_is_in) { ++ /* For CSPLIT OUT Transfer, set the size to 0 so the ++ * core doesn't expect any data written to the FIFO */ ++ hc->xfer_len = 0; ++ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } else { ++ /* ++ * Ensure that the transfer length and packet count will fit ++ * in the widths allocated for them in the HCTSIZn register. ++ */ ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure the transfer size is no larger than one ++ * (micro)frame's worth of data. (A check was done ++ * when the periodic transfer was accepted to ensure ++ * that a (micro)frame's worth of data can be ++ * programmed into a channel.) ++ */ ++ uint32_t max_periodic_len = ++ hc->multi_count * hc->max_packet; ++ if (hc->xfer_len > max_periodic_len) { ++ hc->xfer_len = max_periodic_len; ++ } else { ++ } ++ } else if (hc->xfer_len > max_hc_xfer_size) { ++ /* Make sure that xfer_len is a multiple of max packet size. */ ++ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; ++ } ++ ++ if (hc->xfer_len > 0) { ++ num_packets = ++ (hc->xfer_len + hc->max_packet - ++ 1) / hc->max_packet; ++ if (num_packets > max_hc_pkt_count) { ++ num_packets = max_hc_pkt_count; ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ ++ if (hc->ep_is_in) { ++ /* Always program an integral # of max packets for IN transfers. */ ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure that the multi_count field matches the ++ * actual transfer length. ++ */ ++ hc->multi_count = num_packets; ++ } ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } ++ ++ hc->start_pkt_count = num_packets; ++ hctsiz.b.pktcnt = num_packets; ++ hctsiz.b.pid = hc->data_pid_start; ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); ++ FH_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); ++ FH_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ ++ if (core_if->dma_enable) { ++ fh_dma_t dma_addr; ++ if (hc->align_buff) { ++ dma_addr = hc->align_buff; ++ } else { ++ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); ++ } ++ FH_WRITE_REG32(&hc_regs->hcdma, dma_addr); ++ } ++ ++ /* Start the split */ ++ if (hc->do_split) { ++ hcsplt_data_t hcsplt; ++ hcsplt.d32 = FH_READ_REG32(&hc_regs->hcsplt); ++ hcsplt.b.spltena = 1; ++ FH_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); ++ } ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ FH_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ fh_otg_hc_write_packet(core_if, hc); ++ } ++#ifdef DEBUG ++ if (hc->ep_type != FH_OTG_EP_TYPE_INTR) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ ++ /* Start a timer for this transfer. */ ++ FH_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel ++ * and starts the transfer in Descriptor DMA mode. ++ * ++ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. ++ * Sets PID and NTD values. For periodic transfers ++ * initializes SCHED_INFO field with micro-frame bitmap. ++ * ++ * Initializes HCDMA register with descriptor list address and CTD value ++ * then starts the transfer via enabling the channel. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param hc Information needed to initialize the host channel. ++ */ ++void fh_otg_hc_start_transfer_ddma(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ fh_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcdma_data_t hcdma; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) ++ hctsiz.b_ddma.dopng = 1; ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ ++ hctsiz.b_ddma.pid = hc->data_pid_start; ++ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ ++ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ FH_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); ++ ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcdma.d32 = 0; ++ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; ++ ++ /* Always start from first descriptor. */ ++ hcdma.b.ctd = 0; ++ FH_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ FH_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* Set host channel enable after all other setup is complete. */ ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++#ifdef DEBUG ++ if ((hc->ep_type != FH_OTG_EP_TYPE_INTR) ++ && (hc->ep_type != FH_OTG_EP_TYPE_ISOC)) { ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ /* Start a timer for this transfer. */ ++ FH_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++ ++} ++ ++/** ++ * This function continues a data transfer that was started by previous call ++ * to <code>fh_otg_hc_start_transfer</code>. The caller must ensure there is ++ * sufficient space in the request queue and Tx Data FIFO. This function ++ * should only be called in Slave mode. In DMA mode, the controller acts ++ * autonomously to complete transfers programmed to a host channel. ++ * ++ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO ++ * if there is any data remaining to be queued. For an IN transfer, another ++ * data packet is always requested. For the SETUP phase of a control transfer, ++ * this function does nothing. ++ * ++ * @return 1 if a new request is queued, 0 if no more requests are required ++ * for this transfer. ++ */ ++int fh_otg_hc_continue_transfer(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ if (hc->do_split) { ++ /* SPLITs always queue just once per channel */ ++ return 0; ++ } else if (hc->data_pid_start == FH_OTG_HC_PID_SETUP) { ++ /* SETUPs are queued only once since they can't be NAKed. */ ++ return 0; ++ } else if (hc->ep_is_in) { ++ /* ++ * Always queue another request for other IN transfers. If ++ * back-to-back INs are issued and NAKs are received for both, ++ * the driver may still be processing the first NAK when the ++ * second NAK is received. When the interrupt handler clears ++ * the NAK interrupt for the first NAK, the second NAK will ++ * not be seen. So we can't depend on the NAK interrupt ++ * handler to requeue a NAKed request. Instead, IN requests ++ * are issued each time this function is called. When the ++ * transfer completes, the extra requests for the channel will ++ * be flushed. ++ */ ++ hcchar_data_t hcchar; ++ fh_otg_hc_regs_t *hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ FH_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", ++ hcchar.d32); ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ hc->requests++; ++ return 1; ++ } else { ++ /* OUT transfers. */ ++ if (hc->xfer_count < hc->xfer_len) { ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ hcchar_data_t hcchar; ++ fh_otg_hc_regs_t *hc_regs; ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ } ++ ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ fh_otg_hc_write_packet(core_if, hc); ++ hc->requests++; ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/** ++ * Starts a PING transfer. This function should only be called in Slave mode. ++ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. ++ */ ++void fh_otg_hc_do_ping(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ fh_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ FH_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ hctsiz.d32 = 0; ++ hctsiz.b.dopng = 1; ++ hctsiz.b.pktcnt = 1; ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++} ++ ++/* ++ * This function writes a packet into the Tx FIFO associated with the Host ++ * Channel. For a channel associated with a non-periodic EP, the non-periodic ++ * Tx FIFO is written. For a channel associated with a periodic EP, the ++ * periodic Tx FIFO is written. This function should only be called in Slave ++ * mode. ++ * ++ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by ++ * then number of bytes written to the Tx FIFO. ++ */ ++void fh_otg_hc_write_packet(fh_otg_core_if_t * core_if, fh_hc_t * hc) ++{ ++ uint32_t i; ++ uint32_t remaining_count; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ ++ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); ++ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; ++ ++ remaining_count = hc->xfer_len - hc->xfer_count; ++ if (remaining_count > hc->max_packet) { ++ byte_count = hc->max_packet; ++ } else { ++ byte_count = remaining_count; ++ } ++ ++ dword_count = (byte_count + 3) / 4; ++ ++ if ((((unsigned long)data_buff) & 0x3) == 0) { ++ /* xfer_buff is DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ FH_WRITE_REG32(data_fifo, *data_buff); ++ } ++ } else { ++ /* xfer_buff is not DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ uint32_t data; ++ data = ++ (data_buff[0] | data_buff[1] << 8 | data_buff[2] << ++ 16 | data_buff[3] << 24); ++ FH_WRITE_REG32(data_fifo, data); ++ } ++ } ++ ++ hc->xfer_count += byte_count; ++ hc->xfer_buff += byte_count; ++} ++ ++/** ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. ++ */ ++uint32_t fh_otg_get_frame_number(fh_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /* read current frame/microframe number from DSTS register */ ++ return dsts.b.soffn; ++} ++ ++/** ++ * Calculates and gets the frame Interval value of HFIR register according PHY ++ * type and speed.The application can modify a value of HFIR register only after ++ * the Port Enable bit of the Host Port Control and Status register ++ * (HPRT.PrtEnaPort) has been set. ++*/ ++ ++uint32_t calc_frame_interval(fh_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ hwcfg2_data_t hwcfg2; ++ hprt0_data_t hprt0; ++ int clock = 60; // default value ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ hwcfg2.d32 = FH_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ hprt0.d32 = FH_READ_REG32(core_if->host_if->hprt0); ++ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) ++ clock = 48; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 30; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 48; ++ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) ++ clock = 48; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) ++ clock = 48; ++ if (hprt0.b.prtspd == 0) ++ /* High speed case */ ++ return 125 * clock; ++ else ++ /* FS/LS case */ ++ return 1000 * clock; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Interrupt routine when a SETUP packet has been received in Slave mode. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param dest Destination buffer for packet data. ++ */ ++void fh_otg_read_setup_packet(fh_otg_core_if_t * core_if, uint32_t * dest) ++{ ++ device_grxsts_data_t status; ++ /* Get the 8 bytes of a setup transaction data */ ++ ++ /* Pop 2 DWORDS off the receive data FIFO into memory */ ++ dest[0] = FH_READ_REG32(core_if->data_fifo[0]); ++ dest[1] = FH_READ_REG32(core_if->data_fifo[0]); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a && core_if->snpsid < OTG_CORE_REV_3_30a) { ++ status.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->grxstsp); ++ FH_DEBUGPL(DBG_ANY, ++ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, status.b.pktsts, ++ status.b.fn, status.b.fn); ++ } ++} ++ ++/** ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the ++ * "Enumeration Done" interrupt occurs. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP0 data. ++ */ ++void fh_otg_ep0_activate(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ dsts_data_t dsts; ++ depctl_data_t diepctl; ++ depctl_data_t doepctl; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ ep->stp_rollover = 0; ++ /* Read the Device Status and Endpoint 0 Control registers */ ++ dsts.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = FH_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ ++ /* Set the MPS of the IN EP based on the enumeration speed */ ++ switch (dsts.b.enumspd) { ++ case FH_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ case FH_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case FH_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ diepctl.b.mps = FH_DEP0CTL_MPS_64; ++ break; ++ case FH_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ diepctl.b.mps = FH_DEP0CTL_MPS_8; ++ break; ++ } ++ ++ FH_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Enable OUT EP for receive */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.epena = 1; ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ FH_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ FH_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ FH_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++ dctl.b.cgnpinnak = 1; ++ ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ FH_DEBUGPL(DBG_PCDV, "dctl=%0x\n", ++ FH_READ_REG32(&dev_if->dev_global_regs->dctl)); ++ ++} ++ ++/** ++ * This function activates an EP. The Device EP control register for ++ * the EP is configured as defined in the ep structure. Note: This ++ * function is not used for EP0. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to activate. ++ */ ++void fh_otg_ep_activate(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++#ifdef FH_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ /* If the EP is already active don't change the EP Control ++ * register. */ ++ depctl.d32 = FH_READ_REG32(addr); ++ if (!depctl.b.usbactep) { ++ depctl.b.mps = ep->maxpacket; ++ depctl.b.eptype = ep->type; ++ depctl.b.txfnum = ep->tx_fifo_num; ++ ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) { ++ depctl.b.setd0pid = 1; // ??? ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ depctl.b.usbactep = 1; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) ++ break; ++ } ++ core_if->nextep_seq[i] = ep->num; ++ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ dcfg.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt++; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_DEBUGPL(DBG_PCDV, "%2d\n", ++ core_if->nextep_seq[i]); ++ } ++ ++ } ++ ++ ++ FH_WRITE_REG32(addr, depctl.d32); ++ FH_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", FH_READ_REG32(addr)); ++ } ++ ++ /* Enable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ if (ep->is_in == 1) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ diepmsk.b.txfifoundrn = 1; //????? ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) { ++ diepmsk.b.nak = 1; ++ } ++ ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ FH_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], diepmsk.d32); ++ ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) ++ doepmsk.b.outtknepdis = 1; ++ ++/* ++ ++ if (core_if->dma_desc_enable) { ++ doepmsk.b.bna = 1; ++ } ++*/ ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ doepmsk.b.nak = 1; ++*/ ++ FH_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], doepmsk.d32); ++ } ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, ++ 0, daintmsk.d32); ++ } else { ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) { ++ if (ep->is_in) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.nak = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.outtknepdis = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); ++ } ++ } ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, ++ 0, daintmsk.d32); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", ++ FH_READ_REG32(&dev_if->dev_global_regs->daintmsk)); ++ ++ ep->stall_clear_flag = 0; ++ ++ return; ++} ++ ++/** ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used ++ * for EP0. EP0 cannot be deactivated. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to deactivate. ++ */ ++void fh_otg_ep_deactivate(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i = 0; ++ uint32_t timeout = 1000; ++ ++#ifdef FH_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ depctl.d32 = FH_READ_REG32(addr); ++ ++ depctl.b.usbactep = 0; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG */ ++ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == ep->num) ++ break; ++ } ++ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; ++ if (core_if->first_in_nextep_seq == ep->num) ++ core_if->first_in_nextep_seq = i; ++ core_if->nextep_seq[ep->num] = 0xff; ++ depctl.b.nextep = 0; ++ dcfg.d32 = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt--; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ dcfg.d32); ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (ep->is_in == 1) ++ depctl.b.txfnum = 0; ++ ++ if (core_if->dma_desc_enable) ++ depctl.b.epdis = 1; ++ ++ FH_WRITE_REG32(addr, depctl.d32); ++ depctl.d32 = FH_READ_REG32(addr); ++ if (core_if->dma_enable && ep->type == FH_OTG_EP_TYPE_ISOC ++ && depctl.b.epena) { ++ depctl_data_t depctl = {.d32 = 0 }; ++ if (ep->is_in) { ++ diepint_data_t diepint = {.d32 = 0 }; ++ ++ depctl.b.snak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ fh_udelay(10); ++ diepint.d32 = ++ FH_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.inepnakeff && timeout--); ++ diepint.b.inepnakeff = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ fh_udelay(10); ++ diepint.d32 = ++ FH_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ } else { ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintsts = {.d32 = 0}; ++ doepint_data_t doepint = {.d32 = 0}; ++ dctl.b.sgoutnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ do { ++ fh_udelay(10); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); ++ do ++ { ++ fh_udelay(10); ++ doepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ } ++ ++ /* Disable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32, 0); ++ ++ if (ep->is_in == 1) { ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], 0); ++ } else { ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], 0); ++ } ++ } else { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32, 0); ++ } ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++static void init_dma_desc_chain(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ fh_otg_dev_dma_desc_t *dma_desc; ++ uint32_t offset; ++ uint32_t xfer_est; ++ int i; ++ unsigned maxxfer_local, total_len; ++ ++ if (!ep->is_in && ep->type == FH_OTG_EP_TYPE_INTR && ++ (ep->maxpacket % 4)) { ++ maxxfer_local = ep->maxpacket; ++ total_len = ep->xfer_len; ++ } else { ++ maxxfer_local = ep->maxxfer; ++ total_len = ep->total_len; ++ } ++ ++ ep->desc_cnt = (total_len / maxxfer_local) + ++ ((total_len % maxxfer_local) ? 1 : 0); ++ ++ if (!ep->desc_cnt) ++ ep->desc_cnt = 1; ++ ++ if (ep->desc_cnt > MAX_DMA_DESC_CNT) ++ ep->desc_cnt = MAX_DMA_DESC_CNT; ++ ++ dma_desc = ep->desc_addr; ++ if (maxxfer_local == ep->maxpacket) { ++ if ((total_len % maxxfer_local) && ++ (total_len / maxxfer_local < MAX_DMA_DESC_CNT)) { ++ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + ++ (total_len % maxxfer_local); ++ } else ++ xfer_est = ep->desc_cnt * maxxfer_local; ++ } else ++ xfer_est = total_len; ++ offset = 0; ++ for (i = 0; i < ep->desc_cnt; ++i) { ++ if (ep->type != FH_OTG_EP_TYPE_ISOC) { ++ ++ /** DMA Descriptor Setup */ ++ if (xfer_est > maxxfer_local) { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 0; ++ dma_desc->status.b.ioc = 0; ++ dma_desc->status.b.sp = 0; ++ dma_desc->status.b.bytes = maxxfer_local; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ xfer_est -= maxxfer_local; ++ offset += maxxfer_local; ++ } else { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ if (ep->is_in) { ++ dma_desc->status.b.sp = ++ (xfer_est % ++ ep->maxpacket) ? 1 : ((ep-> ++ sent_zlp) ? 1 : 0); ++ dma_desc->status.b.bytes = xfer_est; ++ } else { ++ if (maxxfer_local == ep->maxpacket) ++ dma_desc->status.b.bytes = xfer_est; ++ else ++ dma_desc->status.b.bytes = ++ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); ++ } ++ ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ } ++ ++ } else { ++ ++ if (ep->is_in) { ++ uint32_t soffn = fh_otg_get_frame_number(core_if); ++ ++ /** DMA Descriptor Setup */ ++ if (xfer_est > ep->maxxfer) { ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->status.b_iso_in.l = 0; ++ dma_desc->status.b_iso_in.ioc = 0; ++ dma_desc->status.b_iso_in.sp = 0; ++ dma_desc->status.b_iso_in.pid = 1; ++ dma_desc->status.b_iso_in.framenum = soffn; ++ dma_desc->status.b_iso_in.txbytes = ep->maxxfer; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ ++ xfer_est -= ep->maxxfer; ++ offset += ep->maxxfer; ++ } else { ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->status.b_iso_in.l = 1; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = 1; ++ dma_desc->status.b_iso_in.framenum = soffn ; ++ dma_desc->status.b_iso_in.sp = ++ (xfer_est % ep->maxpacket) ? 1 : ++ ((ep->sent_zlp) ? 1 : 0); ++ dma_desc->status.b_iso_in.txbytes = xfer_est; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ } ++ } else { ++ uint32_t soffn = fh_otg_get_frame_number(core_if); ++ ++ if (xfer_est > ep->maxxfer) { ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->status.b_iso_out.l = 0; ++ dma_desc->status.b_iso_out.ioc = 0; ++ /*dma_desc->status.b_iso_in.sp = 0;*/ ++ dma_desc->status.b_iso_out.pid = 1; ++ dma_desc->status.b_iso_out.framenum = soffn; ++ dma_desc->status.b_iso_out.rxbytes ++ = ep->maxxfer; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b_iso_out.bs = BS_HOST_READY; ++ ++ xfer_est -= ep->maxxfer; ++ offset += ep->maxxfer; ++ } else { ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->status.b_iso_out.l = 1; ++ dma_desc->status.b_iso_out.ioc = 1; ++ /*dma_desc->status.b_iso_in.sp = 0;*/ ++ dma_desc->status.b_iso_out.pid = 1; ++ dma_desc->status.b_iso_out.framenum = soffn; ++ dma_desc->status.b_iso_out.rxbytes = xfer_est; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b_iso_out.bs = BS_HOST_READY; ++ } ++ } ++ ++ } ++ /*FH_PRINTF("desc: %d:0x%08X:0x%08X\n", i, dma_desc->status, dma_desc->buf );*/ ++ dma_desc++; ++ } ++} ++ ++/** ++ * This function is called when to write ISOC data into appropriate dedicated ++ * periodic FIFO. ++ */ ++static int32_t write_isoc_tx_fifo(fh_otg_core_if_t * core_if, fh_ep_t * fh_ep) ++{ ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ fh_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ int epnum = fh_ep->num; ++ int dwords; ++ ++ FH_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = fh_ep->xfer_len - fh_ep->xfer_count; ++ ++ if (len > fh_ep->maxpacket) { ++ len = fh_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ fh_ep->xfer_count < fh_ep->xfer_len && fh_ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ fh_otg_ep_write_packet(core_if, fh_ep, 0); ++ ++ len = fh_ep->xfer_len - fh_ep->xfer_count; ++ if (len > fh_ep->maxpacket) { ++ len = fh_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void fh_otg_ep_start_transfer(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ FH_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, ++ ep->total_len); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ fh_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ gtxstatus.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { ++#ifdef DEBUG ++ FH_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = FH_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = FH_READ_REG32(&(in_regs->dieptsiz)); ++ ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? ++ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ ++ /* Zero Length Packet? */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count - 1 + ++ ep->maxpacket) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ } ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (ep->type != FH_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = 1; ++ FH_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ FH_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef FH_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ FH_WRITE_REG32(&in_regs->diepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ init_dma_desc_chain(core_if, ep); ++ /** DIEPDMAn Register write */ ++ FH_WRITE_REG32(&in_regs->diepdma, ++ ep->dma_desc_addr); ++#ifdef FH_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ FH_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ if (ep->type != FH_OTG_EP_TYPE_ISOC) { ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ FH_MODIFY_REG32 ++ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ ++ } ++ } ++ } ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ if (!core_if->dma_enable && ep->type == FH_OTG_EP_TYPE_ISOC) { ++ write_isoc_tx_fifo(core_if, ep); ++ } ++ ++ } else { ++ /* OUT endpoint */ ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = FH_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = FH_READ_REG32(&(out_regs->doeptsiz)); ++ ++ if (!core_if->dma_desc_enable) { ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len ++ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ } ++ ++ /* Program the transfer size and packet count as follows: ++ * ++ * pktcnt = N ++ * xfersize = N * maxpacket ++ */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ } ++ if (!core_if->dma_desc_enable) { ++ ep->xfer_len = ++ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ } ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", ++ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ FH_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ FH_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef FH_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ FH_WRITE_REG32(&out_regs->doepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ /** This is used for interrupt out transfers*/ ++ if (!ep->xfer_len) ++ ep->xfer_len = ep->total_len; ++ init_dma_desc_chain(core_if, ep); ++ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == FH_OTG_EP_TYPE_BULK) { ++ deptsiz.b.pktcnt = (ep->total_len + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = ep->total_len; ++ /* Remember initial value of doeptsiz */ ++ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; ++ FH_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ } ++ } ++ /** DOEPDMAn Register write */ ++ FH_WRITE_REG32(&out_regs->doepdma, ++ ep->dma_desc_addr); ++#ifdef FH_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ FH_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ if (ep->type == FH_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0 }; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ FH_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ FH_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ FH_READ_REG32(&out_regs->doepctl), ++ FH_READ_REG32(&out_regs->doeptsiz)); ++ FH_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ FH_READ_REG32(&core_if->core_global_regs-> ++ gintmsk)); ++ ++ /* Timer is scheduling only for out bulk transfers for ++ * "Device DDMA OUT NAK Enhancement" feature to inform user ++ * about received data payload in case of timeout ++ */ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == FH_OTG_EP_TYPE_BULK) { ++ core_if->ep_xfer_info[ep->num].core_if = core_if; ++ core_if->ep_xfer_info[ep->num].ep = ep; ++ core_if->ep_xfer_info[ep->num].state = 1; ++ ++ /* Start a timer for this transfer. */ ++ FH_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); ++ } ++ } ++ } ++} ++ ++/** ++ * This function setup a zero length transfer in Buffer DMA and ++ * Slave modes for usb requests with zero field set ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void fh_otg_ep_start_zl_transfer(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ FH_PRINTF("zero length transfer is called\n"); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ fh_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ depctl.d32 = FH_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = FH_READ_REG32(&(in_regs->dieptsiz)); ++ ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.mc = 1; ++ FH_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ FH_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ FH_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ FH_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = FH_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = FH_READ_REG32(&(out_regs->doeptsiz)); ++ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ FH_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ FH_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ FH_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ FH_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for EP0 and starts ++ * the transfer. For an IN transfer, the packets will be loaded into ++ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are ++ * unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP0 data. ++ */ ++void fh_otg_ep0_start_transfer(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ ++ FH_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p \n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ ep->total_len = ep->xfer_len; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ fh_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ depctl.d32 = FH_READ_REG32(&in_regs->diepctl); ++ if (depctl.b.epena) ++ return; ++ } ++ ++ gtxstatus.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ /* If dedicated FIFO every time flush fifo before enable ep*/ ++ if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a) ++ fh_otg_flush_tx_fifo(core_if, ep->tx_fifo_num); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 ++ && !core_if->dma_enable) { ++#ifdef DEBUG ++ deptsiz.d32 = FH_READ_REG32(&in_regs->dieptsiz); ++ FH_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", ++ FH_READ_REG32(&in_regs->diepctl)); ++ FH_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", ++ deptsiz.d32, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ FH_PRINTF("TX Queue or FIFO Full (0x%0x)\n", ++ gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = FH_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = FH_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ if (ep->xfer_len > ep->maxpacket) { ++ ep->xfer_len = ep->maxpacket; ++ deptsiz.b.xfersize = ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = ep->xfer_len; ++ } ++ deptsiz.b.pktcnt = 1; ++ ++ } ++ FH_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ FH_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ ++ FH_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ FH_WRITE_REG32(&in_regs->diepdma, ++ core_if-> ++ dev_if->dma_in_desc_addr); ++ } ++ } else { ++ FH_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ // Unexpected Back-to-Back SETUP Interrupt Issue: ++ // RxFIFO thresholding enabled: thr_ctl >= 4, ++ // Control IN EP in status or data stage, ++ // Affected versions v3.00a, v3.10a & v3.20a ++ if ((core_if->core_params->thr_ctl & 4) && (ep->is_in) && ++ ((core_if->snpsid == OTG_CORE_REV_3_00a) || ++ (core_if->snpsid == OTG_CORE_REV_3_10a) || ++ (core_if->snpsid == OTG_CORE_REV_3_20a))) { ++ ++ int j = 0; ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintmsk = {.d32 = 0}; ++ gintsts_data_t gintsts = {.d32 = 0}; ++ ++ gintmsk.d32 = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ if (gintmsk.b.goutnakeff) { ++ gintmsk.b.goutnakeff = 0; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ gintmsk.b.goutnakeff = 1; // restore initial value of gintmsk.b.goutnakeff ++ } ++ ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgoutnak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ j = 0; ++ do { ++ j++; ++ fh_udelay(100); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ FH_ERROR("GOUTNAKEFF is not set during 10s\n"); ++ break; ++ } ++ } while (!gintsts.b.goutnakeff); // while not set ++ ++ dctl.b.cgoutnak = 1; ++ dctl.b.sgoutnak = 0; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ j = 0; ++ do { ++ j++; ++ fh_udelay(100); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (j == 100000) { ++ FH_ERROR("GOUTNAKEFF is not cleared during 10s\n"); ++ break; ++ } ++ } while (gintsts.b.goutnakeff); // while not cleared ++ ++ // restore saved gintmsk ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ } ++ // END of WA for Unexpected Back-to-Back SETUP Interrupt Issue ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ FH_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ /* OUT endpoint */ ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = FH_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = FH_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count as follows: ++ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) ++ * pktcnt = N */ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ deptsiz.b.supcnt = 3; ++ ++ FH_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ FH_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ FH_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.mtrf = 0; ++ dma_desc->status.b.sr = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ FH_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if-> ++ dma_out_desc_addr); ++ } ++ } else { ++ FH_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&(out_regs->doepctl), depctl.d32); ++ } ++} ++ ++/** ++ * This function continues control IN transfers started by ++ * fh_otg_ep0_start_transfer, when the transfer does not fit in a ++ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one ++ * bit for the packet count. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP0 data. ++ */ ++void fh_otg_ep0_continue_transfer(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ ++ if (ep->is_in == 1) { ++ fh_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ gnptxsts_data_t tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ /** @todo Should there be check for room in the Tx ++ * Status Queue. If not remove the code above this comment. */ ++ ++ depctl.d32 = FH_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = FH_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.xfersize = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ deptsiz.b.pktcnt = 1; ++ if (core_if->dma_enable == 0) { ++ ep->xfer_len += deptsiz.b.xfersize; ++ } else { ++ ep->xfer_len = deptsiz.b.xfersize; ++ } ++ FH_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } else { ++ ep->xfer_len = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ FH_WRITE_REG32(&in_regs->diepdma, ++ core_if->dev_if->dma_in_desc_addr); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == FH_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ FH_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ FH_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = FH_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = FH_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_desc_enable == 0) { ++ FH_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ FH_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if->dma_out_desc_addr); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == FH_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ FH_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ FH_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++#ifdef DEBUG ++void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ start = 0; ++ while (length > 0) { ++ num = length < 16u ? length : 16u; ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ FH_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ FH_PRINTF("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function writes a packet into the Tx FIFO associated with the ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * periodic EPs the periodic Tx FIFO associated with the EP is written ++ * with all packets for the next micro-frame. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to write packet for. ++ * @param dma Indicates if DMA is being used. ++ */ ++void fh_otg_ep_write_packet(fh_otg_core_if_t * core_if, fh_ep_t * ep, ++ int dma) ++{ ++ /** ++ * The buffer is padded to DWORD on a per packet basis in ++ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * packet, if short, is also padded to a multiple of DWORD. ++ * ++ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * multiple of DWORD in length ++ * ++ * ep->xfer_len can be any number of bytes ++ * ++ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * packet ++ * ++ * FIFO access is DWORD */ ++ ++ uint32_t i; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ uint32_t *fifo; ++ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; ++ ++ FH_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if, ++ ep); ++ if (ep->xfer_count >= ep->xfer_len) { ++ FH_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); ++ return; ++ } ++ ++ /* Find the byte length of the packet either short packet or MPS */ ++ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) { ++ byte_count = ep->xfer_len - ep->xfer_count; ++ } else { ++ byte_count = ep->maxpacket; ++ } ++ ++ /* Find the DWORD length, padded by extra bytes as neccessary if MPS ++ * is not a multiple of DWORD */ ++ dword_count = (byte_count + 3) / 4; ++ ++#ifdef VERBOSE ++ dump_msg(ep->xfer_buff, byte_count); ++#endif ++ ++ /**@todo NGS Where are the Periodic Tx FIFO addresses ++ * intialized? What should this be? */ ++ ++ fifo = core_if->data_fifo[ep->num]; ++ ++ FH_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", ++ fifo, data_buff, *data_buff, byte_count); ++ ++ if (!dma) { ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ FH_WRITE_REG32(fifo, *data_buff); ++ } ++ } ++ ++ ep->xfer_count += byte_count; ++ ep->xfer_buff += byte_count; ++ ep->dma_addr += byte_count; ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to set the stall on. ++ */ ++void fh_otg_ep_set_stall(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ FH_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ depctl.d32 = FH_READ_REG32(depctl_addr); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ FH_WRITE_REG32(depctl_addr, depctl.d32); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ depctl.d32 = FH_READ_REG32(depctl_addr); ++ ++ /* set the stall bit */ ++ depctl.b.stall = 1; ++ FH_WRITE_REG32(depctl_addr, depctl.d32); ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", FH_READ_REG32(depctl_addr)); ++ ++ return; ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to clear stall from. ++ */ ++void fh_otg_ep_clear_stall(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ FH_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ } ++ ++ depctl.d32 = FH_READ_REG32(depctl_addr); ++ ++ /* clear the stall bits */ ++ depctl.b.stall = 0; ++ ++ /* ++ * USB Spec 9.4.5: For endpoints using data toggle, regardless ++ * of whether an endpoint has the Halt feature set, a ++ * ClearFeature(ENDPOINT_HALT) request always results in the ++ * data toggle being reinitialized to DATA0. ++ */ ++ if (ep->type == FH_OTG_EP_TYPE_INTR || ++ ep->type == FH_OTG_EP_TYPE_BULK) { ++ depctl.b.setd0pid = 1; /* DATA0 */ ++ } ++ ++ FH_WRITE_REG32(depctl_addr, depctl.d32); ++ FH_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", FH_READ_REG32(depctl_addr)); ++ return; ++} ++ ++/** ++ * This function reads a packet from the Rx FIFO into the destination ++ * buffer. To read SETUP data use fh_otg_read_setup_packet. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param dest Destination buffer for the packet. ++ * @param bytes Number of bytes to copy to the destination. ++ */ ++void fh_otg_read_packet(fh_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes) ++{ ++ int i; ++ int word_count = (bytes + 3) / 4; ++ ++ volatile uint32_t *fifo = core_if->data_fifo[0]; ++ uint32_t *data_buff = (uint32_t *) dest; ++ ++ /** ++ * @todo Account for the case where _dest is not dword aligned. This ++ * requires reading data from the FIFO into a uint32_t temp buffer, ++ * then moving it into the data buffer. ++ */ ++ ++ FH_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, ++ core_if, dest, bytes); ++ ++ for (i = 0; i < word_count; i++, data_buff++) { ++ *data_buff = FH_READ_REG32(fifo); ++ } ++ ++ return; ++} ++ ++/** ++ * This functions reads the device registers and prints them ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_dump_dev_registers(fh_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ FH_PRINTF("Device Global Registers\n"); ++ addr = &core_if->dev_if->dev_global_regs->dcfg; ++ FH_PRINTF("DCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dctl; ++ FH_PRINTF("DCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dsts; ++ FH_PRINTF("DSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->diepmsk; ++ FH_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->doepmsk; ++ FH_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daint; ++ FH_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daintmsk; ++ FH_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr1; ++ FH_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr2; ++ FH_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbusdis; ++ FH_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; ++ FH_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; ++ FH_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ FH_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ FH_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.multi_proc_int) { ++ ++ addr = &core_if->dev_if->dev_global_regs->deachint; ++ FH_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->deachintmsk; ++ FH_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->diepeachintmsk[i]; ++ FH_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->doepeachintmsk[i]; ++ FH_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ } ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_PRINTF("Device IN EP %d Registers\n", i); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; ++ FH_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepint; ++ FH_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; ++ FH_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; ++ FH_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; ++ FH_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; ++ FH_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, 0 /*FH_READ_REG32(addr) */ ); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ FH_PRINTF("Device OUT EP %d Registers\n", i); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; ++ FH_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepint; ++ FH_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; ++ FH_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; ++ FH_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; ++ FH_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ ++ } ++} ++ ++/** ++ * This functions reads the SPRAM and prints its content ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_dump_spram(fh_otg_core_if_t * core_if) ++{ ++ volatile uint8_t *addr, *start_addr, *end_addr; ++ ++ FH_PRINTF("SPRAM Data:\n"); ++ start_addr = (void *)core_if->core_global_regs; ++ FH_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); ++ start_addr += 0x00028000; ++ end_addr = (void *)core_if->core_global_regs; ++ end_addr += 0x000280e0; ++ ++ for (addr = start_addr; addr < end_addr; addr += 16) { ++ FH_PRINTF ++ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", ++ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], ++ addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], ++ addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] ++ ); ++ } ++ ++ return; ++} ++ ++/** ++ * This function reads the host registers and prints them ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_dump_host_registers(fh_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ FH_PRINTF("Host Global Registers\n"); ++ addr = &core_if->host_if->host_global_regs->hcfg; ++ FH_PRINTF("HCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfir; ++ FH_PRINTF("HFIR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfnum; ++ FH_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hptxsts; ++ FH_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haint; ++ FH_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haintmsk; ++ FH_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->host_global_regs->hflbaddr; ++ FH_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ ++ addr = core_if->host_if->hprt0; ++ FH_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ FH_PRINTF("Host Channel %d Specific Registers\n", i); ++ addr = &core_if->host_if->hc_regs[i]->hcchar; ++ FH_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcsplt; ++ FH_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcint; ++ FH_PRINTF("HCINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcintmsk; ++ FH_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hctsiz; ++ FH_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcdma; ++ FH_PRINTF("HCDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->hc_regs[i]->hcdmab; ++ FH_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ ++ } ++ return; ++} ++ ++/** ++ * This function reads the core global registers and prints them ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_dump_global_registers(fh_otg_core_if_t * core_if) ++{ ++ int i, ep_num; ++ volatile uint32_t *addr; ++ char *txfsiz; ++ ++ FH_PRINTF("Core Global Registers\n"); ++ addr = &core_if->core_global_regs->gotgctl; ++ FH_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gotgint; ++ FH_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gahbcfg; ++ FH_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gusbcfg; ++ FH_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grstctl; ++ FH_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintsts; ++ FH_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintmsk; ++ FH_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxstsr; ++ FH_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxfsiz; ++ FH_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxfsiz; ++ FH_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxsts; ++ FH_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gi2cctl; ++ FH_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpvndctl; ++ FH_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ggpio; ++ FH_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->guid; ++ FH_PRINTF("GUID @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gsnpsid; ++ FH_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg1; ++ FH_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg2; ++ FH_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg3; ++ FH_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg4; ++ FH_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->glpmcfg; ++ FH_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpwrdn; ++ FH_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gdfifocfg; ++ FH_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->adpctl; ++ FH_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ fh_otg_adp_read_reg(core_if)); ++ addr = &core_if->core_global_regs->hptxfsiz; ++ FH_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ txfsiz = "DPTXFSIZ"; ++ } else { ++ ep_num = core_if->hwcfg4.b.num_in_eps; ++ txfsiz = "DIENPTXF"; ++ } ++ for (i = 0; i < ep_num; i++) { ++ addr = &core_if->core_global_regs->dtxfsiz[i]; ++ FH_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, ++ (unsigned long)addr, FH_READ_REG32(addr)); ++ } ++ addr = core_if->pcgcctl; ++ FH_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ FH_READ_REG32(addr)); ++} ++ ++/** ++ * Flush a Tx FIFO. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param num Tx FIFO to flush. ++ */ ++void fh_otg_flush_tx_fifo(fh_otg_core_if_t * core_if, const int num) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ FH_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num); ++ ++ greset.b.txfflsh = 1; ++ greset.b.txfnum = num; ++ FH_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = FH_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ FH_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", ++ __func__, greset.d32, ++ FH_READ_REG32(&global_regs->gnptxsts)); ++ break; ++ } ++ fh_udelay(1); ++ } while (greset.b.txfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ fh_udelay(1); ++} ++ ++/** ++ * Flush Rx FIFO. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++void fh_otg_flush_rx_fifo(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ FH_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); ++ /* ++ * ++ */ ++ greset.b.rxfflsh = 1; ++ FH_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ ++ do { ++ greset.d32 = FH_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ FH_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ break; ++ } ++ fh_udelay(1); ++ } while (greset.b.rxfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ fh_udelay(1); ++} ++ ++/** ++ * Do core a soft reset of the core. Be careful with this because it ++ * resets all the internal state machines of the core. ++ */ ++void fh_otg_core_reset(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ volatile grstctl_t greset = {.d32 = 0 }; ++ int count = 0; ++ ++ FH_DEBUGPL(DBG_CILV, "%s\n", __func__); ++ /* Wait for AHB master IDLE state. */ ++ do { ++ fh_udelay(10); ++ greset.d32 = FH_READ_REG32(&global_regs->grstctl); ++ if (++count > 100000) { ++ FH_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ return; ++ } ++ } ++ while (greset.b.ahbidle == 0); ++ ++ /* Core Soft Reset */ ++ count = 0; ++ greset.b.csftrst = 1; ++ FH_WRITE_REG32(&global_regs->grstctl, greset.d32); ++ do { ++ greset.d32 = FH_READ_REG32(&global_regs->grstctl); ++ if (++count > 10000) { ++ FH_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", ++ __func__, greset.d32); ++ break; ++ } ++ fh_udelay(1); ++ } ++ while (greset.b.csftrst == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ fh_mdelay(100); ++} ++ ++uint8_t fh_otg_is_device_mode(fh_otg_core_if_t * _core_if) ++{ ++ return (fh_otg_mode(_core_if) != FH_HOST_MODE); ++} ++ ++uint8_t fh_otg_is_host_mode(fh_otg_core_if_t * _core_if) ++{ ++ return (fh_otg_mode(_core_if) == FH_HOST_MODE); ++} ++ ++/** ++ * Register HCD callbacks. The callbacks are used to start and stop ++ * the HCD for interrupt processing. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param cb the HCD callback structure. ++ * @param p pointer to be passed to callback function (usb_hcd*). ++ */ ++void fh_otg_cil_register_hcd_callbacks(fh_otg_core_if_t * core_if, ++ fh_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->hcd_cb = cb; ++ cb->p = p; ++} ++ ++/** ++ * Register PCD callbacks. The callbacks are used to start and stop ++ * the PCD for interrupt processing. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param cb the PCD callback structure. ++ * @param p pointer to be passed to callback function (pcd*). ++ */ ++void fh_otg_cil_register_pcd_callbacks(fh_otg_core_if_t * core_if, ++ fh_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->pcd_cb = cb; ++ cb->p = p; ++} ++ ++#ifdef FH_EN_ISOC ++ ++/** ++ * This function writes isoc data per 1 (micro)frame into tx fifo ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void write_isoc_frame_data(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ fh_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ uint32_t dwords; ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ++ ep_regs = core_if->dev_if->in_ep_regs[ep->num]; ++ ++ len = ep->xfer_len - ep->xfer_count; ++ ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ fh_otg_ep_write_packet(core_if, ep, 0); ++ ++ len = ep->xfer_len - ep->xfer_count; ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, ++ txstatus.d32); ++ } ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void fh_otg_iso_ep_start_frm_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ep->cur_pkt_addr; ++ ep->dma_addr = ep->cur_pkt_dma_addr; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ FH_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ } ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ FH_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); ++ ++ if (core_if->dma_enable) { ++ FH_WRITE_REG32(& ++ (core_if->dev_if-> ++ out_ep_regs[ep->num]->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } ++ ++ /** Enable endpoint, clear nak */ ++ ++ depctl.d32 = 0; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ep->next_frame = dsts.b.soffn + ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } else { ++ ep->next_frame += ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ FH_MODIFY_REG32(addr, 0, depctl.d32); ++ depctl.d32 = FH_READ_REG32(addr); ++ ++ if (ep->is_in && core_if->dma_enable == 0) { ++ write_isoc_frame_data(core_if, ep); ++ } ++ ++} ++#endif /* FH_EN_ISOC */ ++ ++static void fh_otg_set_uninitialized(int32_t * p, int size) ++{ ++ int i; ++ for (i = 0; i < size; i++) { ++ p[i] = -1; ++ } ++} ++ ++static int fh_otg_param_initialized(int32_t val) ++{ ++ return val != -1; ++} ++ ++static int fh_otg_setup_params(fh_otg_core_if_t * core_if) ++{ ++ int i; ++ gintsts_data_t gintsts; ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ core_if->core_params = FH_ALLOC(sizeof(*core_if->core_params)); ++ if (!core_if->core_params) { ++ return -FH_E_NO_MEMORY; ++ } ++ fh_otg_set_uninitialized((int32_t *) core_if->core_params, ++ sizeof(*core_if->core_params) / ++ sizeof(int32_t)); ++ FH_PRINTF("Setting default values for core params\n"); ++ fh_otg_set_param_otg_cap(core_if, fh_param_otg_cap_default); ++ fh_otg_set_param_dma_enable(core_if, fh_param_dma_enable_default); ++ fh_otg_set_param_dma_desc_enable(core_if, ++ fh_param_dma_desc_enable_default); ++ fh_otg_set_param_opt(core_if, fh_param_opt_default); ++ fh_otg_set_param_dma_burst_size(core_if, ++ fh_param_dma_burst_size_default); ++ fh_otg_set_param_host_support_fs_ls_low_power(core_if, ++ fh_param_host_support_fs_ls_low_power_default); ++ fh_otg_set_param_enable_dynamic_fifo(core_if, ++ fh_param_enable_dynamic_fifo_default); ++ fh_otg_set_param_data_fifo_size(core_if, ++ fh_param_data_fifo_size_default); ++ fh_otg_set_param_dev_rx_fifo_size(core_if, ++ fh_param_dev_rx_fifo_size_default); ++ fh_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ fh_param_dev_nperio_tx_fifo_size_default); ++ fh_otg_set_param_host_rx_fifo_size(core_if, ++ fh_param_host_rx_fifo_size_default); ++ fh_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ fh_param_host_nperio_tx_fifo_size_default); ++ fh_otg_set_param_host_perio_tx_fifo_size(core_if, ++ fh_param_host_perio_tx_fifo_size_default); ++ fh_otg_set_param_max_transfer_size(core_if, ++ fh_param_max_transfer_size_default); ++ fh_otg_set_param_max_packet_count(core_if, ++ fh_param_max_packet_count_default); ++ fh_otg_set_param_host_channels(core_if, ++ fh_param_host_channels_default); ++ fh_otg_set_param_dev_endpoints(core_if, ++ fh_param_dev_endpoints_default); ++ fh_otg_set_param_phy_type(core_if, fh_param_phy_type_default); ++ fh_otg_set_param_speed(core_if, fh_param_speed_default); ++ fh_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ fh_param_host_ls_low_power_phy_clk_default); ++ fh_otg_set_param_phy_ulpi_ddr(core_if, fh_param_phy_ulpi_ddr_default); ++ fh_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ fh_param_phy_ulpi_ext_vbus_default); ++ fh_otg_set_param_phy_utmi_width(core_if, ++ fh_param_phy_utmi_width_default); ++ fh_otg_set_param_ts_dline(core_if, fh_param_ts_dline_default); ++ fh_otg_set_param_i2c_enable(core_if, fh_param_i2c_enable_default); ++ fh_otg_set_param_ulpi_fs_ls(core_if, fh_param_ulpi_fs_ls_default); ++ fh_otg_set_param_en_multiple_tx_fifo(core_if, ++ fh_param_en_multiple_tx_fifo_default); ++ ++ if (gintsts.b.curmode) { ++ /* Force device mode to get power-on values of device FIFOs */ ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ fh_mdelay(100); ++ for (i = 0; i < 15; i++) { ++ fh_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ fh_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ fh_otg_set_param_dev_tx_fifo_size(core_if, ++ fh_param_dev_tx_fifo_size_default, i); ++ } ++ gusbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_dev_mode = 0; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ fh_mdelay(100); ++ } else { ++ for (i = 0; i < 15; i++) { ++ fh_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ fh_param_dev_perio_tx_fifo_size_default, i); ++ } ++ for (i = 0; i < 15; i++) { ++ fh_otg_set_param_dev_tx_fifo_size(core_if, ++ fh_param_dev_tx_fifo_size_default, i); ++ } ++ } ++ ++ fh_otg_set_param_thr_ctl(core_if, fh_param_thr_ctl_default); ++ fh_otg_set_param_mpi_enable(core_if, fh_param_mpi_enable_default); ++ fh_otg_set_param_pti_enable(core_if, fh_param_pti_enable_default); ++ fh_otg_set_param_lpm_enable(core_if, fh_param_lpm_enable_default); ++ ++ fh_otg_set_param_besl_enable(core_if, fh_param_besl_enable_default); ++ fh_otg_set_param_baseline_besl(core_if, fh_param_baseline_besl_default); ++ fh_otg_set_param_deep_besl(core_if, fh_param_deep_besl_default); ++ ++ fh_otg_set_param_ic_usb_cap(core_if, fh_param_ic_usb_cap_default); ++ fh_otg_set_param_tx_thr_length(core_if, ++ fh_param_tx_thr_length_default); ++ fh_otg_set_param_rx_thr_length(core_if, ++ fh_param_rx_thr_length_default); ++ fh_otg_set_param_ahb_thr_ratio(core_if, ++ fh_param_ahb_thr_ratio_default); ++ fh_otg_set_param_power_down(core_if, fh_param_power_down_default); ++ fh_otg_set_param_reload_ctl(core_if, fh_param_reload_ctl_default); ++ fh_otg_set_param_dev_out_nak(core_if, fh_param_dev_out_nak_default); ++ fh_otg_set_param_cont_on_bna(core_if, fh_param_cont_on_bna_default); ++ fh_otg_set_param_ahb_single(core_if, fh_param_ahb_single_default); ++ fh_otg_set_param_otg_ver(core_if, fh_param_otg_ver_default); ++ fh_otg_set_param_adp_enable(core_if, fh_param_adp_enable_default); ++ return 0; ++} ++ ++uint8_t fh_otg_is_dma_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->dma_enable; ++} ++ ++/* Checks if the parameter is outside of its valid range of values */ ++#define FH_OTG_PARAM_TEST(_param_, _low_, _high_) \ ++ (((_param_) < (_low_)) || \ ++ ((_param_) > (_high_))) ++ ++/* Parameter access functions */ ++int fh_otg_set_param_otg_cap(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int valid; ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 2)) { ++ FH_WARN("Wrong value for otg_cap parameter\n"); ++ FH_WARN("otg_cap parameter must be 0,1 or 2\n"); ++ retval = -FH_E_INVALID; ++ goto out; ++ } ++ ++ valid = 1; ++ switch (val) { ++ case FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE: ++ if (core_if->hwcfg2.b.op_mode != ++ FH_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ valid = 0; ++ break; ++ case FH_OTG_CAP_PARAM_SRP_ONLY_CAPABLE: ++ if ((core_if->hwcfg2.b.op_mode != ++ FH_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ FH_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ && (core_if->hwcfg2.b.op_mode != ++ FH_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ && (core_if->hwcfg2.b.op_mode != ++ FH_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { ++ valid = 0; ++ } ++ break; ++ case FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE: ++ /* always valid */ ++ break; ++ } ++ if (!valid) { ++ if (fh_otg_param_initialized(core_if->core_params->otg_cap)) { ++ FH_ERROR ++ ("%d invalid for otg_cap paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (((core_if->hwcfg2.b.op_mode == ++ FH_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ FH_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (core_if->hwcfg2.b.op_mode == ++ FH_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE) ++ || (core_if->hwcfg2.b.op_mode == ++ FH_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ? ++ FH_OTG_CAP_PARAM_SRP_ONLY_CAPABLE : ++ FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->otg_cap = val; ++out: ++ return retval; ++} ++ ++int32_t fh_otg_get_param_otg_cap(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_cap; ++} ++ ++int fh_otg_set_param_opt(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for opt parameter\n"); ++ return -FH_E_INVALID; ++ } ++ core_if->core_params->opt = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_opt(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->opt; ++} ++ ++int fh_otg_set_param_dma_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for dma enable\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) { ++ if (fh_otg_param_initialized(core_if->core_params->dma_enable)) { ++ FH_ERROR ++ ("%d invalid for dma_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->dma_enable = val; ++ if (val == 0) { ++ fh_otg_set_param_dma_desc_enable(core_if, 0); ++ } ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dma_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_enable; ++} ++ ++int fh_otg_set_param_dma_desc_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for dma_enable\n"); ++ FH_WARN("dma_desc_enable must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) ++ && ((fh_otg_get_param_dma_enable(core_if) == 0) ++ || (core_if->hwcfg4.b.desc_dma == 0))) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->dma_desc_enable)) { ++ FH_ERROR ++ ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ core_if->core_params->dma_desc_enable = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dma_desc_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_desc_enable; ++} ++ ++int fh_otg_set_param_host_support_fs_ls_low_power(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for host_support_fs_low_power\n"); ++ FH_WARN("host_support_fs_low_power must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ core_if->core_params->host_support_fs_ls_low_power = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_host_support_fs_ls_low_power(fh_otg_core_if_t * ++ core_if) ++{ ++ return core_if->core_params->host_support_fs_ls_low_power; ++} ++ ++int fh_otg_set_param_enable_dynamic_fifo(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for enable_dynamic_fifo\n"); ++ FH_WARN("enable_dynamic_fifo must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->enable_dynamic_fifo)) { ++ FH_ERROR ++ ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ core_if->core_params->enable_dynamic_fifo = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_enable_dynamic_fifo(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->enable_dynamic_fifo; ++} ++ ++int fh_otg_set_param_data_fifo_size(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 32, 32768)) { ++ FH_WARN("Wrong value for data_fifo_size\n"); ++ FH_WARN("data_fifo_size must be 32-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > core_if->hwcfg3.b.dfifo_depth) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->data_fifo_size)) { ++ FH_ERROR ++ ("%d invalid for data_fifo_size parameter. Check HW configuration.%d\n", ++ val, core_if->hwcfg3.b.dfifo_depth); ++ } ++ val = core_if->hwcfg3.b.dfifo_depth; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->data_fifo_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_data_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->data_fifo_size; ++} ++ ++int fh_otg_set_param_dev_rx_fifo_size(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for dev_rx_fifo_size\n"); ++ FH_WARN("dev_rx_fifo_size must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > FH_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->dev_rx_fifo_size)) { ++ FH_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); ++ } ++ val = FH_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->dev_rx_fifo_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_rx_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_rx_fifo_size; ++} ++ ++int fh_otg_set_param_dev_nperio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for dev_nperio_tx_fifo\n"); ++ FH_WARN("dev_nperio_tx_fifo must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > (FH_READ_REG32 ++ (&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->dev_nperio_tx_fifo_size)) { ++ FH_ERROR ++ ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (FH_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->dev_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_nperio_tx_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_nperio_tx_fifo_size; ++} ++ ++int fh_otg_set_param_host_rx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for host_rx_fifo_size\n"); ++ FH_WARN("host_rx_fifo_size must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > FH_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->host_rx_fifo_size)) { ++ FH_ERROR ++ ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = FH_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->host_rx_fifo_size = val; ++ return retval; ++ ++} ++ ++int32_t fh_otg_get_param_host_rx_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_rx_fifo_size; ++} ++ ++int fh_otg_set_param_host_nperio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for host_nperio_tx_fifo_size\n"); ++ FH_WARN("host_nperio_tx_fifo_size must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > (FH_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->host_nperio_tx_fifo_size)) { ++ FH_ERROR ++ ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (FH_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> ++ 16); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->host_nperio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_host_nperio_tx_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_nperio_tx_fifo_size; ++} ++ ++int fh_otg_set_param_host_perio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for host_perio_tx_fifo_size\n"); ++ FH_WARN("host_perio_tx_fifo_size must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > ((core_if->hptxfsiz.d32) >> 16)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->host_perio_tx_fifo_size)) { ++ FH_ERROR ++ ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = (core_if->hptxfsiz.d32) >> 16; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->host_perio_tx_fifo_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_host_perio_tx_fifo_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_perio_tx_fifo_size; ++} ++ ++int fh_otg_set_param_max_transfer_size(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 2047, 524288)) { ++ FH_WARN("Wrong value for max_transfer_size\n"); ++ FH_WARN("max_transfer_size must be 2047-524288\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->max_transfer_size)) { ++ FH_ERROR ++ ("%d invalid for max_transfer_size. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) - ++ 1); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->max_transfer_size = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_max_transfer_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_transfer_size; ++} ++ ++int fh_otg_set_param_max_packet_count(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 15, 511)) { ++ FH_WARN("Wrong value for max_packet_count\n"); ++ FH_WARN("max_packet_count must be 15-511\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->max_packet_count)) { ++ FH_ERROR ++ ("%d invalid for max_packet_count. Check HW configuration.\n", ++ val); ++ } ++ val = ++ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->max_packet_count = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_max_packet_count(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->max_packet_count; ++} ++ ++int fh_otg_set_param_host_channels(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 1, 16)) { ++ FH_WARN("Wrong value for host_channels\n"); ++ FH_WARN("host_channels must be 1-16\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->host_channels)) { ++ FH_ERROR ++ ("%d invalid for host_channels. Check HW configurations.\n", ++ val); ++ } ++ val = (core_if->hwcfg2.b.num_host_chan + 1); ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->host_channels = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_host_channels(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_channels; ++} ++ ++int fh_otg_set_param_dev_endpoints(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 1, 15)) { ++ FH_WARN("Wrong value for dev_endpoints\n"); ++ FH_WARN("dev_endpoints must be 1-15\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_dev_ep)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->dev_endpoints)) { ++ FH_ERROR ++ ("%d invalid for dev_endpoints. Check HW configurations.\n", ++ val); ++ } ++ val = core_if->hwcfg2.b.num_dev_ep; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->dev_endpoints = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_endpoints(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_endpoints; ++} ++ ++int fh_otg_set_param_phy_type(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 2)) { ++ FH_WARN("Wrong value for phy_type\n"); ++ FH_WARN("phy_type must be 0,1 or 2\n"); ++ return -FH_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECKS ++ if ((val == FH_PHY_TYPE_PARAM_UTMI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 1) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == FH_PHY_TYPE_PARAM_ULPI) && ++ ((core_if->hwcfg2.b.hs_phy_type == 2) || ++ (core_if->hwcfg2.b.hs_phy_type == 3))) { ++ valid = 1; ++ } else if ((val == FH_PHY_TYPE_PARAM_FS) && ++ (core_if->hwcfg2.b.fs_phy_type == 1)) { ++ valid = 1; ++ } ++ if (!valid) { ++ if (fh_otg_param_initialized(core_if->core_params->phy_type)) { ++ FH_ERROR ++ ("%d invalid for phy_type. Check HW configurations.\n", ++ val); ++ } ++ if (core_if->hwcfg2.b.hs_phy_type) { ++ if ((core_if->hwcfg2.b.hs_phy_type == 3) || ++ (core_if->hwcfg2.b.hs_phy_type == 1)) { ++ val = FH_PHY_TYPE_PARAM_UTMI; ++ } else { ++ val = FH_PHY_TYPE_PARAM_ULPI; ++ } ++ } ++ retval = -FH_E_INVALID; ++ } ++#endif ++ core_if->core_params->phy_type = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_phy_type(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_type; ++} ++ ++int fh_otg_set_param_speed(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for speed parameter\n"); ++ FH_WARN("max_speed parameter must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ if ((val == 0) ++ && fh_otg_get_param_phy_type(core_if) == FH_PHY_TYPE_PARAM_FS) { ++ if (fh_otg_param_initialized(core_if->core_params->speed)) { ++ FH_ERROR ++ ("%d invalid for speed paremter. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (fh_otg_get_param_phy_type(core_if) == ++ FH_PHY_TYPE_PARAM_FS ? 1 : 0); ++ retval = -FH_E_INVALID; ++ } ++ core_if->core_params->speed = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_speed(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->speed; ++} ++ ++int fh_otg_set_param_host_ls_low_power_phy_clk(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN ++ ("Wrong value for host_ls_low_power_phy_clk parameter\n"); ++ FH_WARN("host_ls_low_power_phy_clk must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ) ++ && (fh_otg_get_param_phy_type(core_if) == FH_PHY_TYPE_PARAM_FS)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->host_ls_low_power_phy_clk)) { ++ FH_ERROR ++ ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", ++ val); ++ } ++ val = ++ (fh_otg_get_param_phy_type(core_if) == ++ FH_PHY_TYPE_PARAM_FS) ? ++ FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ : ++ FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->host_ls_low_power_phy_clk = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_host_ls_low_power_phy_clk(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->host_ls_low_power_phy_clk; ++} ++ ++int fh_otg_set_param_phy_ulpi_ddr(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for phy_ulpi_ddr\n"); ++ FH_WARN("phy_upli_ddr must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ddr = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_phy_ulpi_ddr(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ddr; ++} ++ ++int fh_otg_set_param_phy_ulpi_ext_vbus(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong valaue for phy_ulpi_ext_vbus\n"); ++ FH_WARN("phy_ulpi_ext_vbus must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->phy_ulpi_ext_vbus = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_phy_ulpi_ext_vbus(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_ulpi_ext_vbus; ++} ++ ++int fh_otg_set_param_phy_utmi_width(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 8, 8) && FH_OTG_PARAM_TEST(val, 16, 16)) { ++ FH_WARN("Wrong valaue for phy_utmi_width\n"); ++ FH_WARN("phy_utmi_width must be 8 or 16\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->phy_utmi_width = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_phy_utmi_width(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->phy_utmi_width; ++} ++ ++int fh_otg_set_param_ulpi_fs_ls(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong valaue for ulpi_fs_ls\n"); ++ FH_WARN("ulpi_fs_ls must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->ulpi_fs_ls = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_ulpi_fs_ls(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ulpi_fs_ls; ++} ++ ++int fh_otg_set_param_ts_dline(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong valaue for ts_dline\n"); ++ FH_WARN("ts_dline must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->ts_dline = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_ts_dline(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ts_dline; ++} ++ ++int fh_otg_set_param_i2c_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong valaue for i2c_enable\n"); ++ FH_WARN("i2c_enable must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++#ifndef NO_FS_PHY_HW_CHECK ++ if (val == 1 && core_if->hwcfg3.b.i2c == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->i2c_enable)) { ++ FH_ERROR ++ ("%d invalid for i2c_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++#endif ++ ++ core_if->core_params->i2c_enable = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_i2c_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->i2c_enable; ++} ++ ++int fh_otg_set_param_dev_perio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val, int fifo_num) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ ++ if (FH_OTG_PARAM_TEST(val, 4, 768)) { ++ FH_WARN("Wrong value for dev_perio_tx_fifo_size\n"); ++ FH_WARN("dev_perio_tx_fifo_size must be 4-768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ /* ++ if (val > ++ (FH_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16)) { ++ FH_WARN("Value is larger then power-on FIFO size\n"); ++ if (fh_otg_param_initialized ++ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { ++ FH_ERROR ++ ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = (FH_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]) >> 16); ++ retval = -FH_E_INVALID; ++ } ++ */ ++ ++ core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_perio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_perio_tx_fifo_size[fifo_num]; ++} ++ ++int fh_otg_set_param_en_multiple_tx_fifo(fh_otg_core_if_t * core_if, ++ int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong valaue for en_multiple_tx_fifo,\n"); ++ FH_WARN("en_multiple_tx_fifo must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->en_multiple_tx_fifo)) { ++ FH_ERROR ++ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->en_multiple_tx_fifo = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_en_multiple_tx_fifo(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->en_multiple_tx_fifo; ++} ++ ++int fh_otg_set_param_dev_tx_fifo_size(fh_otg_core_if_t * core_if, int32_t val, ++ int fifo_num) ++{ ++ int retval = 0; ++ fifosize_data_t txfifosize; ++ txfifosize.d32 = FH_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]); ++ ++ if (FH_OTG_PARAM_TEST(val, 16, 32768)) { ++ FH_WARN("Wrong value for dev_tx_fifo_size\n"); ++ FH_WARN("dev_tx_fifo_size must be 16-32768\n"); ++ return -FH_E_INVALID; ++ } ++ ++ /* ++ if (val > txfifosize.b.depth) { ++ FH_WARN("Value is larger then power-on FIFO size\n"); ++ if (fh_otg_param_initialized ++ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { ++ FH_ERROR ++ ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); ++ } ++ val = txfifosize.b.depth; ++ retval = -FH_E_INVALID; ++ } ++ */ ++ ++ core_if->core_params->dev_tx_fifo_size[fifo_num] = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int fifo_num) ++{ ++ return core_if->core_params->dev_tx_fifo_size[fifo_num]; ++} ++ ++int fh_otg_set_param_thr_ctl(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 7)) { ++ FH_WARN("Wrong value for thr_ctl\n"); ++ FH_WARN("thr_ctl must be 0-7\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val != 0) && ++ (!fh_otg_get_param_dma_enable(core_if) || ++ !core_if->hwcfg4.b.ded_fifo_en)) { ++ if (fh_otg_param_initialized(core_if->core_params->thr_ctl)) { ++ FH_ERROR ++ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->thr_ctl = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_thr_ctl(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->thr_ctl; ++} ++ ++int fh_otg_set_param_lpm_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for lpm_enable\n"); ++ FH_WARN("lpm_enable must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val && !core_if->hwcfg3.b.otg_lpm_en) { ++ if (fh_otg_param_initialized(core_if->core_params->lpm_enable)) { ++ FH_ERROR ++ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -FH_E_INVALID; ++ } ++ ++ core_if->core_params->lpm_enable = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_lpm_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->lpm_enable; ++} ++ ++int fh_otg_set_param_besl_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("Wrong value for besl_enable\n"); ++ FH_WARN("besl_enable must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->besl_enable = val; ++ ++ if(val) ++ { ++ retval += fh_otg_set_param_lpm_enable(core_if,val); ++ } ++ ++ return retval; ++} ++ ++int32_t fh_otg_get_param_besl_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->besl_enable; ++} ++ ++int fh_otg_set_param_baseline_besl(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 15)) { ++ FH_WARN("Wrong value for baseline_besl\n"); ++ FH_WARN("baseline_besl must be 0-15\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->baseline_besl = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_baseline_besl(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->baseline_besl; ++} ++ ++int fh_otg_set_param_deep_besl(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 15)) { ++ FH_WARN("Wrong value for deep_besl\n"); ++ FH_WARN("deep_besl must be 0-15\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->deep_besl = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_deep_besl(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->deep_besl; ++} ++ ++int fh_otg_set_param_tx_thr_length(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 8, 128)) { ++ FH_WARN("Wrong valaue for tx_thr_length\n"); ++ FH_WARN("tx_thr_length must be 8 - 128\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->tx_thr_length = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_tx_thr_length(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->tx_thr_length; ++} ++ ++int fh_otg_set_param_rx_thr_length(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 8, 128)) { ++ FH_WARN("Wrong valaue for rx_thr_length\n"); ++ FH_WARN("rx_thr_length must be 8 - 128\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->rx_thr_length = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_rx_thr_length(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->rx_thr_length; ++} ++ ++int fh_otg_set_param_dma_burst_size(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ if (FH_OTG_PARAM_TEST(val, 1, 1) && ++ FH_OTG_PARAM_TEST(val, 4, 4) && ++ FH_OTG_PARAM_TEST(val, 8, 8) && ++ FH_OTG_PARAM_TEST(val, 16, 16) && ++ FH_OTG_PARAM_TEST(val, 32, 32) && ++ FH_OTG_PARAM_TEST(val, 64, 64) && ++ FH_OTG_PARAM_TEST(val, 128, 128) && ++ FH_OTG_PARAM_TEST(val, 256, 256)) { ++ FH_WARN("`%d' invalid for parameter `dma_burst_size'\n", val); ++ return -FH_E_INVALID; ++ } ++ core_if->core_params->dma_burst_size = val; ++ return 0; ++} ++ ++int32_t fh_otg_get_param_dma_burst_size(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dma_burst_size; ++} ++ ++int fh_otg_set_param_pti_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `pti_enable'\n", val); ++ return -FH_E_INVALID; ++ } ++ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { ++ if (fh_otg_param_initialized(core_if->core_params->pti_enable)) { ++ FH_ERROR ++ ("%d invalid for parameter pti_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->pti_enable = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_pti_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->pti_enable; ++} ++ ++int fh_otg_set_param_mpi_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `mpi_enable'\n", val); ++ return -FH_E_INVALID; ++ } ++ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { ++ if (fh_otg_param_initialized(core_if->core_params->mpi_enable)) { ++ FH_ERROR ++ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->mpi_enable = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_mpi_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->mpi_enable; ++} ++ ++int fh_otg_set_param_adp_enable(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `adp_enable'\n", val); ++ return -FH_E_INVALID; ++ } ++ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->adp_supp_enable)) { ++ FH_ERROR ++ ("%d invalid for parameter adp_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->adp_supp_enable = val; ++ /* Set OTG version 2.0 in case of enabling ADP */ ++ if (val) ++ fh_otg_set_param_otg_ver(core_if, 1); ++ ++ return retval; ++} ++ ++int32_t fh_otg_get_param_adp_enable(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->adp_supp_enable; ++} ++ ++int fh_otg_set_param_ic_usb_cap(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val); ++ FH_WARN("ic_usb_cap must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { ++ if (fh_otg_param_initialized(core_if->core_params->ic_usb_cap)) { ++ FH_ERROR ++ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ic_usb_cap = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_ic_usb_cap(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ic_usb_cap; ++} ++ ++int fh_otg_set_param_ahb_thr_ratio(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 3)) { ++ FH_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); ++ FH_WARN("ahb_thr_ratio must be 0 - 3\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (val ++ && (core_if->snpsid < OTG_CORE_REV_2_81a ++ || !fh_otg_get_param_thr_ctl(core_if))) { ++ valid = 0; ++ } else if (val ++ && ((fh_otg_get_param_tx_thr_length(core_if) / (1 << val)) < ++ 4)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized ++ (core_if->core_params->ahb_thr_ratio)) { ++ FH_ERROR ++ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ ++ core_if->core_params->ahb_thr_ratio = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_ahb_thr_ratio(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_thr_ratio; ++} ++ ++int fh_otg_set_param_power_down(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; ++ hwcfg4.d32 = FH_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 3)) { ++ FH_WARN("`%d' invalid for parameter `power_down'\n", val); ++ FH_WARN("power_down must be 0 - 3\n"); ++ return -FH_E_INVALID; ++ } ++ if ((val == 1) && (hwcfg4.b.power_optimiz == 0)) { ++ val = 0; ++ } ++ if ((val == 2) && ((core_if->snpsid < OTG_CORE_REV_2_91a) || (hwcfg4.b.hiber == 0)) ) { ++ valid = 0; ++ } ++ if ((val == 3) ++ && ((core_if->snpsid < OTG_CORE_REV_3_00a) ++ || (hwcfg4.b.xhiber == 0))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->power_down)) { ++ FH_ERROR ++ ("%d invalid for parameter power_down. Check HW configuration.\n", ++ val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->power_down = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_power_down(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->power_down; ++} ++ ++int fh_otg_set_param_reload_ctl(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `reload_ctl'\n", val); ++ FH_WARN("reload_ctl must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->reload_ctl)) { ++ FH_ERROR("%d invalid for parameter reload_ctl." ++ "Check HW configuration.\n", val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->reload_ctl = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_reload_ctl(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->reload_ctl; ++} ++ ++int fh_otg_set_param_dev_out_nak(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); ++ FH_WARN("dev_out_nak must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->dev_out_nak)) { ++ FH_ERROR("%d invalid for parameter dev_out_nak." ++ "Check HW configuration.\n", val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->dev_out_nak = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_dev_out_nak(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_out_nak; ++} ++ ++int fh_otg_set_param_cont_on_bna(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); ++ FH_WARN("cont_on_bna must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->cont_on_bna)) { ++ FH_ERROR("%d invalid for parameter cont_on_bna." ++ "Check HW configuration.\n", val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->cont_on_bna = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_cont_on_bna(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->cont_on_bna; ++} ++ ++int fh_otg_set_param_ahb_single(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `ahb_single'\n", val); ++ FH_WARN("ahb_single must be 0 or 1\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (fh_otg_param_initialized(core_if->core_params->ahb_single)) { ++ FH_ERROR("%d invalid for parameter ahb_single." ++ "Check HW configuration.\n", val); ++ } ++ retval = -FH_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ahb_single = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_ahb_single(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_single; ++} ++ ++int fh_otg_set_param_otg_ver(fh_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 1)) { ++ FH_WARN("`%d' invalid for parameter `otg_ver'\n", val); ++ FH_WARN ++ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); ++ return -FH_E_INVALID; ++ } ++ ++ core_if->core_params->otg_ver = val; ++ return retval; ++} ++ ++int32_t fh_otg_get_param_otg_ver(fh_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_ver; ++} ++ ++uint32_t fh_otg_get_hnpstatus(fh_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.hstnegscs; ++} ++ ++uint32_t fh_otg_get_srpstatus(fh_otg_core_if_t * core_if) ++{ ++ gotgctl_data_t otgctl; ++ otgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ return otgctl.b.sesreqscs; ++} ++ ++void fh_otg_set_hnpreq(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ if(core_if->otg_ver == 0) { ++ gotgctl_data_t otgctl; ++ otgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ otgctl.b.hnpreq = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32); ++ } else { ++ core_if->otg_sts = val; ++ } ++} ++ ++uint32_t fh_otg_get_gsnpsid(fh_otg_core_if_t * core_if) ++{ ++ return core_if->snpsid; ++} ++ ++uint32_t fh_otg_get_mode(fh_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ return gintsts.b.curmode; ++} ++ ++uint32_t fh_otg_get_hnpcapable(fh_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.hnpcap; ++} ++ ++void fh_otg_set_hnpcapable(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.hnpcap = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t fh_otg_get_srpcapable(fh_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ return usbcfg.b.srpcap; ++} ++ ++void fh_otg_set_srpcapable(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ gusbcfg_data_t usbcfg; ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.b.srpcap = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++} ++ ++uint32_t fh_otg_get_devspeed(fh_otg_core_if_t * core_if) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ return dcfg.b.devspd; ++} ++ ++void fh_otg_set_devspeed(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++uint32_t fh_otg_get_busconnected(fh_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = FH_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtconnsts; ++} ++ ++uint32_t fh_otg_get_enumspeed(fh_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ return dsts.b.enumspd; ++} ++ ++uint32_t fh_otg_get_prtpower(fh_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = FH_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtpwr; ++ ++} ++ ++uint32_t fh_otg_get_core_state(fh_otg_core_if_t * core_if) ++{ ++ return core_if->hibernation_suspend; ++} ++ ++void fh_otg_set_prtpower(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = val; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t fh_otg_get_prtsuspend(fh_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = FH_READ_REG32(core_if->host_if->hprt0); ++ return hprt0.b.prtsusp; ++ ++} ++ ++void fh_otg_set_prtsuspend(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = val; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t fh_otg_get_fr_interval(fh_otg_core_if_t * core_if) ++{ ++ hfir_data_t hfir; ++ hfir.d32 = FH_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ return hfir.b.frint; ++ ++} ++ ++void fh_otg_set_fr_interval(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ hfir_data_t hfir; ++ uint32_t fram_int; ++ fram_int = calc_frame_interval(core_if); ++ hfir.d32 = FH_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ if (!core_if->core_params->reload_ctl) { ++ FH_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" ++ "not set to 1.\nShould load driver with reload_ctl=1" ++ " module parameter\n"); ++ return; ++ } ++ switch (fram_int) { ++ case 3750: ++ if ((val < 3350) || (val > 4150)) { ++ FH_WARN("HFIR interval for HS core and 30 MHz" ++ "clock freq should be from 3350 to 4150\n"); ++ return; ++ } ++ break; ++ case 30000: ++ if ((val < 26820) || (val > 33180)) { ++ FH_WARN("HFIR interval for FS/LS core and 30 MHz" ++ "clock freq should be from 26820 to 33180\n"); ++ return; ++ } ++ break; ++ case 6000: ++ if ((val < 5360) || (val > 6640)) { ++ FH_WARN("HFIR interval for HS core and 48 MHz" ++ "clock freq should be from 5360 to 6640\n"); ++ return; ++ } ++ break; ++ case 48000: ++ if ((val < 42912) || (val > 53088)) { ++ FH_WARN("HFIR interval for FS/LS core and 48 MHz" ++ "clock freq should be from 42912 to 53088\n"); ++ return; ++ } ++ break; ++ case 7500: ++ if ((val < 6700) || (val > 8300)) { ++ FH_WARN("HFIR interval for HS core and 60 MHz" ++ "clock freq should be from 6700 to 8300\n"); ++ return; ++ } ++ break; ++ case 60000: ++ if ((val < 53640) || (val > 65536)) { ++ FH_WARN("HFIR interval for FS/LS core and 60 MHz" ++ "clock freq should be from 53640 to 65536\n"); ++ return; ++ } ++ break; ++ default: ++ FH_WARN("Unknown frame interval\n"); ++ return; ++ break; ++ ++ } ++ hfir.b.frint = val; ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); ++} ++ ++uint32_t fh_otg_get_mode_ch_tim(fh_otg_core_if_t * core_if) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = FH_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ return hcfg.b.modechtimen; ++ ++} ++ ++void fh_otg_set_mode_ch_tim(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = FH_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.modechtimen = val; ++ FH_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++void fh_otg_set_prtresume(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtres = val; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t fh_otg_get_remotewakesig(fh_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.rmtwkupsig; ++} ++ ++uint32_t fh_otg_get_beslreject(fh_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.besl_reject; ++} ++ ++void fh_otg_set_beslreject(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.besl_reject = val; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++uint32_t fh_otg_get_hirdthresh(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hird_thres; ++} ++ ++void fh_otg_set_hirdthresh(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ ++ if (FH_OTG_PARAM_TEST(val, 0, 15)) { ++ FH_WARN("Wrong valaue for hird_thres\n"); ++ FH_WARN("hird_thres must be 0-f\n"); ++ return ; ++ } ++ ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (1<<4); ++ lpmcfg.b.hird_thres |= val; ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t fh_otg_get_lpm_portsleepstatus(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ FH_ASSERT(! ++ ((core_if->lx_state == FH_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), ++ "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n", ++ core_if->lx_state, lpmcfg.b.prt_sleep_sts); ++ ++ return lpmcfg.b.prt_sleep_sts; ++} ++ ++uint32_t fh_otg_get_lpm_remotewakeenabled(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.rem_wkup_en; ++} ++ ++uint32_t fh_otg_get_lpmresponse(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.appl_resp; ++} ++ ++void fh_otg_set_lpmresponse(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.appl_resp = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t fh_otg_get_hsic_connect(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.hsic_connect; ++} ++ ++void fh_otg_set_hsic_connect(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hsic_connect = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t fh_otg_get_inv_sel_hsic(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ return lpmcfg.b.inv_sel_hsic; ++ ++} ++ ++void fh_otg_set_inv_sel_hsic(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.inv_sel_hsic = val; ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++} ++ ++uint32_t fh_otg_get_gotgctl(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++} ++ ++void fh_otg_set_gotgctl(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgctl, val); ++} ++ ++uint32_t fh_otg_get_gusbcfg(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++} ++ ++void fh_otg_set_gusbcfg(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val); ++} ++ ++uint32_t fh_otg_get_grxfsiz(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->grxfsiz); ++} ++ ++void fh_otg_set_grxfsiz(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val); ++} ++ ++uint32_t fh_otg_get_gnptxfsiz(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++} ++ ++void fh_otg_set_gnptxfsiz(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val); ++} ++ ++uint32_t fh_otg_get_gpvndctl(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->gpvndctl); ++} ++ ++void fh_otg_set_gpvndctl(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val); ++} ++ ++uint32_t fh_otg_get_ggpio(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->ggpio); ++} ++ ++void fh_otg_set_ggpio(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->ggpio, val); ++} ++ ++uint32_t fh_otg_get_hprt0(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(core_if->host_if->hprt0); ++ ++} ++ ++void fh_otg_set_hprt0(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(core_if->host_if->hprt0, val); ++} ++ ++uint32_t fh_otg_get_guid(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->guid); ++} ++ ++void fh_otg_set_guid(fh_otg_core_if_t * core_if, uint32_t val) ++{ ++ FH_WRITE_REG32(&core_if->core_global_regs->guid, val); ++} ++ ++uint32_t fh_otg_get_hptxfsiz(fh_otg_core_if_t * core_if) ++{ ++ return FH_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++} ++ ++uint16_t fh_otg_get_otg_version(fh_otg_core_if_t * core_if) ++{ ++ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void fh_otg_pcd_start_srp_timer(fh_otg_core_if_t * core_if) ++{ ++ core_if->srp_timer_started = 1; ++ FH_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); ++} ++ ++void fh_otg_initiate_srp(void * p) ++{ ++ fh_otg_core_if_t * core_if = p; ++ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); ++ gotgctl_data_t mem; ++ gotgctl_data_t val; ++ ++ val.d32 = FH_READ_REG32(addr); ++ if (val.b.sesreq) { ++ FH_ERROR("Session Request Already active!\n"); ++ return; ++ } ++ ++ FH_INFO("Session Request Initated\n"); //NOTICE ++ mem.d32 = FH_READ_REG32(addr); ++ mem.b.sesreq = 1; ++ FH_WRITE_REG32(addr, mem.d32); ++ ++ /* Start the SRP timer */ ++ fh_otg_pcd_start_srp_timer(core_if); ++ return; ++} ++ ++int fh_otg_check_haps_status(fh_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ ++ if(FH_READ_REG32(&core_if->core_global_regs->gsnpsid) == 0xffffffff) ++ { ++ return -1; ++ } else { ++ return retval; ++ } ++ ++} +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.h +new file mode 100644 +index 00000000..bf5e773a +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil.h +@@ -0,0 +1,1503 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_cil.h $ ++ * $Revision: #136 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#if !defined(__FH_CIL_H__) ++#define __FH_CIL_H__ ++ ++#include "../fh_common_port/fh_list.h" ++#include "fh_otg_dbg.h" ++#include "fh_otg_regs.h" ++ ++#include "fh_otg_core_if.h" ++#include "fh_otg_adp.h" ++ ++/** ++ * @file ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++#ifdef FH_UTE_CFI ++ ++#define MAX_DMA_DESCS_PER_EP 256 ++ ++/** ++ * Enumeration for the data buffer mode ++ */ ++typedef enum _data_buffer_mode { ++ BM_STANDARD = 0, /* data buffer is in normal mode */ ++ BM_SG = 1, /* data buffer uses the scatter/gather mode */ ++ BM_CONCAT = 2, /* data buffer uses the concatenation mode */ ++ BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ ++ BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ ++} data_buffer_mode_e; ++#endif //FH_UTE_CFI ++ ++/** Macros defined for FH OTG HW Release version */ ++ ++#define OTG_CORE_REV_2_60a 0x4F54260A ++#define OTG_CORE_REV_2_71a 0x4F54271A ++#define OTG_CORE_REV_2_72a 0x4F54272A ++#define OTG_CORE_REV_2_80a 0x4F54280A ++#define OTG_CORE_REV_2_81a 0x4F54281A ++#define OTG_CORE_REV_2_90a 0x4F54290A ++#define OTG_CORE_REV_2_91a 0x4F54291A ++#define OTG_CORE_REV_2_92a 0x4F54292A ++#define OTG_CORE_REV_2_93a 0x4F54293A ++#define OTG_CORE_REV_2_94a 0x4F54294A ++#define OTG_CORE_REV_3_00a 0x4F54300A ++#define OTG_CORE_REV_3_10a 0x4F54310A ++#define OTG_CORE_REV_3_20a 0x4F54320A ++#define OTG_CORE_REV_3_30a 0x4F54330A ++ ++/** ++ * Information for each ISOC packet. ++ */ ++typedef struct iso_pkt_info { ++ uint32_t offset; ++ uint32_t length; ++ int32_t status; ++} iso_pkt_info_t; ++ ++/** ++ * The <code>fh_ep</code> structure represents the state of a single ++ * endpoint when acting in device mode. It contains the data items ++ * needed for an endpoint to be activated and transfer packets. ++ */ ++typedef struct fh_ep { ++ /** EP number used for register address lookup */ ++ uint8_t num; ++ /** EP direction 0 = OUT */ ++ unsigned is_in:1; ++ /** EP active. */ ++ unsigned active:1; ++ ++ /** ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic ++ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ ++ unsigned tx_fifo_num:4; ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ unsigned type:2; ++#define FH_OTG_EP_TYPE_CONTROL 0 ++#define FH_OTG_EP_TYPE_ISOC 1 ++#define FH_OTG_EP_TYPE_BULK 2 ++#define FH_OTG_EP_TYPE_INTR 3 ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned data_pid_start:1; ++ /** Frame (even/odd) for ISOC EP */ ++ unsigned even_odd_frame:1; ++ /** Max Packet bytes */ ++ unsigned maxpacket:11; ++ ++ /** Max Transfer size */ ++ uint32_t maxxfer; ++ ++ /** @name Transfer state */ ++ /** @{ */ ++ ++ /** ++ * Pointer to the beginning of the transfer buffer -- do not modify ++ * during transfer. ++ */ ++ fh_dma_t dma_addr; ++ ++ fh_dma_t dma_desc_addr; ++ fh_otg_dev_dma_desc_t *desc_addr; ++ ++ /* Additional desc chain for ISO transfers */ ++ fh_dma_t dma_desc_addr1; ++ fh_otg_dev_dma_desc_t *desc_addr1; ++ /* Flag indicating which one of two ISO desc chains currently is in use */ ++ uint8_t use_add_buf; ++ ++ uint8_t *start_xfer_buff; ++ /** pointer to the transfer buffer */ ++ uint8_t *xfer_buff; ++ /** Number of bytes to transfer */ ++ unsigned xfer_len:19; ++ /** Number of bytes transferred. */ ++ unsigned xfer_count:19; ++ /** Sent ZLP */ ++ unsigned sent_zlp:1; ++ /** Total len for control transfer */ ++ unsigned total_len:19; ++ ++ /** stall clear flag */ ++ unsigned stall_clear_flag:1; ++ ++ /** SETUP pkt cnt rollover flag for EP0 out*/ ++ unsigned stp_rollover; ++ ++#ifdef FH_UTE_CFI ++ /* The buffer mode */ ++ data_buffer_mode_e buff_mode; ++ ++ /* The chain of DMA descriptors. ++ * MAX_DMA_DESCS_PER_EP will be allocated for each active EP. ++ */ ++ fh_otg_dma_desc_t *descs; ++ ++ /* The DMA address of the descriptors chain start */ ++ dma_addr_t descs_dma_addr; ++ /** This variable stores the length of the last enqueued request */ ++ uint32_t cfi_req_len; ++#endif //FH_UTE_CFI ++ ++/** Max DMA Descriptor count for any EP */ ++#define MAX_DMA_DESC_CNT 256 ++ /** Allocated DMA Desc count */ ++ uint32_t desc_cnt; ++ ++ /** First ISO Desc in use in the first chain*/ ++ uint32_t iso_desc_first; ++ /** Last ISO Desc in use in the second chain */ ++ uint32_t iso_desc_second; ++ /** Flag indicated that iso transfers were started */ ++ uint8_t iso_transfer_started; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** Next frame num to setup next ISOC transfer */ ++ uint32_t frame_num; ++ /** Indicates SOF number overrun in DSTS */ ++ uint8_t frm_overrun; ++ ++#ifdef FH_UTE_PER_IO ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t xiso_frame_num; ++ /** bInterval */ ++ uint32_t xiso_bInterval; ++ /** Count of currently active transfers - shall be either 0 or 1 */ ++ int xiso_active_xfers; ++ int xiso_queued_xfers; ++#endif ++#ifdef FH_EN_ISOC ++ /** ++ * Variables specific for ISOC EPs ++ * ++ */ ++ /** DMA addresses of ISOC buffers */ ++ fh_dma_t dma_addr0; ++ fh_dma_t dma_addr1; ++ ++ fh_dma_t iso_dma_desc_addr; ++ fh_otg_dev_dma_desc_t *iso_desc_addr; ++ ++ /** pointer to the transfer buffers */ ++ uint8_t *xfer_buff0; ++ uint8_t *xfer_buff1; ++ ++ /** number of ISOC Buffer is processing */ ++ uint32_t proc_buf_num; ++ /** Interval of ISOC Buffer processing */ ++ uint32_t buf_proc_intrvl; ++ /** Data size for regular frame */ ++ uint32_t data_per_frame; ++ ++ /* todo - pattern data support is to be implemented in the future */ ++ /** Data size for pattern frame */ ++ uint32_t data_pattern_frame; ++ /** Frame number of pattern data */ ++ uint32_t sync_frame; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** ISO Packet number per frame */ ++ uint32_t pkt_per_frm; ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t next_frame; ++ /** Number of packets per buffer processing */ ++ uint32_t pkt_cnt; ++ /** Info for all isoc packets */ ++ iso_pkt_info_t *pkt_info; ++ /** current pkt number */ ++ uint32_t cur_pkt; ++ /** current pkt number */ ++ uint8_t *cur_pkt_addr; ++ /** current pkt number */ ++ uint32_t cur_pkt_dma_addr; ++#endif /* FH_EN_ISOC */ ++ ++/** @} */ ++} fh_ep_t; ++ ++/* ++ * Reasons for halting a host channel. ++ */ ++typedef enum fh_otg_halt_status { ++ FH_OTG_HC_XFER_NO_HALT_STATUS, ++ FH_OTG_HC_XFER_COMPLETE, ++ FH_OTG_HC_XFER_URB_COMPLETE, ++ FH_OTG_HC_XFER_ACK, ++ FH_OTG_HC_XFER_NAK, ++ FH_OTG_HC_XFER_NYET, ++ FH_OTG_HC_XFER_STALL, ++ FH_OTG_HC_XFER_XACT_ERR, ++ FH_OTG_HC_XFER_FRAME_OVERRUN, ++ FH_OTG_HC_XFER_BABBLE_ERR, ++ FH_OTG_HC_XFER_DATA_TOGGLE_ERR, ++ FH_OTG_HC_XFER_AHB_ERR, ++ FH_OTG_HC_XFER_PERIODIC_INCOMPLETE, ++ FH_OTG_HC_XFER_URB_DEQUEUE ++} fh_otg_halt_status_e; ++ ++/** ++ * Host channel descriptor. This structure represents the state of a single ++ * host channel when acting in host mode. It contains the data items needed to ++ * transfer packets to an endpoint via a host channel. ++ */ ++typedef struct fh_hc { ++ /** Host channel number used for register address lookup */ ++ uint8_t hc_num; ++ ++ /** Device to access */ ++ unsigned dev_addr:7; ++ ++ /** EP to access */ ++ unsigned ep_num:4; ++ ++ /** EP direction. 0: OUT, 1: IN */ ++ unsigned ep_is_in:1; ++ ++ /** ++ * EP speed. ++ * One of the following values: ++ * - FH_OTG_EP_SPEED_LOW ++ * - FH_OTG_EP_SPEED_FULL ++ * - FH_OTG_EP_SPEED_HIGH ++ */ ++ unsigned speed:2; ++#define FH_OTG_EP_SPEED_LOW 0 ++#define FH_OTG_EP_SPEED_FULL 1 ++#define FH_OTG_EP_SPEED_HIGH 2 ++ ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - FH_OTG_EP_TYPE_CONTROL: 0 ++ * - FH_OTG_EP_TYPE_ISOC: 1 ++ * - FH_OTG_EP_TYPE_BULK: 2 ++ * - FH_OTG_EP_TYPE_INTR: 3 ++ */ ++ unsigned ep_type:2; ++ ++ /** Max packet size in bytes */ ++ unsigned max_packet:11; ++ ++ /** ++ * PID for initial transaction. ++ * 0: DATA0,<br> ++ * 1: DATA2,<br> ++ * 2: DATA1,<br> ++ * 3: MDATA (non-Control EP), ++ * SETUP (Control EP) ++ */ ++ unsigned data_pid_start:2; ++#define FH_OTG_HC_PID_DATA0 0 ++#define FH_OTG_HC_PID_DATA2 1 ++#define FH_OTG_HC_PID_DATA1 2 ++#define FH_OTG_HC_PID_MDATA 3 ++#define FH_OTG_HC_PID_SETUP 3 ++ ++ /** Number of periodic transactions per (micro)frame */ ++ unsigned multi_count:2; ++ ++ /** @name Transfer State */ ++ /** @{ */ ++ ++ /** Pointer to the current transfer buffer position. */ ++ uint8_t *xfer_buff; ++ /** ++ * In Buffer DMA mode this buffer will be used ++ * if xfer_buff is not DWORD aligned. ++ */ ++ fh_dma_t align_buff; ++ /** Total number of bytes to transfer. */ ++ uint32_t xfer_len; ++ /** Number of bytes transferred so far. */ ++ uint32_t xfer_count; ++ /** Packet count at start of transfer.*/ ++ uint16_t start_pkt_count; ++ ++ /** ++ * Flag to indicate whether the transfer has been started. Set to 1 if ++ * it has been started, 0 otherwise. ++ */ ++ uint8_t xfer_started; ++ ++ /** ++ * Set to 1 to indicate that a PING request should be issued on this ++ * channel. If 0, process normally. ++ */ ++ uint8_t do_ping; ++ ++ /** ++ * Set to 1 to indicate that the error count for this transaction is ++ * non-zero. Set to 0 if the error count is 0. ++ */ ++ uint8_t error_state; ++ ++ /** ++ * Set to 1 to indicate that this channel should be halted the next ++ * time a request is queued for the channel. This is necessary in ++ * slave mode if no request queue space is available when an attempt ++ * is made to halt the channel. ++ */ ++ uint8_t halt_on_queue; ++ ++ /** ++ * Set to 1 if the host channel has been halted, but the core is not ++ * finished flushing queued requests. Otherwise 0. ++ */ ++ uint8_t halt_pending; ++ ++ /** ++ * Reason for halting the host channel. ++ */ ++ fh_otg_halt_status_e halt_status; ++ ++ /* ++ * Split settings for the host channel ++ */ ++ uint8_t do_split; /**< Enable split for the channel */ ++ uint8_t complete_split; /**< Enable complete split */ ++ uint8_t hub_addr; /**< Address of high speed hub */ ++ ++ uint8_t port_addr; /**< Port of the low/full speed device */ ++ /** Split transaction position ++ * One of the following values: ++ * - FH_HCSPLIT_XACTPOS_MID ++ * - FH_HCSPLIT_XACTPOS_BEGIN ++ * - FH_HCSPLIT_XACTPOS_END ++ * - FH_HCSPLIT_XACTPOS_ALL */ ++ uint8_t xact_pos; ++ ++ /** Set when the host channel does a short read. */ ++ uint8_t short_read; ++ ++ /** ++ * Number of requests issued for this channel since it was assigned to ++ * the current transfer (not counting PINGs). ++ */ ++ uint8_t requests; ++ ++ /** ++ * Queue Head for the transfer being processed by this channel. ++ */ ++ struct fh_otg_qh *qh; ++ ++ /** @} */ ++ ++ /** Entry in list of host channels. */ ++ FH_CIRCLEQ_ENTRY(fh_hc) hc_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Number of Transfer Descriptors */ ++ uint16_t ntd; ++ ++ /** Descriptor List DMA address */ ++ fh_dma_t desc_list_addr; ++ ++ /** Scheduling micro-frame bitmap. */ ++ uint8_t schinfo; ++ ++ /** @} */ ++} fh_hc_t; ++ ++/** ++ * The following parameters may be specified when starting the module. These ++ * parameters define how the FH_otg controller should be configured. ++ */ ++typedef struct fh_otg_core_params { ++ int32_t opt; ++ ++ /** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++ int32_t otg_cap; ++ ++ /** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++ int32_t dma_enable; ++ ++ /** ++ * When DMA mode is enabled specifies whether to use address DMA or DMA ++ * Descriptor mode for accessing the data FIFOs in device mode. The driver ++ * will automatically detect the value for this if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++ int32_t dma_desc_enable; ++ /** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++ int32_t dma_burst_size; /* Translate this to GAHBCFG values */ ++ ++ /** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++ int32_t speed; ++ /** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++ int32_t host_support_fs_ls_low_power; ++ ++ /** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++ int32_t host_ls_low_power_phy_clk; ++ ++ /** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++ int32_t enable_dynamic_fifo; ++ ++ /** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++ int32_t data_fifo_size; ++ ++ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++ int32_t dev_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t dev_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_rx_fifo_size; ++ ++ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_nperio_tx_fifo_size; ++ ++ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++ int32_t host_perio_tx_fifo_size; ++ ++ /** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++ int32_t max_transfer_size; ++ ++ /** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++ int32_t max_packet_count; ++ ++ /** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++ int32_t host_channels; ++ ++ /** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++ int32_t dev_endpoints; ++ ++ /** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++ int32_t phy_type; ++ ++ /** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++ int32_t phy_utmi_width; ++ ++ /** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++ int32_t phy_ulpi_ddr; ++ ++ /** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++ int32_t phy_ulpi_ext_vbus; ++ ++ /** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++ int32_t i2c_enable; ++ ++ int32_t ulpi_fs_ls; ++ ++ int32_t ts_dline; ++ ++ /** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++ int32_t en_multiple_tx_fifo; ++ ++ /** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++ uint32_t thr_ctl; ++ ++ /** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t tx_thr_length; ++ ++ /** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++ uint32_t rx_thr_length; ++ ++ /** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++ int32_t lpm_enable; ++ ++ /** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++ int32_t besl_enable; ++ ++ /** ++ * Specifies the baseline besl value ++ */ ++ int32_t baseline_besl; ++ ++ /** ++ * Specifies the deep besl value ++ */ ++ int32_t deep_besl; ++ /** Per Transfer Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t pti_enable; ++ ++ /** Multi Processor Interrupt ++ * mode enable flag ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t mpi_enable; ++ ++ /** IS_USB Capability ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t ic_usb_cap; ++ ++ /** AHB Threshold Ratio ++ * 2'b00 AHB Threshold = MAC Threshold ++ * 2'b01 AHB Threshold = 1/2 MAC Threshold ++ * 2'b10 AHB Threshold = 1/4 MAC Threshold ++ * 2'b11 AHB Threshold = 1/8 MAC Threshold ++ */ ++ int32_t ahb_thr_ratio; ++ ++ /** ADP Support ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t adp_supp_enable; ++ ++ /** HFIR Reload Control ++ * 0 - The HFIR cannot be reloaded dynamically. ++ * 1 - Allow dynamic reloading of the HFIR register during runtime. ++ */ ++ int32_t reload_ctl; ++ ++ /** DCFG: Enable device Out NAK ++ * 0 - The core does not set NAK after Bulk Out transfer complete. ++ * 1 - The core sets NAK after Bulk OUT transfer complete. ++ */ ++ int32_t dev_out_nak; ++ ++ /** DCFG: Enable Continue on BNA ++ * After receiving BNA interrupt the core disables the endpoint,when the ++ * endpoint is re-enabled by the application the core starts processing ++ * 0 - from the DOEPDMA descriptor ++ * 1 - from the descriptor which received the BNA. ++ */ ++ int32_t cont_on_bna; ++ ++ /** GAHBCFG: AHB Single Support ++ * This bit when programmed supports SINGLE transfers for remainder ++ * data in a transfer for DMA mode of operation. ++ * 0 - in this case the remainder data will be sent using INCR burst size. ++ * 1 - in this case the remainder data will be sent using SINGLE burst size. ++ */ ++ int32_t ahb_single; ++ ++ /** Core Power down mode ++ * 0 - No Power Down is enabled ++ * 1 - Reserved ++ * 2 - Complete Power Down (Hibernation) ++ */ ++ int32_t power_down; ++ ++ /** OTG revision supported ++ * 0 - OTG 1.3 revision ++ * 1 - OTG 2.0 revision ++ */ ++ int32_t otg_ver; ++ ++} fh_otg_core_params_t; ++ ++#ifdef DEBUG ++struct fh_otg_core_if; ++typedef struct hc_xfer_info { ++ struct fh_otg_core_if *core_if; ++ fh_hc_t *hc; ++} hc_xfer_info_t; ++#endif ++ ++typedef struct ep_xfer_info { ++ struct fh_otg_core_if *core_if; ++ fh_ep_t *ep; ++ uint8_t state; ++} ep_xfer_info_t; ++/* ++ * Device States ++ */ ++typedef enum fh_otg_lx_state { ++ /** On state */ ++ FH_OTG_L0, ++ /** LPM sleep state*/ ++ FH_OTG_L1, ++ /** USB suspend state*/ ++ FH_OTG_L2, ++ /** Off state*/ ++ FH_OTG_L3 ++} fh_otg_lx_state_e; ++ ++struct fh_otg_global_regs_backup { ++ uint32_t gotgctl_local; ++ uint32_t gintmsk_local; ++ uint32_t gahbcfg_local; ++ uint32_t gusbcfg_local; ++ uint32_t grxfsiz_local; ++ uint32_t gnptxfsiz_local; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ uint32_t glpmcfg_local; ++#endif ++ uint32_t gi2cctl_local; ++ uint32_t hptxfsiz_local; ++ uint32_t pcgcctl_local; ++ uint32_t gdfifocfg_local; ++ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; ++ uint32_t gpwrdn_local; ++ uint32_t xhib_pcgcctl; ++ uint32_t xhib_gpwrdn; ++}; ++ ++struct fh_otg_host_regs_backup { ++ uint32_t hcfg_local; ++ uint32_t haintmsk_local; ++ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; ++ uint32_t hprt0_local; ++ uint32_t hfir_local; ++}; ++ ++struct fh_otg_dev_regs_backup { ++ uint32_t dcfg; ++ uint32_t dctl; ++ uint32_t daintmsk; ++ uint32_t diepmsk; ++ uint32_t doepmsk; ++ uint32_t diepctl[MAX_EPS_CHANNELS]; ++ uint32_t dieptsiz[MAX_EPS_CHANNELS]; ++ uint32_t diepdma[MAX_EPS_CHANNELS]; ++ uint32_t doepctl[MAX_EPS_CHANNELS]; ++ uint32_t doeptsiz[MAX_EPS_CHANNELS]; ++ uint32_t doepdma[MAX_EPS_CHANNELS]; ++}; ++/** ++ * The <code>fh_otg_core_if</code> structure contains information needed to manage ++ * the FH_otg controller acting in either host or device mode. It ++ * represents the programming view of the controller as a whole. ++ */ ++struct fh_otg_core_if { ++ /** Parameters that define how the core should be configured.*/ ++ fh_otg_core_params_t *core_params; ++ ++ /** Core Global registers starting at offset 000h. */ ++ fh_otg_core_global_regs_t *core_global_regs; ++ ++ /** Device-specific information */ ++ fh_otg_dev_if_t *dev_if; ++ /** Host-specific information */ ++ fh_otg_host_if_t *host_if; ++ ++ /** Value from SNPSID register */ ++ uint32_t snpsid; ++ ++ /* ++ * Set to 1 if the core PHY interface bits in USBCFG have been ++ * initialized. ++ */ ++ uint8_t phy_init_done; ++ ++ /* ++ * SRP Success flag, set by srp success interrupt in FS I2C mode ++ */ ++ uint8_t srp_success; ++ uint8_t srp_timer_started; ++ /** Timer for SRP. If it expires before SRP is successful ++ * clear the SRP. */ ++ fh_timer_t *srp_timer; ++ ++#ifdef FH_DEV_SRPCAP ++ /* This timer is needed to power on the hibernated host core if SRP is not ++ * initiated on connected SRP capable device for limited period of time ++ */ ++ uint8_t pwron_timer_started; ++ fh_timer_t *pwron_timer; ++#endif ++ /* Common configuration information */ ++ /** Power and Clock Gating Control Register */ ++ volatile uint32_t *pcgcctl; ++#define FH_OTG_PCGCCTL_OFFSET 0xE00 ++ ++ /** Push/pop addresses for endpoints or host channels.*/ ++ uint32_t *data_fifo[MAX_EPS_CHANNELS]; ++#define FH_OTG_DATA_FIFO_OFFSET 0x1000 ++#define FH_OTG_DATA_FIFO_SIZE 0x1000 ++ ++ /** Total RAM for FIFOs (Bytes) */ ++ uint16_t total_fifo_size; ++ /** Size of Rx FIFO (Bytes) */ ++ uint16_t rx_fifo_size; ++ /** Size of Non-periodic Tx FIFO (Bytes) */ ++ uint16_t nperio_tx_fifo_size; ++ ++ /** 1 if DMA is enabled, 0 otherwise. */ ++ uint8_t dma_enable; ++ ++ /** 1 if DMA descriptor is enabled, 0 otherwise. */ ++ uint8_t dma_desc_enable; ++ ++ /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t pti_enh_enable; ++ ++ /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */ ++ uint8_t multiproc_int_enable; ++ ++ /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */ ++ uint8_t en_multiple_tx_fifo; ++ ++ /** Set to 1 if multiple packets of a high-bandwidth transfer is in ++ * process of being queued */ ++ uint8_t queuing_high_bandwidth; ++ ++ /** Hardware Configuration -- stored here for convenience.*/ ++ hwcfg1_data_t hwcfg1; ++ hwcfg2_data_t hwcfg2; ++ hwcfg3_data_t hwcfg3; ++ hwcfg4_data_t hwcfg4; ++ fifosize_data_t hptxfsiz; ++ ++ /** Host and Device Configuration -- stored here for convenience.*/ ++ hcfg_data_t hcfg; ++ dcfg_data_t dcfg; ++ ++ /** The operational State, during transations ++ * (a_host>>a_peripherial and b_device=>b_host) this may not ++ * match the core but allows the software to determine ++ * transitions. ++ */ ++ uint8_t op_state; ++ ++ /** Test mode for PET testing */ ++ uint8_t test_mode; ++ ++ /** ++ * Set to 1 if the HCD needs to be restarted on a session request ++ * interrupt. This is required if no connector ID status change has ++ * occurred since the HCD was last disconnected. ++ */ ++ uint8_t restart_hcd_on_session_req; ++ ++ /** HCD callbacks */ ++ /** A-Device is a_host */ ++#define A_HOST (1) ++ /** A-Device is a_suspend */ ++#define A_SUSPEND (2) ++ /** A-Device is a_peripherial */ ++#define A_PERIPHERAL (3) ++ /** B-Device is operating as a Peripheral. */ ++#define B_PERIPHERAL (4) ++ /** B-Device is operating as a Host. */ ++#define B_HOST (5) ++ ++ /** HCD callbacks */ ++ struct fh_otg_cil_callbacks *hcd_cb; ++ /** PCD callbacks */ ++ struct fh_otg_cil_callbacks *pcd_cb; ++ ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t p_tx_msk; ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t tx_msk; ++ ++ /** Workqueue object used for handling several interrupts */ ++ fh_workq_t *wq_otg; ++ ++ /** Timer object used for handling "Wakeup Detected" Interrupt */ ++ fh_timer_t *wkp_timer; ++ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ ++ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; ++ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; ++ fh_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; ++#ifdef DEBUG ++ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; ++ ++ hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS]; ++ fh_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS]; ++ ++ uint32_t hfnum_7_samples; ++ uint64_t hfnum_7_frrem_accum; ++ uint32_t hfnum_0_samples; ++ uint64_t hfnum_0_frrem_accum; ++ uint32_t hfnum_other_samples; ++ uint64_t hfnum_other_frrem_accum; ++#endif ++ ++#ifdef FH_UTE_CFI ++ uint16_t pwron_rxfsiz; ++ uint16_t pwron_gnptxfsiz; ++ uint16_t pwron_txfsiz[15]; ++ ++ uint16_t init_rxfsiz; ++ uint16_t init_gnptxfsiz; ++ uint16_t init_txfsiz[15]; ++#endif ++ ++ /** Lx state of device */ ++ fh_otg_lx_state_e lx_state; ++ ++ /** Saved Core Global registers */ ++ struct fh_otg_global_regs_backup *gr_backup; ++ /** Saved Host registers */ ++ struct fh_otg_host_regs_backup *hr_backup; ++ /** Saved Device registers */ ++ struct fh_otg_dev_regs_backup *dr_backup; ++ ++ /** Power Down Enable */ ++ uint32_t power_down; ++ ++ /** ADP support Enable */ ++ uint32_t adp_enable; ++ ++ /** ADP structure object */ ++ fh_otg_adp_t adp; ++ ++ /** hibernation/suspend flag */ ++ int hibernation_suspend; ++ ++ /** Device mode extended hibernation flag */ ++ int xhib; ++ ++ /** OTG revision supported */ ++ uint32_t otg_ver; ++ ++ /** OTG status flag used for HNP polling */ ++ uint8_t otg_sts; ++ ++ /** Pointer to either hcd->lock or pcd->lock */ ++ fh_spinlock_t *lock; ++ ++ /** Start predict NextEP based on Learning Queue if equal 1, ++ * also used as counter of disabled NP IN EP's */ ++ uint8_t start_predict; ++ ++ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and ++ * active, 0xff otherwise */ ++ uint8_t nextep_seq[MAX_EPS_CHANNELS]; ++ ++ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ ++ uint8_t first_in_nextep_seq; ++ ++ /** Frame number while entering to ISR - needed for ISOCs **/ ++ uint32_t frame_num; ++ ++ /** Flag to not perform ADP probing if IDSTS event happened */ ++ uint8_t stop_adpprb; ++ ++}; ++ ++#ifdef DEBUG ++/* ++ * This function is called when transfer is timed out. ++ */ ++extern void hc_xfer_timeout(void *ptr); ++#endif ++ ++/* ++ * This function is called when transfer is timed out on endpoint. ++ */ ++extern void ep_xfer_timeout(void *ptr); ++ ++/* ++ * The following functions are functions for works ++ * using during handling some interrupts ++ */ ++extern void w_conn_id_status_change(void *p); ++ ++extern void w_wakeup_detected(void *p); ++ ++/** Saves global register values into system memory. */ ++extern int fh_otg_save_global_regs(fh_otg_core_if_t * core_if); ++/** Saves device register values into system memory. */ ++extern int fh_otg_save_dev_regs(fh_otg_core_if_t * core_if); ++/** Saves host register values into system memory. */ ++extern int fh_otg_save_host_regs(fh_otg_core_if_t * core_if); ++/** Restore global register values. */ ++extern int fh_otg_restore_global_regs(fh_otg_core_if_t * core_if); ++/** Restore host register values. */ ++extern int fh_otg_restore_host_regs(fh_otg_core_if_t * core_if, int reset); ++/** Restore device register values. */ ++extern int fh_otg_restore_dev_regs(fh_otg_core_if_t * core_if, ++ int rem_wakeup); ++extern int restore_lpm_i2c_regs(fh_otg_core_if_t * core_if); ++extern int restore_essential_regs(fh_otg_core_if_t * core_if, int rmode, ++ int is_host); ++ ++extern int fh_otg_host_hibernation_restore(fh_otg_core_if_t * core_if, ++ int restore_mode, int reset); ++extern int fh_otg_device_hibernation_restore(fh_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/* ++ * The following functions support initialization of the CIL driver component ++ * and the FH_otg controller. ++ */ ++extern void fh_otg_core_host_init(fh_otg_core_if_t * _core_if); ++extern void fh_otg_core_dev_init(fh_otg_core_if_t * _core_if); ++ ++/** @name Device CIL Functions ++ * The following functions support managing the FH_otg controller in device ++ * mode. ++ */ ++/**@{*/ ++extern void fh_otg_wakeup(fh_otg_core_if_t * _core_if); ++extern void fh_otg_read_setup_packet(fh_otg_core_if_t * _core_if, ++ uint32_t * _dest); ++extern uint32_t fh_otg_get_frame_number(fh_otg_core_if_t * _core_if); ++extern void fh_otg_ep0_activate(fh_otg_core_if_t * _core_if, fh_ep_t * _ep); ++extern void fh_otg_ep_activate(fh_otg_core_if_t * _core_if, fh_ep_t * _ep); ++extern void fh_otg_ep_deactivate(fh_otg_core_if_t * _core_if, fh_ep_t * _ep); ++extern void fh_otg_ep_start_transfer(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep); ++extern void fh_otg_ep_start_zl_transfer(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep); ++extern void fh_otg_ep0_start_transfer(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep); ++extern void fh_otg_ep0_continue_transfer(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep); ++extern void fh_otg_ep_write_packet(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep, int _dma); ++extern void fh_otg_ep_set_stall(fh_otg_core_if_t * _core_if, fh_ep_t * _ep); ++extern void fh_otg_ep_clear_stall(fh_otg_core_if_t * _core_if, ++ fh_ep_t * _ep); ++extern void fh_otg_enable_device_interrupts(fh_otg_core_if_t * _core_if); ++ ++#ifdef FH_EN_ISOC ++extern void fh_otg_iso_ep_start_frm_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep); ++extern void fh_otg_iso_ep_start_buf_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep); ++#endif /* FH_EN_ISOC */ ++/**@}*/ ++ ++/** @name Host CIL Functions ++ * The following functions support managing the FH_otg controller in host ++ * mode. ++ */ ++/**@{*/ ++extern void fh_otg_hc_init(fh_otg_core_if_t * _core_if, fh_hc_t * _hc); ++extern void fh_otg_hc_halt(fh_otg_core_if_t * _core_if, ++ fh_hc_t * _hc, fh_otg_halt_status_e _halt_status); ++extern void fh_otg_hc_cleanup(fh_otg_core_if_t * _core_if, fh_hc_t * _hc); ++extern void fh_otg_hc_start_transfer(fh_otg_core_if_t * _core_if, ++ fh_hc_t * _hc); ++extern int fh_otg_hc_continue_transfer(fh_otg_core_if_t * _core_if, ++ fh_hc_t * _hc); ++extern void fh_otg_hc_do_ping(fh_otg_core_if_t * _core_if, fh_hc_t * _hc); ++extern void fh_otg_hc_write_packet(fh_otg_core_if_t * _core_if, ++ fh_hc_t * _hc); ++extern void fh_otg_enable_host_interrupts(fh_otg_core_if_t * _core_if); ++extern void fh_otg_disable_host_interrupts(fh_otg_core_if_t * _core_if); ++ ++extern void fh_otg_hc_start_transfer_ddma(fh_otg_core_if_t * core_if, ++ fh_hc_t * hc); ++ ++extern uint32_t calc_frame_interval(fh_otg_core_if_t * core_if); ++extern int fh_otg_check_haps_status(fh_otg_core_if_t * core_if); ++ ++/* Macro used to clear one channel interrupt */ ++#define clear_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcint_data_t hcint_clear = {.d32 = 0}; \ ++ hcint_clear.b._intr_ = 1; \ ++ FH_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \ ++} while (0) ++ ++/* ++ * Macro used to disable one channel interrupt. Channel interrupts are ++ * disabled when the channel is halted or released by the interrupt handler. ++ * There is no need to handle further interrupts of that type until the ++ * channel is re-assigned. In fact, subsequent handling may cause crashes ++ * because the channel structures are cleaned up when the channel is released. ++ */ ++#define disable_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ ++ hcintmsk.b._intr_ = 1; \ ++ FH_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ ++} while (0) ++ ++/** ++ * This function Reads HPRT0 in preparation to modify. It keeps the ++ * WC bits 0 so that if they are read as 1, they won't clear when you ++ * write it back ++ */ ++static inline uint32_t fh_otg_read_hprt0(fh_otg_core_if_t * _core_if) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = FH_READ_REG32(_core_if->host_if->hprt0); ++ hprt0.b.prtena = 0; ++ hprt0.b.prtconndet = 0; ++ hprt0.b.prtenchng = 0; ++ hprt0.b.prtovrcurrchng = 0; ++ return hprt0.d32; ++} ++ ++/**@}*/ ++ ++/** @name Common CIL Functions ++ * The following functions support managing the FH_otg controller in either ++ * device or host mode. ++ */ ++/**@{*/ ++ ++extern void fh_otg_read_packet(fh_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes); ++ ++extern void fh_otg_flush_tx_fifo(fh_otg_core_if_t * _core_if, const int _num); ++extern void fh_otg_flush_rx_fifo(fh_otg_core_if_t * _core_if); ++extern void fh_otg_core_reset(fh_otg_core_if_t * _core_if); ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t fh_otg_read_core_intr(fh_otg_core_if_t * core_if) ++{ ++ return (FH_READ_REG32(&core_if->core_global_regs->gintsts) & ++ FH_READ_REG32(&core_if->core_global_regs->gintmsk)); ++} ++ ++/** ++ * This function returns the OTG Interrupt register. ++ */ ++static inline uint32_t fh_otg_read_otg_intr(fh_otg_core_if_t * core_if) ++{ ++ return (FH_READ_REG32(&core_if->core_global_regs->gotgint)); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the IN endpoint interrupt bits. ++ */ ++static inline uint32_t fh_otg_read_dev_all_in_ep_intr(fh_otg_core_if_t * ++ core_if) ++{ ++ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ FH_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = FH_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ return (v & 0xffff); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the OUT endpoint interrupt bits. ++ */ ++static inline uint32_t fh_otg_read_dev_all_out_ep_intr(fh_otg_core_if_t * ++ core_if) ++{ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ FH_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = FH_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ ++ return ((v & 0xffff0000) >> 16); ++} ++ ++/** ++ * This function returns the Device IN EP Interrupt register ++ */ ++static inline uint32_t fh_otg_read_dev_in_ep_intr(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep) ++{ ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ uint32_t v, msk, emp; ++ ++ if (core_if->multiproc_int_enable) { ++ msk = ++ FH_READ_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[ep->num]); ++ emp = ++ FH_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = FH_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } else { ++ msk = FH_READ_REG32(&dev_if->dev_global_regs->diepmsk); ++ emp = ++ FH_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = FH_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } ++ ++ return v; ++} ++ ++/** ++ * This function returns the Device OUT EP Interrupt register ++ */ ++static inline uint32_t fh_otg_read_dev_out_ep_intr(fh_otg_core_if_t * ++ _core_if, fh_ep_t * _ep) ++{ ++ fh_otg_dev_if_t *dev_if = _core_if->dev_if; ++ uint32_t v; ++ doepmsk_data_t msk = {.d32 = 0 }; ++ ++ if (_core_if->multiproc_int_enable) { ++ msk.d32 = ++ FH_READ_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[_ep->num]); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = FH_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } else { ++ msk.d32 = FH_READ_REG32(&dev_if->dev_global_regs->doepmsk); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = FH_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } ++ return v; ++} ++ ++/** ++ * This function returns the Host All Channel Interrupt register ++ */ ++static inline uint32_t fh_otg_read_host_all_channels_intr(fh_otg_core_if_t * ++ _core_if) ++{ ++ return (FH_READ_REG32(&_core_if->host_if->host_global_regs->haint)); ++} ++ ++static inline uint32_t fh_otg_read_host_channel_intr(fh_otg_core_if_t * ++ _core_if, fh_hc_t * _hc) ++{ ++ return (FH_READ_REG32 ++ (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); ++} ++ ++/** ++ * This function returns the mode of the operation, host or device. ++ * ++ * @return 0 - Device Mode, 1 - Host Mode ++ */ ++static inline uint32_t fh_otg_mode(fh_otg_core_if_t * _core_if) ++{ ++ return (FH_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1); ++} ++ ++/**@}*/ ++ ++/** ++ * FH_otg CIL callback structure. This structure allows the HCD and ++ * PCD to register functions used for starting and stopping the PCD ++ * and HCD for role change on for a DRD. ++ */ ++typedef struct fh_otg_cil_callbacks { ++ /** Start function for role change */ ++ int (*start) (void *_p); ++ /** Stop Function for role change */ ++ int (*stop) (void *_p); ++ /** Disconnect Function for role change */ ++ int (*disconnect) (void *_p); ++ /** Resume/Remote wakeup Function */ ++ int (*resume_wakeup) (void *_p); ++ /** Suspend function */ ++ int (*suspend) (void *_p); ++ /** Session Start (SRP) */ ++ int (*session_start) (void *_p); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ /** Sleep (switch to L0 state) */ ++ int (*sleep) (void *_p); ++#endif ++ /** Pointer passed to start() and stop() */ ++ void *p; ++} fh_otg_cil_callbacks_t; ++ ++extern void fh_otg_cil_register_pcd_callbacks(fh_otg_core_if_t * _core_if, ++ fh_otg_cil_callbacks_t * _cb, ++ void *_p); ++extern void fh_otg_cil_register_hcd_callbacks(fh_otg_core_if_t * _core_if, ++ fh_otg_cil_callbacks_t * _cb, ++ void *_p); ++ ++void fh_otg_initiate_srp(void * core_if); ++ ++////////////////////////////////////////////////////////////////////// ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_start(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->start) { ++ core_if->hcd_cb->start(core_if->hcd_cb->p); ++ } ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_stop(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->stop) { ++ core_if->hcd_cb->stop(core_if->hcd_cb->p); ++ } ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_disconnect(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { ++ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); ++ } ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_session_start(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { ++ core_if->hcd_cb->session_start(core_if->hcd_cb->p); ++ } ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++/** ++ * Inform the HCD about LPM sleep. ++ * Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_sleep(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { ++ core_if->hcd_cb->sleep(core_if->hcd_cb->p); ++ } ++} ++#endif ++ ++/** Resume the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_hcd_resume(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { ++ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); ++ } ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_pcd_start(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->start) { ++ core_if->pcd_cb->start(core_if->pcd_cb->p); ++ } ++} ++ ++/** Stop the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_pcd_stop(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->stop) { ++ core_if->pcd_cb->stop(core_if->pcd_cb->p); ++ } ++} ++ ++/** Suspend the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_pcd_suspend(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { ++ core_if->pcd_cb->suspend(core_if->pcd_cb->p); ++ } ++} ++ ++/** Resume the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static inline void cil_pcd_resume(fh_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil_intr.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil_intr.c +new file mode 100644 +index 00000000..4b1cd2e4 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_cil_intr.c +@@ -0,0 +1,1739 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_cil_intr.c $ ++ * $Revision: #40 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the FH_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * This file contains the Common Interrupt handlers. ++ */ ++#include "../fh_common_port/fh_os.h" ++#include "fh_otg_regs.h" ++#include "fh_otg_cil.h" ++#include "fh_otg_driver.h" ++#include "fh_otg_pcd.h" ++#include "fh_otg_hcd.h" ++ ++#ifdef DEBUG ++inline const char *op_state_str(fh_otg_core_if_t * core_if) ++{ ++ return (core_if->op_state == A_HOST ? "a_host" : ++ (core_if->op_state == A_SUSPEND ? "a_suspend" : ++ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : ++ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : ++ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); ++} ++#endif ++ ++/** This function will log a debug message ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++int32_t fh_otg_handle_mode_mismatch_intr(fh_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ FH_WARN("Mode Mismatch Interrupt: currently in %s mode\n", ++ fh_otg_mode(core_if) ? "Host" : "Device"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.modemismatch = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function handles the OTG Interrupts. It reads the OTG ++ * Interrupt Register (GOTGINT) to determine what interrupt has ++ * occurred. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++int32_t fh_otg_handle_otg_intr(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gotgint_data_t gotgint; ++ gotgctl_data_t gotgctl; ++ gintmsk_data_t gintmsk; ++ gpwrdn_data_t gpwrdn; ++ ++ gotgint.d32 = FH_READ_REG32(&global_regs->gotgint); ++ gotgctl.d32 = FH_READ_REG32(&global_regs->gotgctl); ++ FH_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, ++ op_state_str(core_if)); ++ ++ if (gotgint.b.sesenddet) { ++ FH_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session End Detected++ (%s)\n", ++ op_state_str(core_if)); ++ gotgctl.d32 = FH_READ_REG32(&global_regs->gotgctl); ++ ++ if (core_if->op_state == B_HOST) { ++ if (core_if->adp_enable && FH_WORKQ_PENDING(core_if->wq_otg)) { ++ ++ /* During ST_B_ADP test after HNP HSOTG tries to go to B_HOST ++ * mode but PET is not expecting fully functional host at that ++ * point and switches off the VBUS expecting immediate ADP probe */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_mdelay(20); ++ fh_otg_adp_probe_start(core_if); ++ goto exit_interrupt; ++ } ++ cil_pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ /* If not B_HOST and Device HNP still set. HNP ++ * Did not succeed!*/ ++ if (gotgctl.b.devhnpen) { ++ FH_DEBUGPL(DBG_ANY, "Session End Detected\n"); ++ __FH_ERROR("Device Not Connected/Responding!\n"); ++ } ++ ++ /* If Session End Detected the B-Cable has ++ * been disconnected. */ ++ /* Reset PCD and Gadget driver to a ++ * clean state. */ ++ core_if->lx_state = FH_OTG_L0; ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ FH_SPINLOCK(core_if->lock); ++ ++ if (core_if->otg_ver) { ++ /** PET testing*/ ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ if (core_if->test_mode == 6) { ++ FH_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, fh_otg_initiate_srp, ++ core_if, 3000, "initate SRP"); //manukz: old value was 50 ++ core_if->test_mode = 0; ++ } else if (core_if->adp_enable) { ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_otg_adp_sense_start(core_if); ++ } ++ } ++ } ++exit_interrupt: ++ if (core_if->otg_ver == 0) { ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } ++ if (gotgint.b.sesreqsucstschng) { ++ FH_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session Reqeust Success Status Change++\n"); ++ gotgctl.d32 = FH_READ_REG32(&global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) { ++ ++ if ((core_if->core_params->phy_type == ++ FH_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { ++ core_if->srp_success = 1; ++ } else { ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_resume(core_if); ++ FH_SPINLOCK(core_if->lock); ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, ++ gotgctl.d32, 0); ++ } ++ } ++ } ++ if (gotgint.b.hstnegsucstschng) { ++ /* Print statements during the HNP interrupt handling ++ * can cause it to fail.*/ ++ gotgctl.d32 = FH_READ_REG32(&global_regs->gotgctl); ++ /* WA for 3.00a- HW is not setting cur_mode, even sometimes ++ * this does not help*/ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ fh_udelay(100); ++ if (gotgctl.b.hstnegscs) { ++ if (fh_otg_is_host_mode(core_if)) { ++ core_if->op_state = B_HOST; ++ /* ++ * Need to disable SOF interrupt immediately. ++ * When switching from device to host, the PCD ++ * interrupt handler won't handle the ++ * interrupt if host mode is already set. The ++ * HCD interrupt handler won't get called if ++ * the HCD state is HALT. This means that the ++ * interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ /* To avoid multiple USB Suspend interrupts during ++ * OTG 2.0 role change */ ++ if (core_if->otg_ver) ++ gintmsk.b.usbsuspend = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, ++ gintmsk.d32, 0); ++ /* Call callback function with spin lock released */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) { ++ fh_mdelay(100); ++ cil_hcd_start(core_if); ++ cil_hcd_session_start(core_if); ++ } else { ++ cil_hcd_start(core_if); ++ } ++ FH_SPINLOCK(core_if->lock); ++ } ++ } else { ++ gotgctl.d32 = 0; ++ gotgctl.b.hnpreq = 1; ++ gotgctl.b.devhnpen = 1; ++ FH_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ FH_DEBUGPL(DBG_ANY, "HNP Failed\n"); ++ __FH_ERROR("Device Not Connected/Responding\n"); ++ } ++ } ++ if (gotgint.b.hstnegdet) { ++ /* The disconnect interrupt is set at the same time as ++ * Host Negotiation Detected. During the mode ++ * switch all interrupts are cleared so the disconnect ++ * interrupt handler will not get executed. ++ */ ++ FH_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Host Negotiation Detected++ (%s)\n", ++ (fh_otg_is_host_mode(core_if) ? "Host" : ++ "Device")); ++ if (fh_otg_is_device_mode(core_if)) { ++ FH_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", ++ core_if->op_state); ++ FH_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = A_PERIPHERAL; ++ } else { ++ /* ++ * Need to disable SOF interrupt immediately. When ++ * switching from device to host, the PCD interrupt ++ * handler won't handle the interrupt if host mode is ++ * already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that ++ * the interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ if (gotgint.b.adevtoutchng) { ++ FH_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "A-Device Timeout Change++\n"); ++ } ++ if (gotgint.b.debdone) { ++ FH_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); ++ /* Need to power off VBUS after 10s if OTG2 non-hnp capable host*/ ++ if (core_if->otg_ver && core_if->op_state == A_PERIPHERAL) { ++ FH_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ ++ //if(core_if->otg_ver == 1) ++ //cil_hcd_session_start(core_if); mvardan (for ADP issue) ++ } ++ ++ /* Clear GOTGINT */ ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32); ++ ++ return 1; ++} ++ ++void w_conn_id_status_change(void *p) ++{ ++ fh_otg_core_if_t *core_if = p; ++ uint32_t count = 0; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ gotgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ FH_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); ++ FH_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl.b.conidsts) { ++ gotgctl_data_t gotgctl_local; ++ /* Wait for switch to device mode. */ ++ while (!fh_otg_is_device_mode(core_if)) { ++ gotgctl_local.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ FH_DEBUGPL(DBG_ANY, "Waiting for Peripheral Mode, Mode=%s count = %d gotgctl=%08x\n", ++ (fh_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral"), count, gotgctl_local.d32); ++ fh_mdelay(1); //vahrama previous value was 100 ++ if(!gotgctl_local.b.conidsts) ++ goto host; ++ if (++count > 10000) ++ break; ++ } ++ FH_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = B_PERIPHERAL; ++ if(core_if->otg_ver == 0) ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++host: ++ /* A-Device connector (Host Mode) */ ++ while (!fh_otg_is_host_mode(core_if)) { ++ FH_DEBUGPL(DBG_ANY,"Waiting for Host Mode, Mode=%s\n", ++ (fh_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ fh_mdelay(1); //vahrama previously was 100 ++ if (++count > 10000) ++ break; ++ } ++ FH_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = A_HOST; ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ if (core_if->otg_ver) ++ /* To power off the bus in 10s from the beginning ++ * of test while denounce has not come yet */ ++ cil_hcd_session_start(core_if); ++ else ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++} ++ ++/** ++ * This function handles the Connector ID Status Change Interrupt. It ++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this ++ * is a Device to Host Mode transition or a Host Mode to Device ++ * Transition. ++ * ++ * This only occurs when the cable is connected/removed from the PHY ++ * connector. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++int32_t fh_otg_handle_conn_id_status_change_intr(fh_otg_core_if_t * core_if) ++{ ++ ++ /* ++ * Need to disable SOF interrupt immediately. If switching from device ++ * to host, the PCD interrupt handler won't handle the interrupt if ++ * host mode is already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that the interrupt does ++ * not get handled and Linux complains loudly. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ gintmsk.b.sofintr = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ FH_DEBUGPL(DBG_CIL, ++ " ++Connector ID Status Change Interrupt++ (%s)\n", ++ (fh_otg_is_host_mode(core_if) ? "Host" : "Device")); ++ ++ FH_SPINUNLOCK(core_if->lock); ++ ++ /* Needed to avoit conn_id_status change duplication */ ++ //if (core_if->otg_ver) ++ //fh_mdelay(50); ++ /* ++ * Need to schedule a work, as there are possible DELAY function calls ++ * Release lock before scheduling workq as it holds spinlock during scheduling ++ */ ++ ++ FH_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, ++ core_if, "connection id status change"); ++ FH_SPINLOCK(core_if->lock); ++ ++ /* Set flag and clear interrupt */ ++ gintsts.b.conidstschng = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device is initiating the Session ++ * Request Protocol to request the host to turn on bus power so a new ++ * session can begin. The handler responds by turning on bus power. If ++ * the FH_otg controller is in low power mode, the handler brings the ++ * controller out of low power mode before turning on bus power. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++int32_t fh_otg_handle_session_req_intr(fh_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++#ifndef FH_HOST_ONLY ++ FH_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ FH_DEBUGPL(DBG_PCD, "SRP: Device mode\n"); ++ gotgctl.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) ++ FH_PRINTF("SRP Success\n"); ++ else ++ FH_PRINTF("SRP Fail\n"); ++ if (core_if->otg_ver) { ++ gotgctl.d32 = 0 ; ++ gotgctl.b.devhnpen = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ } else { ++ hprt0_data_t hprt0; ++ FH_PRINTF("SRP: Host mode\n"); ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sessreqintr = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++void w_wakeup_detected(void *p) ++{ ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) p; ++ /* ++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms ++ * so that OPT tests pass with all PHYs). ++ */ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++#if 0 ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ fh_udelay(10); ++#endif //0 ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ FH_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); ++// fh_mdelay(70); ++ hprt0.b.prtres = 0; /* Resume */ ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ FH_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", ++ FH_READ_REG32(core_if->host_if->hprt0)); ++ ++ cil_hcd_resume(core_if); ++ ++ /** Change to L0 state*/ ++ core_if->lx_state = FH_OTG_L0; ++} ++ ++/** ++ * This interrupt indicates that the FH_otg controller has detected a ++ * resume or remote wakeup sequence. If the FH_otg controller is in ++ * low power mode, the handler must brings the controller out of low ++ * power mode. The controller automatically begins resume ++ * signaling. The handler schedules a time to stop resume signaling. ++ */ ++int32_t fh_otg_handle_wakeup_detected_intr(fh_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ FH_DEBUGPL(DBG_ANY, ++ "++Resume and Remote Wakeup Detected Interrupt++\n"); ++ ++ FH_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state); ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ FH_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ dsts)); ++ if (core_if->lx_state == FH_OTG_L2) { ++#ifdef PARTIAL_POWER_DOWN ++ if (core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = FH_READ_REG32(core_if->pcgcctl); ++ FH_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", ++ power.d32); ++ ++ power.b.stoppclk = 0; ++ FH_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.pwrclmp = 0; ++ FH_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 0; ++ FH_WRITE_REG32(core_if->pcgcctl, power.d32); ++ } ++#endif ++ /* Clear the Remote Wakeup Signaling */ ++ dctl.b.rmtwkupsig = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ ++ FH_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ FH_SPINLOCK(core_if->lock); ++ } else { ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.en_utmi_sleep = 0; ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ /** Change to L0 state*/ ++ core_if->lx_state = FH_OTG_L0; ++ } else { ++ if (core_if->lx_state != FH_OTG_L1) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ FH_TIMER_SCHEDULE(core_if->wkp_timer, 71); ++ } else { ++ /** Change to L0 state*/ ++ core_if->lx_state = FH_OTG_L0; ++ } ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.wkupintr = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * Device disconnect. ++ */ ++static int32_t fh_otg_handle_pwrdn_disconnect_intr(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ gpwrdn_temp.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ FH_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * remote wakeup sequence. ++ */ ++static int32_t fh_otg_handle_pwrdn_wakeup_detected_intr(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ FH_DEBUGPL(DBG_ANY, ++ "++Powerdown Remote Wakeup Detected Interrupt++\n"); ++ ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (gpwrdn.b.idsts) { // Device Mode ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ fh_otg_device_hibernation_restore(core_if, 0, 0); ++ } ++ } else { ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ fh_otg_host_hibernation_restore(core_if, 1, 0); ++ } ++ } ++ return 1; ++} ++ ++static int32_t fh_otg_handle_pwrdn_idsts_change(fh_otg_device_t * otg_dev) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ fh_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ FH_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ gpwrdn_temp.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ FH_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; ++ if (gpwrdn.b.dis_vbus == 1) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ } ++ ++ if (core_if->adp_enable) { ++ uint8_t is_host = 0; ++ FH_SPINUNLOCK(core_if->lock); ++ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ ++#ifndef FH_HOST_ONLY ++ if (gpwrdn_temp.b.idsts) ++ core_if->lock = otg_dev->pcd->lock; ++#endif ++#ifndef FH_DEVICE_ONLY ++ if (!gpwrdn_temp.b.idsts) { ++ core_if->lock = otg_dev->hcd->lock; ++ is_host = 1; ++ } ++#endif ++ FH_DEBUGPL(DBG_ANY, "RESTART ADP\n"); ++ if (core_if->adp.probe_enabled) ++ fh_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ fh_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ FH_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ FH_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ /* Do not need to reset ADP if we are coming back ++ * to the device mode after HNP. This is needed ++ * not to perform SRP after reverse, just do ADP ++ * probe and compare the RTIM values with the one ++ * before HNP */ ++ if (core_if->op_state != B_HOST) { ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ } ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ ++ /* Disable PMU and restart ADP */ ++ gpwrdn_temp.d32 = 0; ++ gpwrdn_temp.b.pmuactv = 1; ++ gpwrdn_temp.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_mdelay(110); ++ fh_otg_adp_start(core_if, is_host); ++ FH_SPINLOCK(core_if->lock); ++ } ++ ++ return 1; ++} ++ ++static int32_t fh_otg_handle_pwrdn_session_change(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ FH_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ if ((otg_cap_param != FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param != FH_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) && ++ gpwrdn.b.bsessvld == 0) { ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ if (otg_cap_param == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param == FH_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ fh_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp_enable && core_if->op_state != A_HOST){ ++ fh_otg_adp_probe_stop(core_if); ++ if (FH_WORKQ_PENDING(core_if->wq_otg)) ++ core_if->stop_adpprb = 1; ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ cil_pcd_start(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * status change either on IDDIG or BSessVld. ++ */ ++static uint32_t fh_otg_handle_pwrdn_stschng_intr(fh_otg_device_t * otg_dev) ++{ ++ int retval; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ fh_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ FH_DEBUGPL(DBG_CIL, "%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (core_if->hibernation_suspend <= 0) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } else ++ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; ++ ++ } else { ++ gpwrdn_temp.d32 = core_if->adp.gpwrdn; ++ } ++ ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { ++ retval = fh_otg_handle_pwrdn_idsts_change(otg_dev); ++ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { ++ retval = fh_otg_handle_pwrdn_session_change(core_if); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * SRP. ++ */ ++static int32_t fh_otg_handle_pwrdn_srp_intr(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ ++ FH_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++#ifdef FH_DEV_SRPCAP ++ if (core_if->pwron_timer_started) { ++ core_if->pwron_timer_started = 0; ++ FH_TIMER_CANCEL(core_if->pwron_timer); ++ } ++#endif ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Programm Disable VBUS to 0 */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Initialize the core as Host */ ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ /* Do not need to du anything if this is "old" SRP and we are already ++ * in the normal mode of operation */ ++ if(core_if->adp_enable) { ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (!gpwrdn.b.pmuactv) { ++ return 1; ++ } ++ ++ fh_otg_adp_probe_stop(core_if); ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** This interrupt indicates that restore command after Hibernation ++ * was completed by the core. */ ++int32_t fh_otg_handle_restore_done_intr(fh_otg_core_if_t * core_if) ++{ ++ pcgcctl_data_t pcgcctl; ++ FH_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); ++ ++ //TODO De-assert restore signal. 8.a ++ pcgcctl.d32 = FH_READ_REG32(core_if->pcgcctl); ++ if (pcgcctl.b.restoremode == 1) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ /* ++ * If restore mode is Remote Wakeup, ++ * unmask Remote Wakeup interrupt. ++ */ ++ gintmsk.b.wkupintr = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device has been disconnected from ++ * the root port. ++ */ ++int32_t fh_otg_handle_disconnect_intr(fh_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ FH_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", ++ (fh_otg_is_host_mode(core_if) ? "Host" : "Device"), ++ op_state_str(core_if)); ++ ++/** @todo Consolidate this if statement. */ ++#ifndef FH_HOST_ONLY ++ if (core_if->op_state == B_HOST) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else if (fh_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.hstsethnpen == 1) { ++ /* Do nothing, if HNP in process the OTG ++ * interrupt "Host Negotiation Detected" ++ * interrupt will do the mode switch. ++ */ ++ } else if (gotgctl.b.devhnpen == 0) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ FH_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); ++ } ++ } else { ++ if (core_if->op_state == A_HOST) { ++ /* A-Cable still connected but device disconnected. */ ++ cil_hcd_disconnect(core_if); ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ cil_hcd_stop(core_if); ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_otg_adp_probe_start(core_if); ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32 ++ (&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ } ++ } ++ } ++#endif ++ /* Change to L3(OFF) state */ ++ core_if->lx_state = FH_OTG_L3; ++ ++ gintsts.d32 = 0; ++ gintsts.b.disconnect = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that SUSPEND state has been detected on ++ * the USB. ++ * ++ * For HNP the USB Suspend interrupt signals the change from ++ * "a_peripheral" to "a_host". ++ * ++ * When power management is enabled the core will be put in low power ++ * mode. ++ */ ++int32_t fh_otg_handle_usb_suspend_intr(fh_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ gintsts_data_t gintsts; ++ dcfg_data_t dcfg; ++ ++ FH_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); ++ ++ if ((core_if->otg_ver == 1) && (core_if->op_state == A_PERIPHERAL)) { ++ core_if->lx_state = FH_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++ } ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ /* Check the Device status register to determine if the Suspend ++ * state is active. */ ++ dsts.d32 = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ FH_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); ++ FH_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " ++ "HWCFG4.power Optimize=%d\n", ++ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); ++ ++#ifdef PARTIAL_POWER_DOWN ++/** @todo Add a module parameter for power management. */ ++ ++ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ FH_DEBUGPL(DBG_CIL, "suspend\n"); ++ ++ power.b.pwrclmp = 1; ++ FH_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ power.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ } else { ++ FH_DEBUGPL(DBG_ANY, "disconnect?\n"); ++ } ++#endif ++ /* PCD callback for suspend. Release the lock inside of callback function */ ++ cil_pcd_suspend(core_if); ++ if (core_if->power_down == 2) { ++ dcfg.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ FH_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); ++ FH_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != FH_OTG_L3 && dcfg.b.devaddr) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = FH_OTG_L2; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ FH_PRINTF("Start of hibernation completed\n"); ++ fh_otg_save_global_regs(core_if); ++ fh_otg_save_dev_regs(core_if); ++ ++ gusbcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ fh_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ fh_udelay(10); ++ } ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ /* Enable interrupts from wake up logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Unmask device mode interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Enable Power Down Clamp */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ FH_PRINTF("Hibernation completed\n"); ++ ++ return 1; ++ } ++ } else if (core_if->power_down == 3) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dcfg.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ FH_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); ++ FH_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != FH_OTG_L3 && dcfg.b.devaddr) { ++ FH_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); ++ core_if->xhib = 1; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ ++ fh_otg_save_global_regs(core_if); ++ fh_otg_save_dev_regs(core_if); ++ ++ /* Wait for 10 PHY clocks */ ++ fh_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ FH_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); ++ ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_switch = 1; ++ core_if->gr_backup->xhib_gpwrdn = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->gr_backup->xhib_pcgcctl = FH_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ FH_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); ++ ++ return 1; ++ } ++ } ++ if ((core_if->otg_ver == 1) && (core_if->core_params->otg_cap == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = FH_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.devhnpen && core_if->otg_ver == 1){ ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ fh_mdelay(5); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.devhnpen = 1; ++ gotgctl.b.hnpreq = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32); ++ } ++ } ++ } else { ++ if (core_if->op_state == A_PERIPHERAL) { ++ FH_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ FH_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ FH_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = FH_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++static int32_t fh_otg_handle_xhib_exit_intr(fh_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ ++ fh_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ FH_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); ++ ++ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ fh_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; ++ gpwrdn.b.restore = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); ++ fh_udelay(10); ++ ++ restore_lpm_i2c_regs(core_if); ++ ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 0; ++ pcgcctl.b.extnd_hiber_switch = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.d32 |= 0x608; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ fh_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 1; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ pcgcctl.b.rstpdwnmodule = 1; ++ pcgcctl.b.restoremode = 1; ++ FH_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ FH_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ return 1; ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++/** ++ * This function hadles LPM transaction received interrupt. ++ */ ++static int32_t fh_otg_handle_lpm_intr(fh_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ gintsts_data_t gintsts; ++ ++ if (!core_if->core_params->lpm_enable) { ++ FH_PRINTF("Unexpected LPM interrupt\n"); ++ } ++ ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ FH_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); ++ ++ if (fh_otg_is_host_mode(core_if)) { ++ cil_hcd_sleep(core_if); ++ } else { ++ ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ lpmcfg.b.hird_thres |= (1 << 4); ++ lpmcfg.b.en_utmi_sleep = 1; ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl,0,pcgcctl.d32); ++ ++ if(fh_otg_get_param_besl_enable(core_if)) { ++ lpmcfg.b.en_besl = 1; ++ } ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ ++ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ ++ fh_udelay(10); ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ /* Save the current state */ ++ core_if->lx_state = FH_OTG_L1; ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.lpmtranrcvd = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++#endif /* CONFIG_USB_FH_OTG_LPM */ ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t fh_otg_read_common_intr(fh_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ gintmsk_data_t gintmsk_common = {.d32 = 0 }; ++ gintmsk_common.b.wkupintr = 1; ++ gintmsk_common.b.sessreqintr = 1; ++ gintmsk_common.b.conidstschng = 1; ++ gintmsk_common.b.otgintr = 1; ++ gintmsk_common.b.modemismatch = 1; ++ gintmsk_common.b.disconnect = 1; ++ gintmsk_common.b.usbsuspend = 1; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ gintmsk_common.b.lpmtranrcvd = 1; ++#endif ++ gintmsk_common.b.restoredone = 1; ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gahbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ ++#ifdef DEBUG ++ /* if any common interrupts set */ ++ if (gintsts.d32 & gintmsk_common.d32) { ++ FH_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ gintsts.d32, gintmsk.d32); ++ } ++#endif ++ if (gahbcfg.b.glblintrmsk) ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ else ++ return 0; ++ ++} ++ ++/* MACRO for clearing interupt bits in GPWRDN register */ ++#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ ++do { \ ++ gpwrdn_data_t gpwrdn = {.d32=0}; \ ++ gpwrdn.b.__intr = 1; \ ++ FH_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ ++ 0, gpwrdn.d32); \ ++} while (0) ++ ++ ++/** ++ * Common interrupt handler. ++ * ++ * The common interrupts are those that occur in both Host and Device mode. ++ * This handler handles the following interrupts: ++ * - Mode Mismatch Interrupt ++ * - Disconnect Interrupt ++ * - OTG Interrupt ++ * - Connector ID Status Change Interrupt ++ * - Session Request Interrupt. ++ * - Resume / Remote Wakeup Detected Interrupt. ++ * - LPM Transaction Received Interrupt ++ * - ADP Transaction Received Interrupt ++ * ++ */ ++int32_t fh_otg_handle_common_intr(void *dev) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ fh_otg_device_t *otg_dev = dev; ++ fh_otg_core_if_t *core_if = otg_dev->core_if; ++ gpwrdn.d32 = FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (fh_otg_check_haps_status(core_if) == -1 ) { ++ FH_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ if (fh_otg_is_device_mode(core_if)) ++ core_if->frame_num = fh_otg_get_frame_number(core_if); ++ ++ if (core_if->lock) ++ FH_SPINLOCK(core_if->lock); ++ ++ if (core_if->power_down == 3 && core_if->xhib == 1) { ++ FH_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); ++ retval |= fh_otg_handle_xhib_exit_intr(core_if); ++ core_if->xhib = 2; ++ if (core_if->lock) ++ FH_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++ } ++ ++ if (core_if->hibernation_suspend <= 0) { ++ gintsts.d32 = fh_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) { ++ retval |= fh_otg_handle_mode_mismatch_intr(core_if); ++ } ++ if (gintsts.b.otgintr) { ++ retval |= fh_otg_handle_otg_intr(core_if); ++ } ++ if (gintsts.b.conidstschng) { ++ retval |= ++ fh_otg_handle_conn_id_status_change_intr(core_if); ++ } ++ if (gintsts.b.disconnect) { ++ retval |= fh_otg_handle_disconnect_intr(core_if); ++ } ++ if (gintsts.b.sessreqintr) { ++ retval |= fh_otg_handle_session_req_intr(core_if); ++ } ++ if (gintsts.b.wkupintr) { ++ retval |= fh_otg_handle_wakeup_detected_intr(core_if); ++ } ++ if (gintsts.b.usbsuspend) { ++ retval |= fh_otg_handle_usb_suspend_intr(core_if); ++ } ++#ifdef CONFIG_USB_FH_OTG_LPM ++ if (gintsts.b.lpmtranrcvd) { ++ retval |= fh_otg_handle_lpm_intr(core_if); ++ } ++#endif ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ if (core_if->power_down == 2) ++ core_if->hibernation_suspend = -1; ++ else if (core_if->power_down == 3 && core_if->xhib == 2) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ FH_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, 0xFFFFFFFF); ++ ++ FH_DEBUGPL(DBG_ANY, ++ "RESTORE DONE generated\n"); ++ ++ gpwrdn.b.restore = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ pcgcctl.b.rstpdwnmodule = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); ++ fh_udelay(50); ++ ++ dctl.b.pwronprgdone = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ fh_udelay(10); ++ ++ fh_otg_restore_global_regs(core_if); ++ fh_otg_restore_dev_regs(core_if, 0); ++ ++ dctl.d32 = 0; ++ dctl.b.pwronprgdone = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ fh_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = FH_OTG_L0; ++ core_if->xhib = 0; ++ ++ FH_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ FH_SPINLOCK(core_if->lock); ++ ++ } ++ ++ gintsts.b.restoredone = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ FH_PRINTF(" --Restore done interrupt received-- \n"); ++ retval |= 1; ++ } ++ if (gintsts.b.portintr && fh_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ retval |= 1; ++ ++ } ++ } else { ++ FH_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); ++ ++ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, disconn_det); ++ if (gpwrdn.b.linestate == 0) { ++ fh_otg_handle_pwrdn_disconnect_intr(core_if); ++ } else { ++ FH_PRINTF("Disconnect detected while linestate is not 0\n"); ++ } ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { ++ CLEAR_GPWRDN_INTR(core_if, lnstschng); ++ /* remote wakeup from hibernation */ ++ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { ++ fh_otg_handle_pwrdn_wakeup_detected_intr(core_if); ++ } else { ++ FH_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); ++ } ++ retval |= 1; ++ } ++ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, rst_det); ++ if (gpwrdn.b.linestate == 0) { ++ FH_PRINTF("Reset detected\n"); ++ retval |= fh_otg_device_hibernation_restore(core_if, 0, 1); ++ } ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ fh_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ } ++ /* Handle ADP interrupt here */ ++ if (gpwrdn.b.adp_int) { ++ CLEAR_GPWRDN_INTR(core_if, adp_int); ++ fh_otg_adp_handle_intr(core_if); ++ retval |= 1; ++ } ++ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { ++ CLEAR_GPWRDN_INTR(core_if, sts_chngint); ++ fh_otg_handle_pwrdn_stschng_intr(otg_dev); ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ fh_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ if (core_if->lock) ++ FH_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++} +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_core_if.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_core_if.h +new file mode 100644 +index 00000000..e4c4e172 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_core_if.h +@@ -0,0 +1,748 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_core_if.h $ ++ * $Revision: #20 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#if !defined(__FH_CORE_IF_H__) ++#define __FH_CORE_IF_H__ ++ ++#include "../fh_common_port/fh_os.h" ++#include <mach/fh_usb.h> ++ ++/** @file ++ * This file defines FH_OTG Core API ++ */ ++ ++struct fh_otg_core_if; ++typedef struct fh_otg_core_if fh_otg_core_if_t; ++ ++/** Maximum number of Periodic FIFOs */ ++#define MAX_PERIO_FIFOS 15 ++/** Maximum number of Periodic FIFOs */ ++#define MAX_TX_FIFOS 15 ++ ++/** Maximum number of Endpoints/HostChannels */ ++#define MAX_EPS_CHANNELS 16 ++ ++extern fh_otg_core_if_t *fh_otg_cil_init(const uint32_t * _reg_base_addr, ++ struct fh_usb_platform_data *fh_usb_data); ++extern void fh_otg_core_init(fh_otg_core_if_t * _core_if); ++extern void fh_otg_cil_remove(fh_otg_core_if_t * _core_if); ++ ++extern void fh_otg_enable_global_interrupts(fh_otg_core_if_t * _core_if); ++extern void fh_otg_disable_global_interrupts(fh_otg_core_if_t * _core_if); ++ ++extern uint8_t fh_otg_is_device_mode(fh_otg_core_if_t * _core_if); ++extern uint8_t fh_otg_is_host_mode(fh_otg_core_if_t * _core_if); ++ ++extern uint8_t fh_otg_is_dma_enable(fh_otg_core_if_t * core_if); ++ ++/** This function should be called on every hardware interrupt. */ ++extern int32_t fh_otg_handle_common_intr(void *otg_dev); ++ ++ ++/** @name OTG Core Parameters */ ++/** @{ */ ++ ++/** ++ * Specifies the OTG capabilities. The driver will automatically ++ * detect the value for this parameter if none is specified. ++ * 0 - HNP and SRP capable (default) ++ * 1 - SRP Only capable ++ * 2 - No HNP/SRP capable ++ */ ++extern int fh_otg_set_param_otg_cap(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_otg_cap(fh_otg_core_if_t * core_if); ++#define FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0 ++#define FH_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1 ++#define FH_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2 ++#define fh_param_otg_cap_default FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE ++ ++extern int fh_otg_set_param_opt(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_opt(fh_otg_core_if_t * core_if); ++#define fh_param_opt_default 1 ++ ++/** ++ * Specifies whether to use slave or DMA mode for accessing the data ++ * FIFOs. The driver will automatically detect the value for this ++ * parameter if none is specified. ++ * 0 - Slave ++ * 1 - DMA (default, if available) ++ */ ++extern int fh_otg_set_param_dma_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dma_enable(fh_otg_core_if_t * core_if); ++#define fh_param_dma_enable_default 1 ++ ++/** ++ * When DMA mode is enabled specifies whether to use ++ * address DMA or DMA Descritor mode for accessing the data ++ * FIFOs in device mode. The driver will automatically detect ++ * the value for this parameter if none is specified. ++ * 0 - address DMA ++ * 1 - DMA Descriptor(default, if available) ++ */ ++extern int fh_otg_set_param_dma_desc_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dma_desc_enable(fh_otg_core_if_t * core_if); ++#define fh_param_dma_desc_enable_default 1 ++ ++/** The DMA Burst size (applicable only for External DMA ++ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ */ ++extern int fh_otg_set_param_dma_burst_size(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dma_burst_size(fh_otg_core_if_t * core_if); ++#define fh_param_dma_burst_size_default 32 ++ ++/** ++ * Specifies the maximum speed of operation in host and device mode. ++ * The actual speed depends on the speed of the attached device and ++ * the value of phy_type. The actual speed depends on the speed of the ++ * attached device. ++ * 0 - High Speed (default) ++ * 1 - Full Speed ++ */ ++extern int fh_otg_set_param_speed(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_speed(fh_otg_core_if_t * core_if); ++#define fh_param_speed_default 0 ++#define FH_SPEED_PARAM_HIGH 0 ++#define FH_SPEED_PARAM_FULL 1 ++ ++/** Specifies whether low power mode is supported when attached ++ * to a Full Speed or Low Speed device in host mode. ++ * 0 - Don't support low power mode (default) ++ * 1 - Support low power mode ++ */ ++extern int fh_otg_set_param_host_support_fs_ls_low_power(fh_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t fh_otg_get_param_host_support_fs_ls_low_power(fh_otg_core_if_t ++ * core_if); ++#define fh_param_host_support_fs_ls_low_power_default 0 ++ ++/** Specifies the PHY clock rate in low power mode when connected to a ++ * Low Speed device in host mode. This parameter is applicable only if ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * then defaults to 6 MHZ otherwise 48 MHZ. ++ * ++ * 0 - 48 MHz ++ * 1 - 6 MHz ++ */ ++extern int fh_otg_set_param_host_ls_low_power_phy_clk(fh_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t fh_otg_get_param_host_ls_low_power_phy_clk(fh_otg_core_if_t * ++ core_if); ++#define fh_param_host_ls_low_power_phy_clk_default 0 ++#define FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0 ++#define FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1 ++ ++#define FH_CC_CLK_FREQ_30MHZ 0x7530 ++ ++/** ++ * 0 - Use cC FIFO size parameters ++ * 1 - Allow dynamic FIFO sizing (default) ++ */ ++extern int fh_otg_set_param_enable_dynamic_fifo(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_enable_dynamic_fifo(fh_otg_core_if_t * ++ core_if); ++#define fh_param_enable_dynamic_fifo_default 1 ++ ++/** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ * Tx FIFOs. ++ * 32 to 32768 (default 8192) ++ * Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ */ ++extern int fh_otg_set_param_data_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_data_fifo_size(fh_otg_core_if_t * core_if); ++#define fh_param_data_fifo_size_default 2560 ++ ++/** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1064) ++ */ ++extern int fh_otg_set_param_dev_rx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dev_rx_fifo_size(fh_otg_core_if_t * core_if); ++#define fh_param_dev_rx_fifo_size_default 1064 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ * when dynamic FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int fh_otg_set_param_dev_nperio_tx_fifo_size(fh_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t fh_otg_get_param_dev_nperio_tx_fifo_size(fh_otg_core_if_t * ++ core_if); ++#define fh_param_dev_nperio_tx_fifo_size_default 128 ++ ++/** Number of 4-byte words in each of the periodic Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int fh_otg_set_param_dev_perio_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val, int fifo_num); ++extern int32_t fh_otg_get_param_dev_perio_tx_fifo_size(fh_otg_core_if_t * ++ core_if, int fifo_num); ++#define fh_param_dev_perio_tx_fifo_size_default 256 ++ ++/** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int fh_otg_set_param_host_rx_fifo_size(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_host_rx_fifo_size(fh_otg_core_if_t * core_if); ++#define fh_param_host_rx_fifo_size_default 512 ++ ++/** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. ++ * 16 to 32768 (default 1024) ++ */ ++extern int fh_otg_set_param_host_nperio_tx_fifo_size(fh_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t fh_otg_get_param_host_nperio_tx_fifo_size(fh_otg_core_if_t * ++ core_if); ++#define fh_param_host_nperio_tx_fifo_size_default 128 ++ ++/** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. ++ * 16 to 32768 (default 1024) ++ */ ++extern int fh_otg_set_param_host_perio_tx_fifo_size(fh_otg_core_if_t * ++ core_if, int32_t val); ++extern int32_t fh_otg_get_param_host_perio_tx_fifo_size(fh_otg_core_if_t * ++ core_if); ++#define fh_param_host_perio_tx_fifo_size_default 256 ++ ++/** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++extern int fh_otg_set_param_max_transfer_size(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_max_transfer_size(fh_otg_core_if_t * core_if); ++#define fh_param_max_transfer_size_default 65535 ++ ++/** The maximum number of packets in a transfer. ++ * 15 to 511 (default 511) ++ */ ++extern int fh_otg_set_param_max_packet_count(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_max_packet_count(fh_otg_core_if_t * core_if); ++#define fh_param_max_packet_count_default 511 ++ ++/** The number of host channel registers to use. ++ * 1 to 16 (default 12) ++ * Note: The FPGA configuration supports a maximum of 12 host channels. ++ */ ++extern int fh_otg_set_param_host_channels(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_host_channels(fh_otg_core_if_t * core_if); ++#define fh_param_host_channels_default 16 ++ ++/** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ * endpoints in addition to EP0. ++ */ ++extern int fh_otg_set_param_dev_endpoints(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dev_endpoints(fh_otg_core_if_t * core_if); ++#define fh_param_dev_endpoints_default 8 ++ ++/** ++ * Specifies the type of PHY interface to use. By default, the driver ++ * will automatically detect the phy_type. ++ * ++ * 0 - Full Speed PHY ++ * 1 - UTMI+ (default) ++ * 2 - ULPI ++ */ ++extern int fh_otg_set_param_phy_type(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_phy_type(fh_otg_core_if_t * core_if); ++#define FH_PHY_TYPE_PARAM_FS 0 ++#define FH_PHY_TYPE_PARAM_UTMI 1 ++#define FH_PHY_TYPE_PARAM_ULPI 2 ++#define fh_param_phy_type_default FH_PHY_TYPE_PARAM_UTMI ++ ++/** ++ * Specifies the UTMI+ Data Width. This parameter is ++ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI ++ * PHY_TYPE, this parameter indicates the data width between ++ * the MAC and the ULPI Wrapper.) Also, this parameter is ++ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set ++ * to "8 and 16 bits", meaning that the core has been ++ * configured to work at either data path width. ++ * ++ * 8 or 16 bits (default 16) ++ */ ++extern int fh_otg_set_param_phy_utmi_width(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_phy_utmi_width(fh_otg_core_if_t * core_if); ++#define fh_param_phy_utmi_width_default 16 ++ ++/** ++ * Specifies whether the ULPI operates at double or single ++ * data rate. This parameter is only applicable if PHY_TYPE is ++ * ULPI. ++ * ++ * 0 - single data rate ULPI interface with 8 bit wide data ++ * bus (default) ++ * 1 - double data rate ULPI interface with 4 bit wide data ++ * bus ++ */ ++extern int fh_otg_set_param_phy_ulpi_ddr(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_phy_ulpi_ddr(fh_otg_core_if_t * core_if); ++#define fh_param_phy_ulpi_ddr_default 0 ++ ++/** ++ * Specifies whether to use the internal or external supply to ++ * drive the vbus with a ULPI phy. ++ */ ++extern int fh_otg_set_param_phy_ulpi_ext_vbus(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_phy_ulpi_ext_vbus(fh_otg_core_if_t * core_if); ++#define FH_PHY_ULPI_INTERNAL_VBUS 0 ++#define FH_PHY_ULPI_EXTERNAL_VBUS 1 ++#define fh_param_phy_ulpi_ext_vbus_default FH_PHY_ULPI_INTERNAL_VBUS ++ ++/** ++ * Specifies whether to use the I2Cinterface for full speed PHY. This ++ * parameter is only applicable if PHY_TYPE is FS. ++ * 0 - No (default) ++ * 1 - Yes ++ */ ++extern int fh_otg_set_param_i2c_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_i2c_enable(fh_otg_core_if_t * core_if); ++#define fh_param_i2c_enable_default 0 ++ ++extern int fh_otg_set_param_ulpi_fs_ls(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_ulpi_fs_ls(fh_otg_core_if_t * core_if); ++#define fh_param_ulpi_fs_ls_default 0 ++ ++extern int fh_otg_set_param_ts_dline(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_ts_dline(fh_otg_core_if_t * core_if); ++#define fh_param_ts_dline_default 0 ++ ++/** ++ * Specifies whether dedicated transmit FIFOs are ++ * enabled for non periodic IN endpoints in device mode ++ * 0 - No ++ * 1 - Yes ++ */ ++extern int fh_otg_set_param_en_multiple_tx_fifo(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_en_multiple_tx_fifo(fh_otg_core_if_t * ++ core_if); ++#define fh_param_en_multiple_tx_fifo_default 1 ++ ++/** Number of 4-byte words in each of the Tx FIFOs in device ++ * mode when dynamic FIFO sizing is enabled. ++ * 4 to 768 (default 256) ++ */ ++extern int fh_otg_set_param_dev_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int fifo_num, int32_t val); ++extern int32_t fh_otg_get_param_dev_tx_fifo_size(fh_otg_core_if_t * core_if, ++ int fifo_num); ++#define fh_param_dev_tx_fifo_size_default 256 ++ ++/** Thresholding enable flag- ++ * bit 0 - enable non-ISO Tx thresholding ++ * bit 1 - enable ISO Tx thresholding ++ * bit 2 - enable Rx thresholding ++ */ ++extern int fh_otg_set_param_thr_ctl(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_thr_ctl(fh_otg_core_if_t * core_if, int fifo_num); ++#define fh_param_thr_ctl_default 0 ++ ++/** Thresholding length for Tx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int fh_otg_set_param_tx_thr_length(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_tx_thr_length(fh_otg_core_if_t * core_if); ++#define fh_param_tx_thr_length_default 64 ++ ++/** Thresholding length for Rx ++ * FIFOs in 32 bit DWORDs ++ */ ++extern int fh_otg_set_param_rx_thr_length(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_rx_thr_length(fh_otg_core_if_t * core_if); ++#define fh_param_rx_thr_length_default 64 ++ ++/** ++ * Specifies whether LPM (Link Power Management) support is enabled ++ */ ++extern int fh_otg_set_param_lpm_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_lpm_enable(fh_otg_core_if_t * core_if); ++#define fh_param_lpm_enable_default 1 ++ ++/** ++ * Specifies whether LPM Errata (Link Power Management) support is enabled ++ */ ++extern int fh_otg_set_param_besl_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_besl_enable(fh_otg_core_if_t * core_if); ++#define fh_param_besl_enable_default 0 ++ ++/** ++ * Specifies baseline_besl default value ++ */ ++extern int fh_otg_set_param_baseline_besl(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_baseline_besl(fh_otg_core_if_t * core_if); ++#define fh_param_baseline_besl_default 0 ++ ++/** ++ * Specifies deep_besl default value ++ */ ++extern int fh_otg_set_param_deep_besl(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_deep_besl(fh_otg_core_if_t * core_if); ++#define fh_param_deep_besl_default 15 ++ ++/** ++ * Specifies whether PTI enhancement is enabled ++ */ ++extern int fh_otg_set_param_pti_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_pti_enable(fh_otg_core_if_t * core_if); ++#define fh_param_pti_enable_default 0 ++ ++/** ++ * Specifies whether MPI enhancement is enabled ++ */ ++extern int fh_otg_set_param_mpi_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_mpi_enable(fh_otg_core_if_t * core_if); ++#define fh_param_mpi_enable_default 0 ++ ++/** ++ * Specifies whether ADP capability is enabled ++ */ ++extern int fh_otg_set_param_adp_enable(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_adp_enable(fh_otg_core_if_t * core_if); ++#define fh_param_adp_enable_default 0 ++ ++/** ++ * Specifies whether IC_USB capability is enabled ++ */ ++ ++extern int fh_otg_set_param_ic_usb_cap(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_ic_usb_cap(fh_otg_core_if_t * core_if); ++#define fh_param_ic_usb_cap_default 0 ++ ++extern int fh_otg_set_param_ahb_thr_ratio(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_ahb_thr_ratio(fh_otg_core_if_t * core_if); ++#define fh_param_ahb_thr_ratio_default 0 ++ ++extern int fh_otg_set_param_power_down(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_power_down(fh_otg_core_if_t * core_if); ++#define fh_param_power_down_default 0 ++ ++extern int fh_otg_set_param_reload_ctl(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_reload_ctl(fh_otg_core_if_t * core_if); ++#define fh_param_reload_ctl_default 0 ++ ++extern int fh_otg_set_param_dev_out_nak(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_dev_out_nak(fh_otg_core_if_t * core_if); ++#define fh_param_dev_out_nak_default 0 ++ ++extern int fh_otg_set_param_cont_on_bna(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_cont_on_bna(fh_otg_core_if_t * core_if); ++#define fh_param_cont_on_bna_default 0 ++ ++extern int fh_otg_set_param_ahb_single(fh_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t fh_otg_get_param_ahb_single(fh_otg_core_if_t * core_if); ++#define fh_param_ahb_single_default 0 ++ ++extern int fh_otg_set_param_otg_ver(fh_otg_core_if_t * core_if, int32_t val); ++extern int32_t fh_otg_get_param_otg_ver(fh_otg_core_if_t * core_if); ++#define fh_param_otg_ver_default 0 ++ ++/** @} */ ++ ++/** @name Access to registers and bit-fields */ ++ ++/** ++ * Dump core registers and SPRAM ++ */ ++extern void fh_otg_dump_dev_registers(fh_otg_core_if_t * _core_if); ++extern void fh_otg_dump_spram(fh_otg_core_if_t * _core_if); ++extern void fh_otg_dump_host_registers(fh_otg_core_if_t * _core_if); ++extern void fh_otg_dump_global_registers(fh_otg_core_if_t * _core_if); ++ ++/** ++ * Get host negotiation status. ++ */ ++extern uint32_t fh_otg_get_hnpstatus(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get srp status ++ */ ++extern uint32_t fh_otg_get_srpstatus(fh_otg_core_if_t * core_if); ++ ++/** ++ * Set hnpreq bit in the GOTGCTL register. ++ */ ++extern void fh_otg_set_hnpreq(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get Content of SNPSID register. ++ */ ++extern uint32_t fh_otg_get_gsnpsid(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get current mode. ++ * Returns 0 if in device mode, and 1 if in host mode. ++ */ ++extern uint32_t fh_otg_get_mode(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of hnpcapable field in the GUSBCFG register ++ */ ++extern uint32_t fh_otg_get_hnpcapable(fh_otg_core_if_t * core_if); ++/** ++ * Set value of hnpcapable field in the GUSBCFG register ++ */ ++extern void fh_otg_set_hnpcapable(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of srpcapable field in the GUSBCFG register ++ */ ++extern uint32_t fh_otg_get_srpcapable(fh_otg_core_if_t * core_if); ++/** ++ * Set value of srpcapable field in the GUSBCFG register ++ */ ++extern void fh_otg_set_srpcapable(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of devspeed field in the DCFG register ++ */ ++extern uint32_t fh_otg_get_devspeed(fh_otg_core_if_t * core_if); ++/** ++ * Set value of devspeed field in the DCFG register ++ */ ++extern void fh_otg_set_devspeed(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get the value of busconnected field from the HPRT0 register ++ */ ++extern uint32_t fh_otg_get_busconnected(fh_otg_core_if_t * core_if); ++ ++/** ++ * Gets the device enumeration Speed. ++ */ ++extern uint32_t fh_otg_get_enumspeed(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of prtpwr field from the HPRT0 register ++ */ ++extern uint32_t fh_otg_get_prtpower(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of flag indicating core state - hibernated or not ++ */ ++extern uint32_t fh_otg_get_core_state(fh_otg_core_if_t * core_if); ++ ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void fh_otg_set_prtpower(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prtsusp field from the HPRT0 regsiter ++ */ ++extern uint32_t fh_otg_get_prtsuspend(fh_otg_core_if_t * core_if); ++/** ++ * Set value of prtpwr field from the HPRT0 register ++ */ ++extern void fh_otg_set_prtsuspend(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern uint32_t fh_otg_get_mode_ch_tim(fh_otg_core_if_t * core_if); ++/** ++ * Set value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern void fh_otg_set_mode_ch_tim(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of Fram Interval field from the HFIR regsiter ++ */ ++extern uint32_t fh_otg_get_fr_interval(fh_otg_core_if_t * core_if); ++/** ++ * Set value of Frame Interval field from the HFIR regsiter ++ */ ++extern void fh_otg_set_fr_interval(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Set value of prtres field from the HPRT0 register ++ *FIXME Remove? ++ */ ++extern void fh_otg_set_prtresume(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of rmtwkupsig bit in DCTL register ++ */ ++extern uint32_t fh_otg_get_remotewakesig(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of besl_reject bit in DCTL register ++ */ ++ ++extern uint32_t fh_otg_get_beslreject(fh_otg_core_if_t * core_if); ++ ++/** ++ * Set value of besl_reject bit in DCTL register ++ */ ++ ++extern void fh_otg_set_beslreject(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of prt_sleep_sts field from the GLPMCFG register ++ */ ++extern uint32_t fh_otg_get_lpm_portsleepstatus(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of rem_wkup_en field from the GLPMCFG register ++ */ ++extern uint32_t fh_otg_get_lpm_remotewakeenabled(fh_otg_core_if_t * core_if); ++ ++/** ++ * Get value of appl_resp field from the GLPMCFG register ++ */ ++extern uint32_t fh_otg_get_lpmresponse(fh_otg_core_if_t * core_if); ++/** ++ * Set value of appl_resp field from the GLPMCFG register ++ */ ++extern void fh_otg_set_lpmresponse(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of hsic_connect field from the GLPMCFG register ++ */ ++extern uint32_t fh_otg_get_hsic_connect(fh_otg_core_if_t * core_if); ++/** ++ * Set value of hsic_connect field from the GLPMCFG register ++ */ ++extern void fh_otg_set_hsic_connect(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of inv_sel_hsic field from the GLPMCFG register. ++ */ ++extern uint32_t fh_otg_get_inv_sel_hsic(fh_otg_core_if_t * core_if); ++/** ++ * Set value of inv_sel_hsic field from the GLPMFG register. ++ */ ++extern void fh_otg_set_inv_sel_hsic(fh_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Set value of hird_thresh field from the GLPMFG register. ++ */ ++extern void fh_otg_set_hirdthresh(fh_otg_core_if_t * core_if, uint32_t val); ++/** ++ * Get value of hird_thresh field from the GLPMFG register. ++ */ ++extern uint32_t fh_otg_get_hirdthresh(fh_otg_core_if_t * core_if); ++ ++ ++/* ++ * Some functions for accessing registers ++ */ ++ ++/** ++ * GOTGCTL register ++ */ ++extern uint32_t fh_otg_get_gotgctl(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_gotgctl(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUSBCFG register ++ */ ++extern uint32_t fh_otg_get_gusbcfg(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_gusbcfg(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GRXFSIZ register ++ */ ++extern uint32_t fh_otg_get_grxfsiz(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_grxfsiz(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GNPTXFSIZ register ++ */ ++extern uint32_t fh_otg_get_gnptxfsiz(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_gnptxfsiz(fh_otg_core_if_t * core_if, uint32_t val); ++ ++extern uint32_t fh_otg_get_gpvndctl(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_gpvndctl(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GGPIO register ++ */ ++extern uint32_t fh_otg_get_ggpio(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_ggpio(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GUID register ++ */ ++extern uint32_t fh_otg_get_guid(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_guid(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * HPRT0 register ++ */ ++extern uint32_t fh_otg_get_hprt0(fh_otg_core_if_t * core_if); ++extern void fh_otg_set_hprt0(fh_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * GHPTXFSIZE ++ */ ++extern uint32_t fh_otg_get_hptxfsiz(fh_otg_core_if_t * core_if); ++ ++/** @} */ ++ ++#endif /* __FH_CORE_IF_H__ */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_dbg.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_dbg.h +new file mode 100644 +index 00000000..661bb020 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_dbg.h +@@ -0,0 +1,113 @@ ++/* ========================================================================== ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __FH_OTG_DBG_H__ ++#define __FH_OTG_DBG_H__ ++ ++/** @file ++ * This file defines debug levels. ++ * Debugging support vanishes in non-debug builds. ++ */ ++ ++/** ++ * The Debug Level bit-mask variable. ++ */ ++extern uint32_t g_dbg_lvl; ++/** ++ * Set the Debug Level variable. ++ */ ++static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) ++{ ++ uint32_t old = g_dbg_lvl; ++ g_dbg_lvl = new; ++ return old; ++} ++ ++/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ ++#define DBG_CIL (0x2) ++/** When debug level has the DBG_CILV bit set, display CIL Verbose debug ++ * messages */ ++#define DBG_CILV (0x20) ++/** When debug level has the DBG_PCD bit set, display PCD (Device) debug ++ * messages */ ++#define DBG_PCD (0x4) ++/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug ++ * messages */ ++#define DBG_PCDV (0x40) ++/** When debug level has the DBG_HCD bit set, display Host debug messages */ ++#define DBG_HCD (0x8) ++/** When debug level has the DBG_HCDV bit set, display Verbose Host debug ++ * messages */ ++#define DBG_HCDV (0x80) ++/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host ++ * mode. */ ++#define DBG_HCD_URB (0x800) ++ ++/** When debug level has any bit set, display debug messages */ ++#define DBG_ANY (0xFF) ++ ++/** All debug messages off */ ++#define DBG_OFF 0 ++ ++/** Prefix string for FH_DEBUG print macros. */ ++#define USB_FH "FH_otg: " ++ ++/** ++ * Print a debug message when the Global debug level variable contains ++ * the bit defined in <code>lvl</code>. ++ * ++ * @param[in] lvl - Debug level, use one of the DBG_ constants above. ++ * @param[in] x - like printf ++ * ++ * Example:<p> ++ * <code> ++ * FH_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); ++ * </code> ++ * <br> ++ * results in:<br> ++ * <code> ++ * usb-FH_otg: fh_otg_cil_init(ca867000) ++ * </code> ++ */ ++#ifdef DEBUG ++ ++# define FH_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__FH_DEBUG(USB_FH x ); }while(0) ++# define FH_DEBUGP(x...) FH_DEBUGPL(DBG_ANY, x ) ++ ++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) ++ ++#else ++ ++# define FH_DEBUGPL(lvl, x...) do{}while(0) ++# define FH_DEBUGP(x...) ++ ++# define CHK_DEBUG_LEVEL(level) (0) ++ ++#endif /*DEBUG*/ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.c +new file mode 100644 +index 00000000..da5896bc +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.c +@@ -0,0 +1,1523 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_driver.c $ ++ * $Revision: #105 $ ++ * $Date: 2015/10/13 $ ++ * $Change: 2974245 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++/** @file ++ * The fh_otg_driver module provides the initialization and cleanup entry ++ * points for the FH_otg driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the fh_otg_driver_init function is called. When the module is ++ * removed (using rmmod), the fh_otg_driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the fh_otg_driver, which is ++ * used in conjunction with the standard ARM lm_device structure. These ++ * structures allow the OTG driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++ ++#include <linux/platform_device.h> ++ ++#include "fh_otg_os_dep.h" ++#include "../fh_common_port/fh_os.h" ++#include "fh_otg_dbg.h" ++#include "fh_otg_driver.h" ++#include "fh_otg_attr.h" ++#include "fh_otg_core_if.h" ++#include "fh_otg_pcd_if.h" ++#include "fh_otg_hcd_if.h" ++#include <linux/clk.h> ++ ++ ++#define FH_DRIVER_VERSION "3.30a 13-OCT-2015" ++#define FH_DRIVER_DESC "HS OTG USB Controller driver" ++ ++static const char fh_driver_name[] = "fh_otg"; ++int g_irq; ++ ++extern int pcd_init(struct platform_device *dev, int irq); ++ ++extern int hcd_init(struct platform_device *dev, int irq); ++ ++extern int pcd_remove(struct platform_device *dev, int irq); ++ ++extern void hcd_remove(struct platform_device *dev); ++ ++extern void fh_otg_adp_start(fh_otg_core_if_t * core_if, uint8_t is_host); ++ ++/*-------------------------------------------------------------------------*/ ++/* Encapsulate the module parameter settings */ ++ ++struct fh_otg_driver_module_params { ++ int32_t opt; ++ int32_t otg_cap; ++ int32_t dma_enable; ++ int32_t dma_desc_enable; ++ int32_t dma_burst_size; ++ int32_t speed; ++ int32_t host_support_fs_ls_low_power; ++ int32_t host_ls_low_power_phy_clk; ++ int32_t enable_dynamic_fifo; ++ int32_t data_fifo_size; ++ int32_t dev_rx_fifo_size; ++ int32_t dev_nperio_tx_fifo_size; ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ int32_t host_rx_fifo_size; ++ int32_t host_nperio_tx_fifo_size; ++ int32_t host_perio_tx_fifo_size; ++ int32_t max_transfer_size; ++ int32_t max_packet_count; ++ int32_t host_channels; ++ int32_t dev_endpoints; ++ int32_t phy_type; ++ int32_t phy_utmi_width; ++ int32_t phy_ulpi_ddr; ++ int32_t phy_ulpi_ext_vbus; ++ int32_t i2c_enable; ++ int32_t ulpi_fs_ls; ++ int32_t ts_dline; ++ int32_t en_multiple_tx_fifo; ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ uint32_t thr_ctl; ++ uint32_t tx_thr_length; ++ uint32_t rx_thr_length; ++ int32_t pti_enable; ++ int32_t mpi_enable; ++ int32_t lpm_enable; ++ int32_t besl_enable; ++ int32_t baseline_besl; ++ int32_t deep_besl; ++ int32_t ic_usb_cap; ++ int32_t ahb_thr_ratio; ++ int32_t power_down; ++ int32_t reload_ctl; ++ int32_t dev_out_nak; ++ int32_t cont_on_bna; ++ int32_t ahb_single; ++ int32_t otg_ver; ++ int32_t adp_enable; ++}; ++ ++static struct fh_otg_driver_module_params fh_otg_module_params = { ++ .opt = -1, ++ .otg_cap = 0, ++ .dma_enable = 1, ++ .dma_desc_enable = 1, ++ .dma_burst_size = -1, ++ .speed = 0, ++ .host_support_fs_ls_low_power = 0, ++ .host_ls_low_power_phy_clk = 0, ++ .enable_dynamic_fifo = 1, ++ .data_fifo_size = -1, ++ .dev_rx_fifo_size = 549, ++ .dev_nperio_tx_fifo_size = 256, ++ .dev_perio_tx_fifo_size = { ++ /* dev_perio_tx_fifo_size_1 */ ++ 256, ++ 256, ++ 256, ++ 256, ++ 256, ++ 32, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16 ++ /* 15 */ ++ }, ++ .host_rx_fifo_size = 542, ++ .host_nperio_tx_fifo_size = 256, ++ .host_perio_tx_fifo_size = 512, ++ .max_transfer_size = 65535, ++ .max_packet_count = 511, ++ .host_channels = 8, ++ .dev_endpoints = 5, ++ .phy_type = 1, ++ .phy_utmi_width = 16, ++ .phy_ulpi_ddr = 0, ++ .phy_ulpi_ext_vbus = 0, ++ .i2c_enable = 0, ++ .ulpi_fs_ls = 0, ++ .ts_dline = 0, ++ .en_multiple_tx_fifo = 1, ++ .dev_tx_fifo_size = { ++ /* dev_tx_fifo_size */ ++ 256, ++ 256, ++ 256, ++ 256, ++ 256, ++ 32, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16, ++ 16 ++ /* 15 */ ++ }, ++ .thr_ctl = 0, ++ .tx_thr_length = -1, ++ .rx_thr_length = -1, ++ .pti_enable = 0, ++ .mpi_enable = 0, ++ .lpm_enable = 0, ++ .besl_enable = 0, ++ .baseline_besl = 0, ++ .deep_besl = -1, ++ .ic_usb_cap = 0, ++ .ahb_thr_ratio = 0, ++ .power_down = 0, ++ .reload_ctl = 0, ++ .dev_out_nak = 0, ++ .cont_on_bna = 0, ++ .ahb_single = 0, ++ .otg_ver = 0, ++ .adp_enable = -1, ++}; ++ ++/** ++ * Global Debug Level Mask. ++ */ ++uint32_t g_dbg_lvl = 0; /* OFF */ ++ ++#ifdef DEBUG ++/** ++ * This function shows the Driver Version. ++ */ ++static ssize_t version_show(struct device_driver *dev, char *buf) ++{ ++ return snprintf(buf, sizeof(FH_DRIVER_VERSION) + 2, "%s\n", ++ FH_DRIVER_VERSION); ++} ++ ++static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); ++ ++/** ++ * This function shows the driver Debug Level. ++ */ ++static ssize_t dbg_level_show(struct device_driver *drv, char *buf) ++{ ++ return sprintf(buf, "0x%0x\n", g_dbg_lvl); ++} ++ ++/** ++ * This function stores the driver Debug Level. ++ */ ++static ssize_t dbg_level_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ g_dbg_lvl = simple_strtoul(buf, NULL, 16); ++ return count; ++} ++ ++static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show, ++ dbg_level_store); ++#endif ++/** ++ * This function is called during module intialization ++ * to pass module parameters to the FH_OTG CORE. ++ */ ++static int set_parameters(fh_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int i; ++ ++ if (fh_otg_module_params.otg_cap != -1) { ++ retval += ++ fh_otg_set_param_otg_cap(core_if, ++ fh_otg_module_params.otg_cap); ++ } ++ printk(KERN_ERR "dma_enable :%d\n", fh_otg_module_params.dma_enable); ++ if (fh_otg_module_params.dma_enable != -1) { ++ retval += ++ fh_otg_set_param_dma_enable(core_if, ++ fh_otg_module_params. ++ dma_enable); ++ } ++ printk(KERN_ERR "dma_desc_enable :%d\n", fh_otg_module_params.dma_desc_enable); ++ if (fh_otg_module_params.dma_desc_enable != -1) { ++ retval += ++ fh_otg_set_param_dma_desc_enable(core_if, ++ fh_otg_module_params. ++ dma_desc_enable); ++ } ++ if (fh_otg_module_params.opt != -1) { ++ retval += ++ fh_otg_set_param_opt(core_if, fh_otg_module_params.opt); ++ } ++ if (fh_otg_module_params.dma_burst_size != -1) { ++ retval += ++ fh_otg_set_param_dma_burst_size(core_if, ++ fh_otg_module_params. ++ dma_burst_size); ++ } ++ if (fh_otg_module_params.host_support_fs_ls_low_power != -1) { ++ retval += ++ fh_otg_set_param_host_support_fs_ls_low_power(core_if, ++ fh_otg_module_params. ++ host_support_fs_ls_low_power); ++ } ++ if (fh_otg_module_params.enable_dynamic_fifo != -1) { ++ retval += ++ fh_otg_set_param_enable_dynamic_fifo(core_if, ++ fh_otg_module_params. ++ enable_dynamic_fifo); ++ } ++ if (fh_otg_module_params.data_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_data_fifo_size(core_if, ++ fh_otg_module_params. ++ data_fifo_size); ++ } ++ if (fh_otg_module_params.dev_rx_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_dev_rx_fifo_size(core_if, ++ fh_otg_module_params. ++ dev_rx_fifo_size); ++ } ++ if (fh_otg_module_params.dev_nperio_tx_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ fh_otg_module_params. ++ dev_nperio_tx_fifo_size); ++ } ++ if (fh_otg_module_params.host_rx_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_host_rx_fifo_size(core_if, ++ fh_otg_module_params.host_rx_fifo_size); ++ } ++ if (fh_otg_module_params.host_nperio_tx_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ fh_otg_module_params. ++ host_nperio_tx_fifo_size); ++ } ++ if (fh_otg_module_params.host_perio_tx_fifo_size != -1) { ++ retval += ++ fh_otg_set_param_host_perio_tx_fifo_size(core_if, ++ fh_otg_module_params. ++ host_perio_tx_fifo_size); ++ } ++ if (fh_otg_module_params.max_transfer_size != -1) { ++ retval += ++ fh_otg_set_param_max_transfer_size(core_if, ++ fh_otg_module_params. ++ max_transfer_size); ++ } ++ if (fh_otg_module_params.max_packet_count != -1) { ++ retval += ++ fh_otg_set_param_max_packet_count(core_if, ++ fh_otg_module_params. ++ max_packet_count); ++ } ++ if (fh_otg_module_params.host_channels != -1) { ++ retval += ++ fh_otg_set_param_host_channels(core_if, ++ fh_otg_module_params. ++ host_channels); ++ } ++ if (fh_otg_module_params.dev_endpoints != -1) { ++ retval += ++ fh_otg_set_param_dev_endpoints(core_if, ++ fh_otg_module_params. ++ dev_endpoints); ++ } ++ if (fh_otg_module_params.phy_type != -1) { ++ retval += ++ fh_otg_set_param_phy_type(core_if, ++ fh_otg_module_params.phy_type); ++ } ++ if (fh_otg_module_params.speed != -1) { ++ retval += ++ fh_otg_set_param_speed(core_if, ++ fh_otg_module_params.speed); ++ } ++ if (fh_otg_module_params.host_ls_low_power_phy_clk != -1) { ++ retval += ++ fh_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ fh_otg_module_params. ++ host_ls_low_power_phy_clk); ++ } ++ if (fh_otg_module_params.phy_ulpi_ddr != -1) { ++ retval += ++ fh_otg_set_param_phy_ulpi_ddr(core_if, ++ fh_otg_module_params. ++ phy_ulpi_ddr); ++ } ++ if (fh_otg_module_params.phy_ulpi_ext_vbus != -1) { ++ retval += ++ fh_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ fh_otg_module_params. ++ phy_ulpi_ext_vbus); ++ } ++ if (fh_otg_module_params.phy_utmi_width != -1) { ++ retval += ++ fh_otg_set_param_phy_utmi_width(core_if, ++ fh_otg_module_params. ++ phy_utmi_width); ++ } ++ if (fh_otg_module_params.ulpi_fs_ls != -1) { ++ retval += ++ fh_otg_set_param_ulpi_fs_ls(core_if, ++ fh_otg_module_params.ulpi_fs_ls); ++ } ++ if (fh_otg_module_params.ts_dline != -1) { ++ retval += ++ fh_otg_set_param_ts_dline(core_if, ++ fh_otg_module_params.ts_dline); ++ } ++ if (fh_otg_module_params.i2c_enable != -1) { ++ retval += ++ fh_otg_set_param_i2c_enable(core_if, ++ fh_otg_module_params. ++ i2c_enable); ++ } ++ if (fh_otg_module_params.en_multiple_tx_fifo != -1) { ++ retval += ++ fh_otg_set_param_en_multiple_tx_fifo(core_if, ++ fh_otg_module_params. ++ en_multiple_tx_fifo); ++ } ++ for (i = 0; i < 15; i++) { ++ if (fh_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { ++ retval += ++ fh_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ fh_otg_module_params. ++ dev_perio_tx_fifo_size ++ [i], i); ++ } ++ } ++ ++ for (i = 0; i < 15; i++) { ++ if (fh_otg_module_params.dev_tx_fifo_size[i] != -1) { ++ retval += fh_otg_set_param_dev_tx_fifo_size(core_if, ++ fh_otg_module_params. ++ dev_tx_fifo_size ++ [i], i); ++ } ++ } ++ if (fh_otg_module_params.thr_ctl != -1) { ++ retval += ++ fh_otg_set_param_thr_ctl(core_if, ++ fh_otg_module_params.thr_ctl); ++ } ++ if (fh_otg_module_params.mpi_enable != -1) { ++ retval += ++ fh_otg_set_param_mpi_enable(core_if, ++ fh_otg_module_params. ++ mpi_enable); ++ } ++ if (fh_otg_module_params.pti_enable != -1) { ++ retval += ++ fh_otg_set_param_pti_enable(core_if, ++ fh_otg_module_params. ++ pti_enable); ++ } ++ if (fh_otg_module_params.lpm_enable != -1) { ++ retval += ++ fh_otg_set_param_lpm_enable(core_if, ++ fh_otg_module_params. ++ lpm_enable); ++ } ++ if (fh_otg_module_params.besl_enable != -1) { ++ retval += ++ fh_otg_set_param_besl_enable(core_if, ++ fh_otg_module_params. ++ besl_enable); ++ } ++ if (fh_otg_module_params.baseline_besl != -1) { ++ retval += ++ fh_otg_set_param_baseline_besl(core_if, ++ fh_otg_module_params. ++ baseline_besl); ++ } ++ if (fh_otg_module_params.deep_besl != -1) { ++ retval += ++ fh_otg_set_param_deep_besl(core_if, ++ fh_otg_module_params. ++ deep_besl); ++ } ++ if (fh_otg_module_params.ic_usb_cap != -1) { ++ retval += ++ fh_otg_set_param_ic_usb_cap(core_if, ++ fh_otg_module_params. ++ ic_usb_cap); ++ } ++ if (fh_otg_module_params.tx_thr_length != -1) { ++ retval += ++ fh_otg_set_param_tx_thr_length(core_if, ++ fh_otg_module_params.tx_thr_length); ++ } ++ if (fh_otg_module_params.rx_thr_length != -1) { ++ retval += ++ fh_otg_set_param_rx_thr_length(core_if, ++ fh_otg_module_params. ++ rx_thr_length); ++ } ++ if (fh_otg_module_params.ahb_thr_ratio != -1) { ++ retval += ++ fh_otg_set_param_ahb_thr_ratio(core_if, ++ fh_otg_module_params.ahb_thr_ratio); ++ } ++ if (fh_otg_module_params.power_down != -1) { ++ retval += ++ fh_otg_set_param_power_down(core_if, ++ fh_otg_module_params.power_down); ++ } ++ if (fh_otg_module_params.reload_ctl != -1) { ++ retval += ++ fh_otg_set_param_reload_ctl(core_if, ++ fh_otg_module_params.reload_ctl); ++ } ++ ++ if (fh_otg_module_params.dev_out_nak != -1) { ++ retval += ++ fh_otg_set_param_dev_out_nak(core_if, ++ fh_otg_module_params.dev_out_nak); ++ } ++ ++ if (fh_otg_module_params.cont_on_bna != -1) { ++ retval += ++ fh_otg_set_param_cont_on_bna(core_if, ++ fh_otg_module_params.cont_on_bna); ++ } ++ ++ if (fh_otg_module_params.ahb_single != -1) { ++ retval += ++ fh_otg_set_param_ahb_single(core_if, ++ fh_otg_module_params.ahb_single); ++ } ++ ++ if (fh_otg_module_params.otg_ver != -1) { ++ retval += ++ fh_otg_set_param_otg_ver(core_if, ++ fh_otg_module_params.otg_ver); ++ } ++ if (fh_otg_module_params.adp_enable != -1) { ++ retval += ++ fh_otg_set_param_adp_enable(core_if, ++ fh_otg_module_params. ++ adp_enable); ++ } ++ return retval; ++} ++ ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Device and host modes) interrupts. ++ */ ++static irqreturn_t fh_otg_common_irq(int irq, void *dev) ++{ ++ int32_t retval = IRQ_NONE; ++ ++ retval = fh_otg_handle_common_intr(dev); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function is called when a lm_device is unregistered with the ++ * fh_otg_driver. This happens, for example, when the rmmod command is ++ * executed. The device may or may not be electrically present. If it is ++ * present, the driver stops device processing. Any resources used on behalf ++ * of this device are freed. ++ * ++ * @param _dev ++ */ ++static int fh_otg_driver_remove(struct platform_device *dev) ++{ ++ int retval = 0; ++ fh_otg_device_t *otg_dev = platform_get_drvdata(dev); ++ ++ ++ printk(KERN_ERR "%s (%p)\n", __func__, dev); ++ ++ if (!otg_dev) { ++ /* Memory allocation for the fh_otg_device failed. */ ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return -EINVAL; ++ } ++#ifndef FH_DEVICE_ONLY ++ if (otg_dev->hcd) { ++ hcd_remove(dev); ++ } else { ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ ++ } ++#endif ++ ++#ifndef FH_HOST_ONLY ++ if (otg_dev->pcd) { ++ pcd_remove(dev, g_irq); ++ } else { ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); ++ ++ } ++#endif ++ /* ++ * Free the IRQ ++ */ ++ if (otg_dev->common_irq_installed) { ++ free_irq(g_irq, otg_dev); ++ } else { ++ FH_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); ++ ++ } ++ ++ if (otg_dev->core_if) { ++ fh_otg_cil_remove(otg_dev->core_if); ++ } else { ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); ++ ++ } ++ ++ /* ++ * Remove the device attributes ++ */ ++ //fh_otg_attr_remove(dev); ++ ++ /* ++ * Return the memory. ++ */ ++ if (otg_dev->os_dep.base) ++ iounmap(otg_dev->os_dep.base); ++ FH_FREE(otg_dev); ++ ++ /* ++ * Clear the drvdata pointer. ++ */ ++ ++ release_mem_region(otg_dev->os_dep.rsrc_start, otg_dev->os_dep.rsrc_len); ++ platform_set_drvdata(dev, 0); ++ g_irq = 0; ++ return retval; ++} ++ ++/** ++ * This function is called when an lm_device is bound to a ++ * fh_otg_driver. It creates the driver components required to ++ * control the device (CIL, HCD, and PCD) and it initializes the ++ * device. The driver components are stored in a fh_otg_device ++ * structure. A reference to the fh_otg_device is saved in the ++ * lm_device. This allows the driver to access the fh_otg_device ++ * structure on subsequent calls to driver methods for this device. ++ * ++ * @param _dev Bus device ++ */ ++static int fh_otg_driver_probe(struct platform_device *dev) ++{ ++ int retval = 0; ++ fh_otg_device_t *fh_otg_device; ++ struct resource *res; ++ int irq; ++ struct fh_usb_platform_data *fh_usb_data; ++#if !defined(CONFIG_ARCH_FH8856) ++ struct clk *usb_clk; ++#endif ++ ++ //printk(KERN_ERR "fh_otg_driver_probe(%p)\n", dev); ++ ++ fh_otg_device = FH_ALLOC(sizeof(fh_otg_device_t)); ++ ++ if (!fh_otg_device) { ++ dev_err(&dev->dev, "kmalloc of fh_otg_device failed\n"); ++ return -ENOMEM; ++ } ++ ++#if !defined(CONFIG_ARCH_FH8856) ++ usb_clk = clk_get(NULL, "usb_clk"); ++ if (IS_ERR(usb_clk)) { ++ retval = PTR_ERR(usb_clk); ++ return -EPERM; ++ } ++ clk_enable(usb_clk); ++#endif ++ ++ fh_usb_data = dev->dev.platform_data; ++ if (fh_usb_data != NULL && fh_usb_data->power_on) ++ fh_usb_data->power_on(); ++ ++ if (fh_usb_data != NULL && fh_usb_data->utmi_rst) ++ fh_usb_data->utmi_rst(); ++ ++ if (fh_usb_data != NULL && fh_usb_data->phy_rst) ++ fh_usb_data->phy_rst(); ++ ++ if (fh_usb_data != NULL && fh_usb_data->hcd_resume) ++ fh_usb_data->hcd_resume(); ++ ++ memset(fh_otg_device, 0, sizeof(*fh_otg_device)); ++ fh_otg_device->os_dep.reg_offset = 0xFFFFFFFF; ++ ++ /* ++ * Map the FH_otg Core memory into virtual address space. ++ */ ++ res = platform_get_resource(dev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&dev->dev, ++ "Found HC with no IRQ. Check %s setup!\n", ++ dev_name(&dev->dev)); ++ return -ENODEV; ++ } ++ irq = res->start; ++ g_irq = irq; ++ ++ res = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&dev->dev, ++ "Found HC with no register addr. Check %s setup!\n", ++ dev_name(&dev->dev)); ++ return -ENODEV; ++ } ++ fh_otg_device->os_dep.rsrc_start = res->start; ++ fh_otg_device->os_dep.rsrc_len = res->end - res->start + 1; ++ ++ ++ printk(KERN_ERR "resource: start=%08x, len=%08x\n", ++ (unsigned)fh_otg_device->os_dep.rsrc_start, ++ (unsigned)fh_otg_device->os_dep.rsrc_len); ++ ++ if (!request_mem_region ++ (fh_otg_device->os_dep.rsrc_start, fh_otg_device->os_dep.rsrc_len, ++ "fh_otg")) { ++ dev_dbg(&dev->dev, "error requesting memory\n"); ++ FH_FREE(fh_otg_device); ++ return -EFAULT; ++ } ++ ++ fh_otg_device->os_dep.base = ++ ioremap_nocache(fh_otg_device->os_dep.rsrc_start, ++ fh_otg_device->os_dep.rsrc_len); ++ if (fh_otg_device->os_dep.base == NULL) { ++ dev_dbg(&dev->dev, "error mapping memory\n"); ++ release_mem_region(fh_otg_device->os_dep.rsrc_start, ++ fh_otg_device->os_dep.rsrc_len); ++ FH_FREE(fh_otg_device); ++ return -EFAULT; ++ } ++ //printk(KERN_INFO "base=0x%p (before adjust) \n", ++ // fh_otg_device->os_dep.base); ++ fh_otg_device->os_dep.base = (char *)fh_otg_device->os_dep.base; ++ printk(KERN_ERR "base=0x%p (after adjust) \n", ++ fh_otg_device->os_dep.base); ++ printk(KERN_INFO "%s: mapped PA 0x%x to VA 0x%p\n", __func__, ++ (unsigned)fh_otg_device->os_dep.rsrc_start, ++ fh_otg_device->os_dep.base); ++ ++ /* ++ * Initialize driver data to point to the global FH_otg ++ * Device structure. ++ */ ++ ++ dev_dbg(&dev->dev, "fh_otg_device=0x%p\n", fh_otg_device); ++ ++ fh_otg_device->core_if = fh_otg_cil_init(fh_otg_device->os_dep.base, ++ fh_usb_data); ++ if (!fh_otg_device->core_if) { ++ dev_err(&dev->dev, "CIL initialization failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ /* ++ * Attempt to ensure this device is really a FH_otg Controller. ++ * Read and verify the SNPSID register contents. The value should be ++ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", ++ * as in "OTG version 2.XX" or "OTG version 3.XX". ++ */ ++ ++ if (((fh_otg_get_gsnpsid(fh_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ++ ((fh_otg_get_gsnpsid(fh_otg_device->core_if) & 0xFFFFF000) != 0x4F543000) && ++ ((fh_otg_get_gsnpsid(fh_otg_device->core_if) & 0xFFFFF000) != 0x4F544000)) { ++ dev_err(&dev->dev, "Bad value for SNPSID: 0x%08x\n", ++ fh_otg_get_gsnpsid(fh_otg_device->core_if)); ++ retval = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Validate parameter values. ++ */ ++ if (set_parameters(fh_otg_device->core_if)) { ++ retval = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Create Device Attributes in sysfs ++ */ ++ /*fh_otg_attr_create(dev);*/ ++ ++ ++ /* ++ * Disable the global interrupt until all the interrupt ++ * handlers are installed. ++ */ ++ fh_otg_disable_global_interrupts(fh_otg_device->core_if); ++ ++ /* ++ * Install the interrupt handler for the common interrupts before ++ * enabling common interrupts in core_init below. ++ */ ++ retval = request_irq(irq, fh_otg_common_irq, ++ IRQF_SHARED | IRQF_DISABLED | IRQ_LEVEL, "fh_otg", ++ fh_otg_device); ++ if (retval) { ++ FH_ERROR("request of irq%d failed\n", irq); ++ retval = -EBUSY; ++ goto fail; ++ } else { ++ fh_otg_device->common_irq_installed = 1; ++ } ++ ++ /* ++ * Initialize the FH_otg core. ++ */ ++ fh_otg_core_init(fh_otg_device->core_if); ++ fh_otg_device->os_dep.pdev = dev; ++ platform_set_drvdata(dev, fh_otg_device); ++ ++#ifndef FH_HOST_ONLY ++ /* ++ * Initialize the PCD ++ */ ++ retval = pcd_init(dev, irq); ++ if (retval != 0) { ++ FH_ERROR("pcd_init failed\n"); ++ fh_otg_device->pcd = NULL; ++ goto fail; ++ } ++#endif ++ ++#ifndef FH_DEVICE_ONLY ++ /* ++ * Initialize the HCD ++ */ ++ retval = hcd_init(dev, irq); ++ if (retval != 0) { ++ FH_ERROR("hcd_init failed\n"); ++ fh_otg_device->hcd = NULL; ++ goto fail; ++ } ++#endif ++ ++ /* ++ * Enable the global interrupt after all the interrupt ++ * handlers are installed if there is no ADP support else ++ * perform initial actions required for Internal ADP logic. ++ */ ++ if (!fh_otg_get_param_adp_enable(fh_otg_device->core_if)) ++ fh_otg_enable_global_interrupts(fh_otg_device->core_if); ++ else ++ fh_otg_adp_start(fh_otg_device->core_if, ++ fh_otg_is_host_mode(fh_otg_device->core_if)); ++ ++ ++ return 0; ++ ++fail: ++ fh_otg_driver_remove(dev); ++ return retval; ++} ++ ++static const struct of_device_id fh_of_match_table[] = { ++ { .compatible = "brcm,bcm2835-usb", .data = NULL }, ++ { .compatible = "rockchip,rk3066-usb", .data = NULL }, ++ { .compatible = "fullhan,fh2", .data = NULL }, ++ { .compatible = "samsung,s3c6400-hsotg", .data = NULL}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, fh_of_match_table); ++ ++static struct platform_driver fh_otg_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = fh_driver_name, ++ .of_match_table = fh_of_match_table, ++ }, ++ ++ .probe = fh_otg_driver_probe, ++ .remove = fh_otg_driver_remove, ++}; ++ ++ ++static int __init fh_otg_driver_init(void) ++{ ++ return platform_driver_register(&fh_otg_driver); ++} ++module_init(fh_otg_driver_init); ++ ++static void __exit fh_otg_driver_cleanup(void) ++{ ++ platform_driver_unregister(&fh_otg_driver); ++} ++ ++module_exit(fh_otg_driver_cleanup); ++ ++MODULE_DESCRIPTION(FH_DRIVER_DESC); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE("GPL"); ++ ++module_param_named(otg_cap, fh_otg_module_params.otg_cap, int, 0444); ++MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None"); ++module_param_named(opt, fh_otg_module_params.opt, int, 0444); ++MODULE_PARM_DESC(opt, "OPT Mode"); ++module_param_named(dma_enable, fh_otg_module_params.dma_enable, int, 0444); ++MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); ++ ++module_param_named(dma_desc_enable, fh_otg_module_params.dma_desc_enable, int, ++ 0444); ++MODULE_PARM_DESC(dma_desc_enable, ++ "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled"); ++ ++module_param_named(dma_burst_size, fh_otg_module_params.dma_burst_size, int, ++ 0444); ++MODULE_PARM_DESC(dma_burst_size, ++ "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); ++module_param_named(speed, fh_otg_module_params.speed, int, 0444); ++MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed"); ++module_param_named(host_support_fs_ls_low_power, ++ fh_otg_module_params.host_support_fs_ls_low_power, int, ++ 0444); ++MODULE_PARM_DESC(host_support_fs_ls_low_power, ++ "Support Low Power w/FS or LS 0=Support 1=Don't Support"); ++module_param_named(host_ls_low_power_phy_clk, ++ fh_otg_module_params.host_ls_low_power_phy_clk, int, 0444); ++MODULE_PARM_DESC(host_ls_low_power_phy_clk, ++ "Low Speed Low Power Clock 0=48Mhz 1=6Mhz"); ++module_param_named(enable_dynamic_fifo, ++ fh_otg_module_params.enable_dynamic_fifo, int, 0444); ++MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing"); ++module_param_named(data_fifo_size, fh_otg_module_params.data_fifo_size, int, ++ 0444); ++MODULE_PARM_DESC(data_fifo_size, ++ "Total number of words in the data FIFO memory 32-32768"); ++module_param_named(dev_rx_fifo_size, fh_otg_module_params.dev_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(dev_nperio_tx_fifo_size, ++ fh_otg_module_params.dev_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(dev_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(dev_perio_tx_fifo_size_1, ++ fh_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_2, ++ fh_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_3, ++ fh_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_4, ++ fh_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_5, ++ fh_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_6, ++ fh_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_7, ++ fh_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_8, ++ fh_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_9, ++ fh_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_10, ++ fh_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_11, ++ fh_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_11, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_12, ++ fh_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_12, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_13, ++ fh_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_13, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_14, ++ fh_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_14, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_15, ++ fh_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_15, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(host_rx_fifo_size, fh_otg_module_params.host_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(host_nperio_tx_fifo_size, ++ fh_otg_module_params.host_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(host_perio_tx_fifo_size, ++ fh_otg_module_params.host_perio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_perio_tx_fifo_size, ++ "Number of words in the host periodic Tx FIFO 16-32768"); ++module_param_named(max_transfer_size, fh_otg_module_params.max_transfer_size, ++ int, 0444); ++/** @todo Set the max to 512K, modify checks */ ++MODULE_PARM_DESC(max_transfer_size, ++ "The maximum transfer size supported in bytes 2047-65535"); ++module_param_named(max_packet_count, fh_otg_module_params.max_packet_count, ++ int, 0444); ++MODULE_PARM_DESC(max_packet_count, ++ "The maximum number of packets in a transfer 15-511"); ++module_param_named(host_channels, fh_otg_module_params.host_channels, int, ++ 0444); ++MODULE_PARM_DESC(host_channels, ++ "The number of host channel registers to use 1-16"); ++module_param_named(dev_endpoints, fh_otg_module_params.dev_endpoints, int, ++ 0444); ++MODULE_PARM_DESC(dev_endpoints, ++ "The number of endpoints in addition to EP0 available for device mode 1-15"); ++module_param_named(phy_type, fh_otg_module_params.phy_type, int, 0444); ++MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI"); ++module_param_named(phy_utmi_width, fh_otg_module_params.phy_utmi_width, int, ++ 0444); ++MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits"); ++module_param_named(phy_ulpi_ddr, fh_otg_module_params.phy_ulpi_ddr, int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ddr, ++ "ULPI at double or single data rate 0=Single 1=Double"); ++module_param_named(phy_ulpi_ext_vbus, fh_otg_module_params.phy_ulpi_ext_vbus, ++ int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ext_vbus, ++ "ULPI PHY using internal or external vbus 0=Internal"); ++module_param_named(i2c_enable, fh_otg_module_params.i2c_enable, int, 0444); ++MODULE_PARM_DESC(i2c_enable, "FS PHY Interface"); ++module_param_named(ulpi_fs_ls, fh_otg_module_params.ulpi_fs_ls, int, 0444); ++MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only"); ++module_param_named(ts_dline, fh_otg_module_params.ts_dline, int, 0444); ++MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs"); ++module_param_named(debug, g_dbg_lvl, int, 0444); ++MODULE_PARM_DESC(debug, ""); ++ ++module_param_named(en_multiple_tx_fifo, ++ fh_otg_module_params.en_multiple_tx_fifo, int, 0444); ++MODULE_PARM_DESC(en_multiple_tx_fifo, ++ "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled"); ++module_param_named(dev_tx_fifo_size_1, ++ fh_otg_module_params.dev_tx_fifo_size[0], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_2, ++ fh_otg_module_params.dev_tx_fifo_size[1], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_3, ++ fh_otg_module_params.dev_tx_fifo_size[2], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_4, ++ fh_otg_module_params.dev_tx_fifo_size[3], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_5, ++ fh_otg_module_params.dev_tx_fifo_size[4], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_6, ++ fh_otg_module_params.dev_tx_fifo_size[5], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_7, ++ fh_otg_module_params.dev_tx_fifo_size[6], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_8, ++ fh_otg_module_params.dev_tx_fifo_size[7], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_9, ++ fh_otg_module_params.dev_tx_fifo_size[8], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_10, ++ fh_otg_module_params.dev_tx_fifo_size[9], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_11, ++ fh_otg_module_params.dev_tx_fifo_size[10], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_12, ++ fh_otg_module_params.dev_tx_fifo_size[11], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_13, ++ fh_otg_module_params.dev_tx_fifo_size[12], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_14, ++ fh_otg_module_params.dev_tx_fifo_size[13], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_15, ++ fh_otg_module_params.dev_tx_fifo_size[14], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768"); ++ ++module_param_named(thr_ctl, fh_otg_module_params.thr_ctl, int, 0444); ++MODULE_PARM_DESC(thr_ctl, ++ "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled"); ++module_param_named(tx_thr_length, fh_otg_module_params.tx_thr_length, int, ++ 0444); ++MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs"); ++module_param_named(rx_thr_length, fh_otg_module_params.rx_thr_length, int, ++ 0444); ++MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs"); ++ ++module_param_named(pti_enable, fh_otg_module_params.pti_enable, int, 0444); ++module_param_named(mpi_enable, fh_otg_module_params.mpi_enable, int, 0444); ++module_param_named(lpm_enable, fh_otg_module_params.lpm_enable, int, 0444); ++MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled"); ++ ++module_param_named(besl_enable, fh_otg_module_params.besl_enable, int, 0444); ++MODULE_PARM_DESC(besl_enable, "BESL Enable 0=BESL Disabled 1=BESL Enabled"); ++module_param_named(baseline_besl, fh_otg_module_params.baseline_besl, int, 0444); ++MODULE_PARM_DESC(baseline_besl, "Set the baseline besl value"); ++module_param_named(deep_besl, fh_otg_module_params.deep_besl, int, 0444); ++MODULE_PARM_DESC(deep_besl, "Set the deep besl value"); ++ ++module_param_named(ic_usb_cap, fh_otg_module_params.ic_usb_cap, int, 0444); ++MODULE_PARM_DESC(ic_usb_cap, ++ "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled"); ++module_param_named(ahb_thr_ratio, fh_otg_module_params.ahb_thr_ratio, int, ++ 0444); ++MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio"); ++module_param_named(power_down, fh_otg_module_params.power_down, int, 0444); ++MODULE_PARM_DESC(power_down, "Power Down Mode"); ++module_param_named(reload_ctl, fh_otg_module_params.reload_ctl, int, 0444); ++MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control"); ++module_param_named(dev_out_nak, fh_otg_module_params.dev_out_nak, int, 0444); ++MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK"); ++module_param_named(cont_on_bna, fh_otg_module_params.cont_on_bna, int, 0444); ++MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA"); ++module_param_named(ahb_single, fh_otg_module_params.ahb_single, int, 0444); ++MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support"); ++module_param_named(adp_enable, fh_otg_module_params.adp_enable, int, 0444); ++MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled"); ++module_param_named(otg_ver, fh_otg_module_params.otg_ver, int, 0444); ++MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0"); ++ ++/** @page "Module Parameters" ++ * ++ * The following parameters may be specified when starting the module. ++ * These parameters define how the FH_otg controller should be ++ * configured. Parameter values are passed to the CIL initialization ++ * function fh_otg_cil_init ++ * ++ * Example: <code>modprobe fh_otg speed=1 otg_cap=1</code> ++ * ++ ++ <table> ++ <tr><td>Parameter Name</td><td>Meaning</td></tr> ++ ++ <tr> ++ <td>otg_cap</td> ++ <td>Specifies the OTG capabilities. The driver will automatically detect the ++ value for this parameter if none is specified. ++ - 0: HNP and SRP capable (default, if available) ++ - 1: SRP Only capable ++ - 2: No HNP/SRP capable ++ </td></tr> ++ ++ <tr> ++ <td>dma_enable</td> ++ <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Slave ++ - 1: DMA (default, if available) ++ </td></tr> ++ ++ <tr> ++ <td>dma_burst_size</td> ++ <td>The DMA Burst size (applicable only for External DMA Mode). ++ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++ </td></tr> ++ ++ <tr> ++ <td>speed</td> ++ <td>Specifies the maximum speed of operation in host and device mode. The ++ actual speed depends on the speed of the attached device and the value of ++ phy_type. ++ - 0: High Speed (default) ++ - 1: Full Speed ++ </td></tr> ++ ++ <tr> ++ <td>host_support_fs_ls_low_power</td> ++ <td>Specifies whether low power mode is supported when attached to a Full ++ Speed or Low Speed device in host mode. ++ - 0: Don't support low power mode (default) ++ - 1: Support low power mode ++ </td></tr> ++ ++ <tr> ++ <td>host_ls_low_power_phy_clk</td> ++ <td>Specifies the PHY clock rate in low power mode when connected to a Low ++ Speed device in host mode. This parameter is applicable only if ++ HOST_SUPPORT_FS_LS_LOW_POWER is enabled. ++ - 0: 48 MHz (default) ++ - 1: 6 MHz ++ </td></tr> ++ ++ <tr> ++ <td>enable_dynamic_fifo</td> ++ <td> Specifies whether FIFOs may be resized by the driver software. ++ - 0: Use cC FIFO size parameters ++ - 1: Allow dynamic FIFO sizing (default) ++ </td></tr> ++ ++ <tr> ++ <td>data_fifo_size</td> ++ <td>Total number of 4-byte words in the data FIFO memory. This memory ++ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs. ++ - Values: 32 to 32768 (default 8192) ++ ++ Note: The total FIFO memory depth in the FPGA configuration is 8192. ++ </td></tr> ++ ++ <tr> ++ <td>dev_rx_fifo_size</td> ++ <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1064) ++ </td></tr> ++ ++ <tr> ++ <td>dev_nperio_tx_fifo_size</td> ++ <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when ++ dynamic FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++ </td></tr> ++ ++ <tr> ++ <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td> ++ <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode ++ when dynamic FIFO sizing is enabled. ++ - Values: 4 to 768 (default 256) ++ </td></tr> ++ ++ <tr> ++ <td>host_rx_fifo_size</td> ++ <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++ </td></tr> ++ ++ <tr> ++ <td>host_nperio_tx_fifo_size</td> ++ <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when ++ dynamic FIFO sizing is enabled in the core. ++ - Values: 16 to 32768 (default 1024) ++ </td></tr> ++ ++ <tr> ++ <td>host_perio_tx_fifo_size</td> ++ <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++ </td></tr> ++ ++ <tr> ++ <td>max_transfer_size</td> ++ <td>The maximum transfer size supported in bytes. ++ - Values: 2047 to 65,535 (default 65,535) ++ </td></tr> ++ ++ <tr> ++ <td>max_packet_count</td> ++ <td>The maximum number of packets in a transfer. ++ - Values: 15 to 511 (default 511) ++ </td></tr> ++ ++ <tr> ++ <td>host_channels</td> ++ <td>The number of host channel registers to use. ++ - Values: 1 to 16 (default 12) ++ ++ Note: The FPGA configuration supports a maximum of 12 host channels. ++ </td></tr> ++ ++ <tr> ++ <td>dev_endpoints</td> ++ <td>The number of endpoints in addition to EP0 available for device mode ++ operations. ++ - Values: 1 to 15 (default 6 IN and OUT) ++ ++ Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in ++ addition to EP0. ++ </td></tr> ++ ++ <tr> ++ <td>phy_type</td> ++ <td>Specifies the type of PHY interface to use. By default, the driver will ++ automatically detect the phy_type. ++ - 0: Full Speed ++ - 1: UTMI+ (default, if available) ++ - 2: ULPI ++ </td></tr> ++ ++ <tr> ++ <td>phy_utmi_width</td> ++ <td>Specifies the UTMI+ Data Width. This parameter is applicable for a ++ phy_type of UTMI+. Also, this parameter is applicable only if the ++ OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the ++ core has been configured to work at either data path width. ++ - Values: 8 or 16 bits (default 16) ++ </td></tr> ++ ++ <tr> ++ <td>phy_ulpi_ddr</td> ++ <td>Specifies whether the ULPI operates at double or single data rate. This ++ parameter is only applicable if phy_type is ULPI. ++ - 0: single data rate ULPI interface with 8 bit wide data bus (default) ++ - 1: double data rate ULPI interface with 4 bit wide data bus ++ </td></tr> ++ ++ <tr> ++ <td>i2c_enable</td> ++ <td>Specifies whether to use the I2C interface for full speed PHY. This ++ parameter is only applicable if PHY_TYPE is FS. ++ - 0: Disabled (default) ++ - 1: Enabled ++ </td></tr> ++ ++ <tr> ++ <td>ulpi_fs_ls</td> ++ <td>Specifies whether to use ULPI FS/LS mode only. ++ - 0: Disabled (default) ++ - 1: Enabled ++ </td></tr> ++ ++ <tr> ++ <td>ts_dline</td> ++ <td>Specifies whether term select D-Line pulsing for all PHYs is enabled. ++ - 0: Disabled (default) ++ - 1: Enabled ++ </td></tr> ++ ++ <tr> ++ <td>en_multiple_tx_fifo</td> ++ <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Disabled ++ - 1: Enabled (default, if available) ++ </td></tr> ++ ++ <tr> ++ <td>dev_tx_fifo_size_n (n = 1 to 15)</td> ++ <td>Number of 4-byte words in each of the Tx FIFOs in device mode ++ when dynamic FIFO sizing is enabled. ++ - Values: 4 to 768 (default 256) ++ </td></tr> ++ ++ <tr> ++ <td>tx_thr_length</td> ++ <td>Transmit Threshold length in 32 bit double words ++ - Values: 8 to 128 (default 64) ++ </td></tr> ++ ++ <tr> ++ <td>rx_thr_length</td> ++ <td>Receive Threshold length in 32 bit double words ++ - Values: 8 to 128 (default 64) ++ </td></tr> ++ ++<tr> ++ <td>thr_ctl</td> ++ <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of ++ this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and ++ Rx transfers accordingly. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - Values: 0 to 7 (default 0) ++ Bit values indicate: ++ - 0: Thresholding disabled ++ - 1: Thresholding enabled ++ </td></tr> ++ ++<tr> ++ <td>dma_desc_enable</td> ++ <td>Specifies whether to enable Descriptor DMA mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Descriptor DMA disabled ++ - 1: Descriptor DMA (default, if available) ++ </td></tr> ++ ++<tr> ++ <td>mpi_enable</td> ++ <td>Specifies whether to enable MPI enhancement mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: MPI disabled (default) ++ - 1: MPI enable ++ </td></tr> ++ ++<tr> ++ <td>pti_enable</td> ++ <td>Specifies whether to enable PTI enhancement support. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: PTI disabled (default) ++ - 1: PTI enable ++ </td></tr> ++ ++<tr> ++ <td>lpm_enable</td> ++ <td>Specifies whether to enable LPM support. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: LPM disabled ++ - 1: LPM enable (default, if available) ++ </td></tr> ++ ++ <tr> ++ <td>besl_enable</td> ++ <td>Specifies whether to enable LPM Errata support. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: LPM Errata disabled (default) ++ - 1: LPM Errata enable ++ </td></tr> ++ ++ <tr> ++ <td>baseline_besl</td> ++ <td>Specifies the baseline besl value. ++ - Values: 0 to 15 (default 0) ++ </td></tr> ++ ++ <tr> ++ <td>deep_besl</td> ++ <td>Specifies the deep besl value. ++ - Values: 0 to 15 (default 15) ++ </td></tr> ++ ++<tr> ++ <td>ic_usb_cap</td> ++ <td>Specifies whether to enable IC_USB capability. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: IC_USB disabled (default, if available) ++ - 1: IC_USB enable ++ </td></tr> ++ ++<tr> ++ <td>ahb_thr_ratio</td> ++ <td>Specifies AHB Threshold ratio. ++ - Values: 0 to 3 (default 0) ++ </td></tr> ++ ++<tr> ++ <td>power_down</td> ++ <td>Specifies Power Down(Hibernation) Mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Power Down disabled (default) ++ - 2: Power Down enabled ++ </td></tr> ++ ++ <tr> ++ <td>reload_ctl</td> ++ <td>Specifies whether dynamic reloading of the HFIR register is allowed during ++ run time. The driver will automatically detect the value for this parameter if ++ none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0 ++ the core might misbehave. ++ - 0: Reload Control disabled (default) ++ - 1: Reload Control enabled ++ </td></tr> ++ ++ <tr> ++ <td>dev_out_nak</td> ++ <td>Specifies whether Device OUT NAK enhancement enabled or no. ++ The driver will automatically detect the value for this parameter if ++ none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1'b1. ++ - 0: The core does not set NAK after Bulk OUT transfer complete (default) ++ - 1: The core sets NAK after Bulk OUT transfer complete ++ </td></tr> ++ ++ <tr> ++ <td>cont_on_bna</td> ++ <td>Specifies whether Enable Continue on BNA enabled or no. ++ After receiving BNA interrupt the core disables the endpoint,when the ++ endpoint is re-enabled by the application the ++ - 0: Core starts processing from the DOEPDMA descriptor (default) ++ - 1: Core starts processing from the descriptor which received the BNA. ++ This parameter is valid only when OTG_EN_DESC_DMA == 1'b1. ++ </td></tr> ++ ++ <tr> ++ <td>ahb_single</td> ++ <td>This bit when programmed supports SINGLE transfers for remainder data ++ in a transfer for DMA mode of operation. ++ - 0: The remainder data will be sent using INCR burst size (default) ++ - 1: The remainder data will be sent using SINGLE burst size. ++ </td></tr> ++ ++<tr> ++ <td>adp_enable</td> ++ <td>Specifies whether ADP feature is enabled. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: ADP feature disabled (default) ++ - 1: ADP feature enabled ++ </td></tr> ++ ++ <tr> ++ <td>otg_ver</td> ++ <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3 ++ USB OTG device. ++ - 0: OTG 2.0 support disabled (default) ++ - 1: OTG 2.0 support enabled ++ </td></tr> ++ ++*/ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.h +new file mode 100644 +index 00000000..cddb6347 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_driver.h +@@ -0,0 +1,86 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_driver.h $ ++ * $Revision: #21 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __FH_OTG_DRIVER_H__ ++#define __FH_OTG_DRIVER_H__ ++ ++/** @file ++ * This file contains the interface to the Linux driver. ++ */ ++#include "fh_otg_os_dep.h" ++#include "fh_otg_core_if.h" ++ ++/* Type declarations */ ++struct fh_otg_pcd; ++struct fh_otg_hcd; ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single FH_otg controller. ++ */ ++typedef struct fh_otg_device { ++ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE ++ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD ++ * require this. */ ++ struct os_dependent os_dep; ++ ++ /** Pointer to the core interface structure. */ ++ fh_otg_core_if_t *core_if; ++ ++ /** Pointer to the PCD structure. */ ++ struct fh_otg_pcd *pcd; ++ ++ /** Pointer to the HCD structure. */ ++ struct fh_otg_hcd *hcd; ++ ++ /** Flag to indicate whether the common IRQ handler is installed. */ ++ uint8_t common_irq_installed; ++ ++} fh_otg_device_t; ++ ++/*We must clear S3C24XX_EINTPEND external interrupt register ++ * because after clearing in this register trigerred IRQ from ++ * H/W core in kernel interrupt can be occured again before OTG ++ * handlers clear all IRQ sources of Core registers because of ++ * timing latencies and Low Level IRQ Type. ++ */ ++#ifdef CONFIG_MACH_IPMATE ++#define S3C2410X_CLEAR_EINTPEND() \ ++do { \ ++ __raw_writel(1UL << 11,S3C24XX_EINTPEND); \ ++} while (0) ++#else ++#define S3C2410X_CLEAR_EINTPEND() do { } while (0) ++#endif ++ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.c +new file mode 100755 +index 00000000..449dccc5 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.c +@@ -0,0 +1,3459 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd.c $ ++ * $Revision: #110 $ ++ * $Date: 2013/05/19 $ ++ * $Change: 2234022 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++ ++/** @file ++ * This file implements HCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * Interface provided by HCD Core is defined in <code><hcd_if.h></code> ++ * header file. ++ */ ++ ++#include "fh_otg_hcd.h" ++#include "fh_otg_regs.h" ++ ++fh_otg_hcd_t *fh_otg_hcd_alloc_hcd(void) ++{ ++ return FH_ALLOC(sizeof(fh_otg_hcd_t)); ++} ++ ++/** ++ * Connection timeout function. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. ++ */ ++void fh_otg_hcd_connect_timeout(void *ptr) ++{ ++ fh_otg_hcd_t *hcd; ++ gpwrdn_data_t gpwrdn; ++ FH_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr); ++ FH_PRINTF("Connect Timeout\n"); ++ __FH_ERROR("Device Not Connected/Responding\n"); ++ /** Remove buspower after 10s */ ++ hcd = ptr; ++ if (hcd->core_if->otg_ver) ++ fh_otg_set_prtpower(hcd->core_if, 0); ++ if (hcd->core_if->adp_enable && !hcd->core_if->adp.probe_enabled) { ++ cil_hcd_disconnect(hcd->core_if); ++ gpwrdn.d32 = 0; ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&hcd->core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ fh_mdelay(220); ++ fh_otg_adp_probe_start(hcd->core_if); ++ } ++} ++ ++#ifdef DEBUG ++static void dump_channel_info(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ if (qh->channel != NULL) { ++ fh_hc_t *hc = qh->channel; ++ fh_list_link_t *item; ++ fh_otg_qh_t *qh_item; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ int i; ++ ++ fh_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ ++ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = FH_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ hcdma = FH_READ_REG32(&hc_regs->hcdma); ++ ++ FH_PRINTF(" Assigned to channel %p:\n", hc); ++ FH_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, ++ hcsplt.d32); ++ FH_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, ++ hcdma); ++ FH_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ FH_PRINTF(" ep_type: %d\n", hc->ep_type); ++ FH_PRINTF(" max_packet: %d\n", hc->max_packet); ++ FH_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ FH_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ FH_PRINTF(" halt_status: %d\n", hc->halt_status); ++ FH_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ FH_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ FH_PRINTF(" qh: %p\n", hc->qh); ++ FH_PRINTF(" NP inactive sched:\n"); ++ FH_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) { ++ qh_item = ++ FH_LIST_ENTRY(item, fh_otg_qh_t, qh_list_entry); ++ FH_PRINTF(" %p\n", qh_item); ++ } ++ FH_PRINTF(" NP active sched:\n"); ++ FH_LIST_FOREACH(item, &hcd->non_periodic_sched_active) { ++ qh_item = ++ FH_LIST_ENTRY(item, fh_otg_qh_t, qh_list_entry); ++ FH_PRINTF(" %p\n", qh_item); ++ } ++ FH_PRINTF(" Channels: \n"); ++ for (i = 0; i < num_channels; i++) { ++ fh_hc_t *hc = hcd->hc_ptr_array[i]; ++ FH_PRINTF(" %2d: %p\n", i, hc); ++ } ++ } ++} ++#endif /* DEBUG */ ++ ++/** ++ * Work queue function for starting the HCD when A-Cable is connected. ++ * The hcd_start() must be called in a process context. ++ */ ++static void hcd_start_func(void *_vp) ++{ ++ fh_otg_hcd_t *hcd = (fh_otg_hcd_t *) _vp; ++ ++ FH_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd); ++ if (hcd) { ++ hcd->fops->start(hcd); ++ } ++} ++ ++static void del_xfer_timers(fh_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int i; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ FH_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++} ++ ++static void del_timers(fh_otg_hcd_t * hcd) ++{ ++ del_xfer_timers(hcd); ++ FH_TIMER_CANCEL(hcd->conn_timer); ++} ++ ++/** ++ * Processes all the URBs in a single list of QHs. Completes them with ++ * -ETIMEDOUT and frees the QTD. ++ */ ++static void kill_urbs_in_qh_list(fh_otg_hcd_t * hcd, fh_list_link_t * qh_list) ++{ ++ fh_list_link_t *qh_item; ++ fh_otg_qh_t *qh; ++ fh_otg_qtd_t *qtd, *qtd_tmp; ++ ++ FH_LIST_FOREACH(qh_item, qh_list) { ++ qh = FH_LIST_ENTRY(qh_item, fh_otg_qh_t, qh_list_entry); ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, ++ &qh->qtd_list, qtd_list_entry) { ++ qtd = FH_CIRCLEQ_FIRST(&qh->qtd_list); ++ if (qtd->urb != NULL) { ++ if(!qtd->urb->priv) { ++ FH_ERROR("urb->priv is NULL !!!!\n"); ++ return; ++ } ++ if(!hcd->fops) ++ FH_ERROR("hcd->fops is NULL !!!!!\n"); ++ if(!hcd->fops->complete) ++ FH_ERROR("fops->complete is NULL !!!!\n"); ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -FH_E_TIMEOUT); ++ fh_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ ++ } ++ } ++} ++ ++/** ++ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic ++ * and periodic schedules. The QTD associated with each URB is removed from ++ * the schedule and freed. This function may be called when a disconnect is ++ * detected or when the HCD is being stopped. ++ */ ++static void kill_all_urbs(fh_otg_hcd_t * hcd) ++{ ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); ++} ++ ++/** ++ * Start the connection timer. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. The ++ * timer is deleted if a port connect interrupt occurs before the ++ * timer expires. ++ */ ++static void fh_otg_hcd_start_connect_timer(fh_otg_hcd_t * hcd) ++{ ++ FH_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ ); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int32_t fh_otg_hcd_session_start_cb(void *p) ++{ ++ fh_otg_hcd_t *fh_otg_hcd; ++ FH_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ fh_otg_hcd = p; ++ fh_otg_hcd_start_connect_timer(fh_otg_hcd); ++ return 1; ++} ++ ++/** ++ * HCD Callback function for starting the HCD when A-Cable is ++ * connected. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int32_t fh_otg_hcd_start_cb(void *p) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = p; ++ fh_otg_core_if_t *core_if; ++ hprt0_data_t hprt0; ++ uint32_t timeout = 50; ++ ++ core_if = fh_otg_hcd->core_if; ++ /**@todo vahrama: Check the timeout value for OTG 2.0 */ ++ if (core_if->otg_ver) ++ timeout = 25; ++ if (core_if->op_state == B_HOST) { ++ /* ++ * Reset the port. During a HNP mode switch the reset ++ * needs to occur within 1ms and have a duration of at ++ * least 50ms. ++ */ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ if (core_if->otg_ver) { ++ fh_mdelay(60); ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ } ++ FH_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, ++ hcd_start_func, fh_otg_hcd, timeout, ++ "start hcd"); ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int32_t fh_otg_hcd_disconnect_cb(void *p) ++{ ++ gintsts_data_t intr; ++ fh_otg_hcd_t *fh_otg_hcd = p; ++ ++ /* ++ * Set status flags for the hub driver. ++ */ ++ fh_otg_hcd->flags.b.port_connect_status_change = 1; ++ fh_otg_hcd->flags.b.port_connect_status = 0; ++ ++ /* ++ * Shutdown any transfers in process by clearing the Tx FIFO Empty ++ * interrupt mask and status bits and disabling subsequent host ++ * channel interrupts. ++ */ ++ intr.d32 = 0; ++ intr.b.nptxfempty = 1; ++ intr.b.ptxfempty = 1; ++ intr.b.hcintr = 1; ++ FH_MODIFY_REG32(&fh_otg_hcd->core_if->core_global_regs->gintmsk, ++ intr.d32, 0); ++ FH_MODIFY_REG32(&fh_otg_hcd->core_if->core_global_regs->gintsts, ++ intr.d32, 0); ++ ++ /* ++ * Turn off the vbus power only if the core has transitioned to device ++ * mode. If still in host mode, need to keep power on to detect a ++ * reconnection. ++ */ ++ if (fh_otg_is_device_mode(fh_otg_hcd->core_if)) { ++ if (fh_otg_hcd->core_if->op_state != A_SUSPEND) { ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ FH_PRINTF("Disconnect: PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ FH_WRITE_REG32(fh_otg_hcd->core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /** Delete timers if become device */ ++ del_timers(fh_otg_hcd); ++ fh_otg_disable_host_interrupts(fh_otg_hcd->core_if); ++ } ++ ++ /* Respond with an error status to all URBs in the schedule. */ ++ kill_all_urbs(fh_otg_hcd); ++ ++ if (fh_otg_is_host_mode(fh_otg_hcd->core_if)) { ++ /* Clean up any host channels that were in use. */ ++ int num_channels; ++ int i; ++ fh_hc_t *channel; ++ fh_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ ++ if (fh_otg_hcd->core_if->otg_ver == 1) ++ del_xfer_timers(fh_otg_hcd); ++ else ++ del_timers(fh_otg_hcd); ++ ++ num_channels = fh_otg_hcd->core_if->core_params->host_channels; ++ ++ if (!fh_otg_hcd->core_if->dma_enable) { ++ /* Flush out any channel requests in slave mode. */ ++ for (i = 0; i < num_channels; i++) { ++ channel = fh_otg_hcd->hc_ptr_array[i]; ++ if (FH_CIRCLEQ_EMPTY_ENTRY ++ (channel, hc_list_entry)) { ++ hc_regs = ++ fh_otg_hcd->core_if-> ++ host_if->hc_regs[i]; ++ hcchar.d32 = ++ FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ FH_WRITE_REG32 ++ (&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < num_channels; i++) { ++ channel = fh_otg_hcd->hc_ptr_array[i]; ++ if (FH_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { ++ hc_regs = ++ fh_otg_hcd->core_if->host_if->hc_regs[i]; ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ /* Halt the channel. */ ++ hcchar.b.chdis = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ ++ fh_otg_hc_cleanup(fh_otg_hcd->core_if, ++ channel); ++ FH_CIRCLEQ_INSERT_TAIL ++ (&fh_otg_hcd->free_hc_list, channel, ++ hc_list_entry); ++ /* ++ * Added for Descriptor DMA to prevent channel double cleanup ++ * in release_channel_ddma(). Which called from ep_disable ++ * when device disconnect. ++ */ ++ channel->qh = NULL; ++ } ++ } ++ } ++ ++ if (fh_otg_hcd->fops->disconnect) { ++ fh_otg_hcd->fops->disconnect(fh_otg_hcd); ++ } ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for stopping the HCD. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int32_t fh_otg_hcd_stop_cb(void *p) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = p; ++ ++ FH_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ fh_otg_hcd_stop(fh_otg_hcd); ++ return 1; ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++/** ++ * HCD Callback function for sleep of HCD. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int fh_otg_hcd_sleep_cb(void *p) ++{ ++ fh_otg_hcd_t *hcd = p; ++ ++ fh_otg_hcd_free_hc_from_lpm(hcd); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * HCD Callback function for Remote Wakeup. ++ * ++ * @param p void pointer to the <code>struct usb_hcd</code> ++ */ ++static int fh_otg_hcd_rem_wakeup_cb(void *p) ++{ ++ fh_otg_hcd_t *hcd = p; ++ ++ if (hcd->core_if->lx_state == FH_OTG_L2) { ++ hcd->flags.b.port_suspend_change = 1; ++ } ++#ifdef CONFIG_USB_FH_OTG_LPM ++ else { ++ hcd->flags.b.port_l1_change = 1; ++ } ++#endif ++ return 0; ++} ++ ++/** ++ * Halts the FH_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void fh_otg_hcd_stop(fh_otg_hcd_t * hcd) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD STOP\n"); ++ ++ /* ++ * The root hub should be disconnected before this function is called. ++ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) ++ * and the QH lists (via ..._hcd_endpoint_disable). ++ */ ++ ++ /* Turn off all host-specific interrupts. */ ++ fh_otg_disable_host_interrupts(hcd->core_if); ++ ++ /* Turn off the vbus power */ ++ FH_PRINTF("PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ FH_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ fh_mdelay(1); ++} ++ ++int fh_otg_hcd_urb_enqueue(fh_otg_hcd_t * hcd, ++ fh_otg_hcd_urb_t * fh_otg_urb, void **ep_handle, ++ int atomic_alloc) ++{ ++ fh_irqflags_t flags; ++ int retval = 0; ++ fh_otg_qtd_t *qtd; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!hcd->flags.b.port_connect_status) { ++ /* No longer connected. */ ++ FH_ERROR("Not connected\n"); ++ return -FH_E_NO_DEVICE; ++ } ++ ++ qtd = fh_otg_hcd_qtd_create(fh_otg_urb, atomic_alloc); ++ if (qtd == NULL) { ++ FH_ERROR("FH OTG HCD URB Enqueue failed creating QTD\n"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ retval = ++ fh_otg_hcd_qtd_add(qtd, hcd, (fh_otg_qh_t **) ep_handle, atomic_alloc); ++ if (retval < 0) { ++ FH_ERROR("FH OTG HCD URB Enqueue failed adding QTD. " ++ "Error status %d\n", retval); ++ fh_otg_hcd_qtd_free(qtd); ++ } else { ++ qtd->qh = *ep_handle; ++ } ++ intr_mask.d32 = FH_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); ++ if (!intr_mask.b.sofintr && retval == 0) { ++ fh_otg_transaction_type_e tr_type; ++ if ((qtd->qh->ep_type == UE_BULK) ++ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { ++ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ ++ return 0; ++ } ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ tr_type = fh_otg_hcd_select_transactions(hcd); ++ if (tr_type != FH_OTG_TRANSACTION_NONE) { ++ fh_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ } ++ ++ return retval; ++} ++ ++int fh_otg_hcd_urb_dequeue(fh_otg_hcd_t * hcd, ++ fh_otg_hcd_urb_t * fh_otg_urb) ++{ ++ fh_otg_qh_t *qh; ++ fh_otg_qtd_t *urb_qtd; ++ ++ urb_qtd = fh_otg_urb->qtd; ++ qh = urb_qtd->qh; ++ if (!urb_qtd) { ++ printk(KERN_ERR "## Urb QTD is NULL ##\n"); ++ return -EINVAL; ++ } ++ ++ qh = urb_qtd->qh; ++ if (!qh) { ++ printk(KERN_ERR "## Urb QH is NULL ##\n"); ++ return -EINVAL; ++ } ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ if (urb_qtd->in_process) { ++ dump_channel_info(hcd, qh); ++ } ++ } ++#endif ++ if (urb_qtd->in_process && qh->channel) { ++ /* The QTD is in process (it has been assigned to a channel). */ ++ if (hcd->flags.b.port_connect_status) { ++ /* ++ * If still connected (i.e. in host mode), halt the ++ * channel so it can be used for other transfers. If ++ * no longer connected, the host registers can't be ++ * written to halt the channel since the core is in ++ * device mode. ++ */ ++ fh_otg_hc_halt(hcd->core_if, qh->channel, ++ FH_OTG_HC_XFER_URB_DEQUEUE); ++ } ++ } ++ ++ /* ++ * Free the QTD and clean up the associated QH. Leave the QH in the ++ * schedule if it has any remaining QTDs. ++ */ ++ ++ if (!hcd->core_if->dma_desc_enable) { ++ uint8_t b = urb_qtd->in_process; ++ fh_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ if (b) { ++ fh_otg_hcd_qh_deactivate(hcd, qh, 0); ++ qh->channel = NULL; ++ } else if (FH_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ fh_otg_hcd_qh_remove(hcd, qh); ++ } ++ } else { ++ fh_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ } ++ return 0; ++} ++ ++int fh_otg_hcd_endpoint_disable(fh_otg_hcd_t * hcd, void *ep_handle, ++ int retry) ++{ ++ fh_otg_qh_t *qh = (fh_otg_qh_t *) ep_handle; ++ int retval = 0; ++ fh_irqflags_t flags; ++ ++ if (retry < 0) { ++ retval = -FH_E_INVALID; ++ goto done; ++ } ++ ++ if (!qh) { ++ retval = -FH_E_INVALID; ++ goto done; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ ++ while (!FH_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ retry--; ++ fh_msleep(5); ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } ++ ++ fh_otg_hcd_qh_remove(hcd, qh); ++ ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ /* ++ * Split fh_otg_hcd_qh_remove_and_free() into qh_remove ++ * and qh_free to prevent stack dump on FH_DMA_FREE() with ++ * irq_disabled (spinlock_irqsave) in fh_otg_hcd_desc_list_free() ++ * and fh_otg_hcd_frame_list_alloc(). ++ */ ++ fh_otg_hcd_qh_free(hcd, qh); ++ ++done: ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++int fh_otg_hcd_endpoint_reset(fh_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int retval = 0; ++ fh_otg_qh_t *qh = (fh_otg_qh_t *) ep_handle; ++ if (!qh) ++ return -FH_E_INVALID; ++ ++ qh->data_toggle = FH_OTG_HC_PID_DATA0; ++ return retval; ++} ++#endif ++ ++/** ++ * HCD Callback structure for handling mode switching. ++ */ ++static fh_otg_cil_callbacks_t hcd_cil_callbacks = { ++ .start = fh_otg_hcd_start_cb, ++ .stop = fh_otg_hcd_stop_cb, ++ .disconnect = fh_otg_hcd_disconnect_cb, ++ .session_start = fh_otg_hcd_session_start_cb, ++ .resume_wakeup = fh_otg_hcd_rem_wakeup_cb, ++#ifdef CONFIG_USB_FH_OTG_LPM ++ .sleep = fh_otg_hcd_sleep_cb, ++#endif ++ .p = 0, ++}; ++ ++/** ++ * Reset tasklet function ++ */ ++static void reset_tasklet_func(void *data) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = (fh_otg_hcd_t *) data; ++ fh_otg_core_if_t *core_if = fh_otg_hcd->core_if; ++ hprt0_data_t hprt0; ++ ++ FH_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); ++ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ fh_mdelay(60); ++ ++ hprt0.b.prtrst = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ fh_otg_hcd->flags.b.port_reset_change = 1; ++} ++ ++static void qh_list_free(fh_otg_hcd_t * hcd, fh_list_link_t * qh_list) ++{ ++ fh_list_link_t *item; ++ fh_otg_qh_t *qh; ++ fh_irqflags_t flags; ++ ++ if (!qh_list->next) { ++ /* The list hasn't been initialized yet. */ ++ return; ++ } ++ /* ++ * Hold spinlock here. Not needed in that case if bellow ++ * function is being called from ISR ++ */ ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ /* Ensure there are no QTDs or URBs left. */ ++ kill_urbs_in_qh_list(hcd, qh_list); ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++ FH_LIST_FOREACH(item, qh_list) { ++ qh = FH_LIST_ENTRY(item, fh_otg_qh_t, qh_list_entry); ++ fh_otg_hcd_qh_remove_and_free(hcd, qh); ++ } ++} ++ ++/** ++ * Exit from Hibernation if Host did not detect SRP from connected SRP capable ++ * Device during SRP time by host power up. ++ */ ++void fh_otg_hcd_power_up(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) ptr; ++ ++ FH_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ FH_PRINTF("Already exited from Hibernation\n"); ++ return; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ fh_udelay(10); ++ ++ /* Enable VBUS */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->op_state = A_HOST; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++} ++ ++/** ++ * Frees secondary storage associated with the fh_otg_hcd structure contained ++ * in the struct usb_hcd field. ++ */ ++static void fh_otg_hcd_free(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ int i; ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD FREE\n"); ++ ++ del_timers(fh_otg_hcd); ++ ++ /* Free memory for QH/QTD lists */ ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->non_periodic_sched_inactive); ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->non_periodic_sched_active); ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->periodic_sched_inactive); ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->periodic_sched_ready); ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->periodic_sched_assigned); ++ qh_list_free(fh_otg_hcd, &fh_otg_hcd->periodic_sched_queued); ++ ++ /* Free memory for the host channels. */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ fh_hc_t *hc = fh_otg_hcd->hc_ptr_array[i]; ++ ++#ifdef DEBUG ++ if (fh_otg_hcd->core_if->hc_xfer_timer[i]) { ++ FH_TIMER_FREE(fh_otg_hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++ if (hc != NULL) { ++ FH_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", ++ i, hc); ++ FH_FREE(hc); ++ } ++ } ++ ++ if (fh_otg_hcd->core_if->dma_enable) { ++ if (fh_otg_hcd->status_buf_dma) { ++ FH_DMA_FREE(FH_OTG_HCD_STATUS_BUF_SIZE, ++ fh_otg_hcd->status_buf, ++ fh_otg_hcd->status_buf_dma); ++ } ++ } else if (fh_otg_hcd->status_buf != NULL) { ++ FH_FREE(fh_otg_hcd->status_buf); ++ } ++ FH_SPINLOCK_FREE(fh_otg_hcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ fh_otg_hcd->core_if->lock = NULL; ++ ++ FH_TIMER_FREE(fh_otg_hcd->conn_timer); ++ FH_TASK_FREE(fh_otg_hcd->reset_tasklet); ++ ++#ifdef FH_DEV_SRPCAP ++ if (fh_otg_hcd->core_if->power_down == 2 && ++ fh_otg_hcd->core_if->pwron_timer) { ++ FH_TIMER_FREE(fh_otg_hcd->core_if->pwron_timer); ++ } ++#endif ++ FH_FREE(fh_otg_hcd); ++} ++ ++int fh_otg_hcd_init(fh_otg_hcd_t * hcd, fh_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int num_channels; ++ int i; ++ fh_hc_t *channel; ++ ++ hcd->lock = FH_SPINLOCK_ALLOC(); ++ if (!hcd->lock) { ++ FH_ERROR("Could not allocate lock for pcd"); ++ FH_FREE(hcd); ++ retval = -FH_E_NO_MEMORY; ++ goto out; ++ } ++ hcd->core_if = core_if; ++ ++ /* Register the HCD CIL Callbacks */ ++ fh_otg_cil_register_hcd_callbacks(hcd->core_if, ++ &hcd_cil_callbacks, hcd); ++ ++ /* Initialize the non-periodic schedule. */ ++ FH_LIST_INIT(&hcd->non_periodic_sched_inactive); ++ FH_LIST_INIT(&hcd->non_periodic_sched_active); ++ ++ /* Initialize the periodic schedule. */ ++ FH_LIST_INIT(&hcd->periodic_sched_inactive); ++ FH_LIST_INIT(&hcd->periodic_sched_ready); ++ FH_LIST_INIT(&hcd->periodic_sched_assigned); ++ FH_LIST_INIT(&hcd->periodic_sched_queued); ++ ++ /* ++ * Create a host channel descriptor for each host channel implemented ++ * in the controller. Initialize the channel descriptor array. ++ */ ++ FH_CIRCLEQ_INIT(&hcd->free_hc_list); ++ num_channels = hcd->core_if->core_params->host_channels; ++ FH_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); ++ for (i = 0; i < num_channels; i++) { ++ channel = FH_ALLOC(sizeof(fh_hc_t)); ++ if (channel == NULL) { ++ retval = -FH_E_NO_MEMORY; ++ FH_ERROR("%s: host channel allocation failed\n", ++ __func__); ++ fh_otg_hcd_free(hcd); ++ goto out; ++ } ++ channel->hc_num = i; ++ hcd->hc_ptr_array[i] = channel; ++#ifdef DEBUG ++ hcd->core_if->hc_xfer_timer[i] = ++ FH_TIMER_ALLOC("hc timer", hc_xfer_timeout, ++ &hcd->core_if->hc_xfer_info[i]); ++#endif ++ FH_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, ++ channel); ++ } ++ ++ /* Initialize the Connection timeout timer. */ ++ hcd->conn_timer = FH_TIMER_ALLOC("Connection timer", ++ fh_otg_hcd_connect_timeout, hcd); ++ ++ /* Initialize reset tasklet. */ ++ hcd->reset_tasklet = FH_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); ++#ifdef FH_DEV_SRPCAP ++ if (hcd->core_if->power_down == 2) { ++ /* Initialize Power on timer for Host power up in case hibernation */ ++ hcd->core_if->pwron_timer = FH_TIMER_ALLOC("PWRON TIMER", ++ fh_otg_hcd_power_up, core_if); ++ } ++#endif ++ ++ /* ++ * Allocate space for storing data on status transactions. Normally no ++ * data is sent, but this space acts as a bit bucket. This must be ++ * done after usb_add_hcd since that function allocates the DMA buffer ++ * pool. ++ */ ++ if (hcd->core_if->dma_enable) { ++ hcd->status_buf = ++ FH_DMA_ALLOC(FH_OTG_HCD_STATUS_BUF_SIZE, ++ &hcd->status_buf_dma); ++ } else { ++ hcd->status_buf = FH_ALLOC(FH_OTG_HCD_STATUS_BUF_SIZE); ++ } ++ if (!hcd->status_buf) { ++ retval = -FH_E_NO_MEMORY; ++ FH_ERROR("%s: status_buf allocation failed\n", __func__); ++ fh_otg_hcd_free(hcd); ++ goto out; ++ } ++ ++ hcd->otg_port = 1; ++ hcd->frame_list = NULL; ++ hcd->frame_list_dma = 0; ++ hcd->periodic_qh_count = 0; ++out: ++ return retval; ++} ++ ++void fh_otg_hcd_remove(fh_otg_hcd_t * hcd) ++{ ++ /* Turn off all host-specific interrupts. */ ++ fh_otg_disable_host_interrupts(hcd->core_if); ++ ++ fh_otg_hcd_free(hcd); ++} ++ ++/** ++ * Initializes dynamic portions of the FH_otg HCD state. ++ */ ++static void fh_otg_hcd_reinit(fh_otg_hcd_t * hcd) ++{ ++ int num_channels; ++ int i; ++ fh_hc_t *channel; ++ fh_hc_t *channel_tmp; ++ ++ hcd->flags.d32 = 0; ++ ++ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ ++ /* ++ * Put all channels in the free channel list and clean up channel ++ * states. ++ */ ++ FH_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp, ++ &hcd->free_hc_list, hc_list_entry) { ++ FH_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry); ++ } ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = hcd->hc_ptr_array[i]; ++ FH_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel, ++ hc_list_entry); ++ fh_otg_hc_cleanup(hcd->core_if, channel); ++ } ++ ++ /* Initialize the FH core for host mode operation. */ ++ fh_otg_core_host_init(hcd->core_if); ++ ++ /* Set core_if's lock pointer to the hcd->lock */ ++ hcd->core_if->lock = hcd->lock; ++} ++ ++/** ++ * Assigns transactions from a QTD to a free host channel and initializes the ++ * host channel to perform the transactions. The host channel is removed from ++ * the free list. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh Transactions from the first QTD for this QH are selected and ++ * assigned to a free host channel. ++ */ ++static int assign_and_init_hc(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ fh_hc_t *hc = NULL; ++ fh_otg_qtd_t *qtd; ++ fh_otg_hcd_urb_t *urb; ++ void* ptr = NULL; ++ hcchar_data_t hcchar; ++ int num_channels; ++ int i; ++ ++ FH_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh); ++ ++ qtd = FH_CIRCLEQ_FIRST(&qh->qtd_list); ++ if (!qtd) { ++ FH_ERROR("qh qtd is none\n"); ++ return -ENOMEM; ++ } ++ urb = qtd->urb; ++ if (!urb) { ++ FH_ERROR("hcd urb is none\n"); ++ return -ENOMEM; ++ } ++ num_channels = hcd->core_if->core_params->host_channels; ++ ++ /* WA to not select channel with chdis bit set, this was ++ * observed after role switch as part of OTG 2.0 HNP ++ */ ++ for (i = 0; i < num_channels; i++) { ++ hc = FH_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ hcchar.d32 = FH_READ_REG32(&hcd->core_if->host_if->hc_regs[hc->hc_num]->hcchar); ++ FH_DEBUGPL(DBG_HCDV, "HC num = %d HCCHAR %08x\n", hc->hc_num, hcchar.d32); ++ if(!hcchar.b.chdis && !hcchar.b.chen) ++ break; ++ FH_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ FH_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc = NULL; ++ } ++ if (!hc) { ++ FH_ERROR("No free channel with en and dis bits 0\n"); ++ return -ENOMEM; ++ } ++ ++ ++ ++ /* Remove the host channel from the free list. */ ++ FH_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ qh->channel = hc; ++ ++ qtd->in_process = 1; ++ ++ /* ++ * Use usb_pipedevice to determine device address. This address is ++ * 0 before the SET_ADDRESS command and the correct address afterward. ++ */ ++ hc->dev_addr = fh_otg_hcd_get_dev_addr(&urb->pipe_info); ++ hc->ep_num = fh_otg_hcd_get_ep_num(&urb->pipe_info); ++ hc->speed = qh->dev_speed; ++ hc->max_packet = fh_max_packet(qh->maxp); ++ ++ hc->xfer_started = 0; ++ hc->halt_status = FH_OTG_HC_XFER_NO_HALT_STATUS; ++ hc->error_state = (qtd->error_count > 0); ++ hc->halt_on_queue = 0; ++ hc->halt_pending = 0; ++ hc->requests = 0; ++ ++ /* ++ * The following values may be modified in the transfer type section ++ * below. The xfer_len value may be reduced when the transfer is ++ * started to accommodate the max widths of the XferSize and PktCnt ++ * fields in the HCTSIZn register. ++ */ ++ ++ hc->ep_is_in = (fh_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } else { ++ hc->do_ping = qh->ping_state; ++ } ++ ++ hc->data_pid_start = qh->data_toggle; ++ hc->multi_count = 1; ++ ++ if (urb->actual_length > urb->length && ++ !fh_otg_hcd_is_pipe_in(&urb->pipe_info)) { ++ urb->actual_length = urb->length; ++ } ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; ++ ++ /* For non-dword aligned case */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && !hcd->core_if->dma_desc_enable) { ++ ptr = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ hc->xfer_len = urb->length - urb->actual_length; ++ hc->xfer_count = 0; ++ ++ /* ++ * Set the split attributes ++ */ ++ hc->do_split = 0; ++ if (qh->do_split) { ++ uint32_t hub_addr, port_addr; ++ hc->do_split = 1; ++ hc->xact_pos = qtd->isoc_split_pos; ++ hc->complete_split = qtd->complete_split; ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); ++ hc->hub_addr = (uint8_t) hub_addr; ++ hc->port_addr = (uint8_t) port_addr; ++ } ++ ++ switch (fh_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ hc->ep_type = FH_OTG_EP_TYPE_CONTROL; ++ switch (qtd->control_phase) { ++ case FH_OTG_CONTROL_SETUP: ++ FH_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); ++ hc->do_ping = 0; ++ hc->ep_is_in = 0; ++ hc->data_pid_start = FH_OTG_HC_PID_SETUP; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->setup_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->setup_packet; ++ } ++ hc->xfer_len = 8; ++ ptr = NULL; ++ break; ++ case FH_OTG_CONTROL_DATA: ++ FH_DEBUGPL(DBG_HCDV, " Control data transaction\n"); ++ hc->data_pid_start = qtd->data_toggle; ++ break; ++ case FH_OTG_CONTROL_STATUS: ++ /* ++ * Direction is opposite of data direction or IN if no ++ * data. ++ */ ++ FH_DEBUGPL(DBG_HCDV, " Control status transaction\n"); ++ if (urb->length == 0) { ++ hc->ep_is_in = 1; ++ } else { ++ hc->ep_is_in = ++ fh_otg_hcd_is_pipe_out(&urb->pipe_info); ++ } ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } ++ ++ hc->data_pid_start = FH_OTG_HC_PID_DATA1; ++ ++ hc->xfer_len = 0; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf; ++ } ++ ptr = NULL; ++ break; ++ } ++ break; ++ case UE_BULK: ++ hc->ep_type = FH_OTG_EP_TYPE_BULK; ++ break; ++ case UE_INTERRUPT: ++ hc->ep_type = FH_OTG_EP_TYPE_INTR; ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ struct fh_otg_hcd_iso_packet_desc *frame_desc; ++ ++ hc->ep_type = FH_OTG_EP_TYPE_ISOC; ++ ++ if (hcd->core_if->dma_desc_enable) ++ break; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ ++ frame_desc->status = 0; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf; ++ } ++ hc->xfer_buff += ++ frame_desc->offset + qtd->isoc_split_offset; ++ hc->xfer_len = ++ frame_desc->length - qtd->isoc_split_offset; ++ ++ /* For non-dword aligned buffers */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && hcd->core_if->dma_enable) { ++ ptr = ++ (uint8_t *) urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset; ++ } else ++ ptr = NULL; ++ ++ if (hc->xact_pos == FH_HCSPLIT_XACTPOS_ALL) { ++ if (hc->xfer_len <= 188) { ++ hc->xact_pos = FH_HCSPLIT_XACTPOS_ALL; ++ } else { ++ hc->xact_pos = ++ FH_HCSPLIT_XACTPOS_BEGIN; ++ } ++ } ++ } ++ break; ++ } ++ /* non DWORD-aligned buffer case */ ++ if (ptr) { ++ uint32_t buf_size; ++ if (hc->ep_type != FH_OTG_EP_TYPE_ISOC) { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } else { ++ buf_size = 4096; ++ } ++ if (!qh->dw_align_buf) { ++ qh->dw_align_buf = FH_DMA_ALLOC_ATOMIC(buf_size, ++ &qh->dw_align_buf_dma); ++ printk(KERN_ERR "FH_DMA_ALLOC_ATOMIC (%p)\n", qh->dw_align_buf); ++ if (!qh->dw_align_buf) { ++ FH_ERROR ++ ("%s: Failed to allocate memory to handle " ++ "non-dword aligned buffer case\n", ++ __func__); ++ return -ENOMEM; ++ } ++ } ++ if (!hc->ep_is_in) { ++ fh_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); ++ } ++ hc->align_buff = qh->dw_align_buf_dma; ++ } else { ++ hc->align_buff = 0; ++ } ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * This value may be modified when the transfer is started to ++ * reflect the actual transfer length. ++ */ ++ hc->multi_count = fh_hb_mult(qh->maxp); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) ++ hc->desc_list_addr = qh->desc_list_dma; ++ ++ fh_otg_hc_init(hcd->core_if, hc); ++ hc->qh = qh; ++ ++ return 0; ++} ++ ++/** ++ * This function selects transactions from the HCD transfer schedule and ++ * assigns them to available host channels. It is called from HCD interrupt ++ * handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * ++ * @return The types of new transactions that were assigned to host channels. ++ */ ++fh_otg_transaction_type_e fh_otg_hcd_select_transactions(fh_otg_hcd_t * hcd) ++{ ++ fh_list_link_t *qh_ptr; ++ fh_otg_qh_t *qh; ++ int num_channels; ++ fh_otg_transaction_type_e ret_val = FH_OTG_TRANSACTION_NONE; ++ ++#ifdef DEBUG_SOF ++ FH_DEBUGPL(DBG_HCD, " Select Transactions\n"); ++#endif ++ ++ /* Process entries in the periodic ready list. */ ++ qh_ptr = FH_LIST_FIRST(&hcd->periodic_sched_ready); ++ ++ while (qh_ptr != &hcd->periodic_sched_ready && ++ !FH_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = FH_LIST_ENTRY(qh_ptr, fh_otg_qh_t, qh_list_entry); ++ if (assign_and_init_hc(hcd, qh)) ++ break; ++ ++ /* ++ * Move the QH from the periodic ready schedule to the ++ * periodic assigned schedule. ++ */ ++ qh_ptr = FH_LIST_NEXT(qh_ptr); ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ ++ ret_val = FH_OTG_TRANSACTION_PERIODIC; ++ } ++ ++ /* ++ * Process entries in the inactive portion of the non-periodic ++ * schedule. Some free host channels may not be used if they are ++ * reserved for periodic transfers. ++ */ ++ qh_ptr = hcd->non_periodic_sched_inactive.next; ++ num_channels = hcd->core_if->core_params->host_channels; ++ while (qh_ptr != &hcd->non_periodic_sched_inactive && ++ (hcd->non_periodic_channels < ++ num_channels - hcd->periodic_channels) && ++ !FH_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ qh = FH_LIST_ENTRY(qh_ptr, fh_otg_qh_t, qh_list_entry); ++ ++ if (FH_CIRCLEQ_EMPTY(&qh->qtd_list)) ++ break; ++ if (assign_and_init_hc(hcd, qh)) ++ break; ++ ++ /* ++ * Move the QH from the non-periodic inactive schedule to the ++ * non-periodic active schedule. ++ */ ++ qh_ptr = FH_LIST_NEXT(qh_ptr); ++ FH_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, ++ &qh->qh_list_entry); ++ ++ if (ret_val == FH_OTG_TRANSACTION_NONE) { ++ ret_val = FH_OTG_TRANSACTION_NON_PERIODIC; ++ } else { ++ ret_val = FH_OTG_TRANSACTION_ALL; ++ } ++ ++ hcd->non_periodic_channels++; ++ } ++ ++ return ret_val; ++} ++ ++/** ++ * Attempts to queue a single transaction request for a host channel ++ * associated with either a periodic or non-periodic transfer. This function ++ * assumes that there is space available in the appropriate request queue. For ++ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space ++ * is available in the appropriate Tx FIFO. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc Host channel descriptor associated with either a periodic or ++ * non-periodic transfer. ++ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx ++ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic ++ * transfers. ++ * ++ * @return 1 if a request is queued and more requests may be needed to ++ * complete the transfer, 0 if no more requests are required for this ++ * transfer, -1 if there is insufficient space in the Tx FIFO. ++ */ ++static int queue_transaction(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, uint16_t fifo_dwords_avail) ++{ ++ int retval; ++ ++ if (hcd->core_if->dma_enable) { ++ if (hcd->core_if->dma_desc_enable) { ++ if (!hc->xfer_started ++ || (hc->ep_type == FH_OTG_EP_TYPE_ISOC)) { ++ fh_otg_hcd_start_xfer_ddma(hcd, hc->qh); ++ hc->qh->ping_state = 0; ++ } ++ } else if (!hc->xfer_started) { ++ fh_otg_hc_start_transfer(hcd->core_if, hc); ++ hc->qh->ping_state = 0; ++ } ++ retval = 0; ++ } else if (hc->halt_pending) { ++ /* Don't queue a request if the channel has been halted. */ ++ retval = 0; ++ } else if (hc->halt_on_queue) { ++ fh_otg_hc_halt(hcd->core_if, hc, hc->halt_status); ++ retval = 0; ++ } else if (hc->do_ping) { ++ if (!hc->xfer_started) { ++ fh_otg_hc_start_transfer(hcd->core_if, hc); ++ } ++ retval = 0; ++ } else if (!hc->ep_is_in || hc->data_pid_start == FH_OTG_HC_PID_SETUP) { ++ if ((fifo_dwords_avail * 4) >= hc->max_packet) { ++ if (!hc->xfer_started) { ++ fh_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = ++ fh_otg_hc_continue_transfer(hcd->core_if, ++ hc); ++ } ++ } else { ++ retval = -1; ++ } ++ } else { ++ if (!hc->xfer_started) { ++ fh_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = fh_otg_hc_continue_transfer(hcd->core_if, hc); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Processes periodic channels for the next frame and queues transactions for ++ * these channels to the FH_otg controller. After queueing transactions, the ++ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions ++ * to queue as Periodic Tx FIFO or request queue space becomes available. ++ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. ++ */ ++static void process_periodic_channels(fh_otg_hcd_t * hcd) ++{ ++ hptxsts_data_t tx_status; ++ fh_list_link_t *qh_ptr; ++ fh_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ ++ fh_otg_host_global_regs_t *host_regs; ++ host_regs = hcd->core_if->host_if->host_global_regs; ++ ++ FH_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = FH_READ_REG32(&host_regs->hptxsts); ++ FH_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ FH_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ ++ qh_ptr = hcd->periodic_sched_assigned.next; ++ while (qh_ptr != &hcd->periodic_sched_assigned) { ++ tx_status.d32 = FH_READ_REG32(&host_regs->hptxsts); ++ if (tx_status.b.ptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = FH_LIST_ENTRY(qh_ptr, fh_otg_qh_t, qh_list_entry); ++ ++ /* ++ * Set a flag if we're queuing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* ++ * In Slave mode, stay on the current transfer until there is ++ * nothing more to do or the high-bandwidth request count is ++ * reached. In DMA mode, only need to queue one request. The ++ * controller automatically handles multiple packets for ++ * high-bandwidth transfers. ++ */ ++ if (hcd->core_if->dma_enable || status == 0 || ++ qh->channel->requests == qh->channel->multi_count) { ++ qh_ptr = qh_ptr->next; ++ /* ++ * Move the QH from the periodic assigned schedule to ++ * the periodic queued schedule. ++ */ ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_queued, ++ &qh->qh_list_entry); ++ ++ /* done queuing high bandwidth */ ++ hcd->core_if->queuing_high_bandwidth = 0; ++ } ++ } ++ ++ if (!hcd->core_if->dma_enable) { ++ fh_otg_core_global_regs_t *global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ global_regs = hcd->core_if->core_global_regs; ++ intr_mask.b.ptxfempty = 1; ++#ifdef DEBUG ++ tx_status.d32 = FH_READ_REG32(&host_regs->hptxsts); ++ FH_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ FH_DEBUGPL(DBG_HCDV, ++ " P Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ if (!FH_LIST_EMPTY(&hcd->periodic_sched_assigned) || ++ no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the periodic Tx ++ * FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ FH_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * Processes active non-periodic channels and queues transactions for these ++ * channels to the FH_otg controller. After queueing transactions, the NP Tx ++ * FIFO Empty interrupt is enabled if there are more transactions to queue as ++ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx ++ * FIFO Empty interrupt is disabled. ++ */ ++static void process_non_periodic_channels(fh_otg_hcd_t * hcd) ++{ ++ gnptxsts_data_t tx_status; ++ fh_list_link_t *orig_qh_ptr; ++ fh_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ int more_to_do = 0; ++ ++ fh_otg_core_global_regs_t *global_regs = ++ hcd->core_if->core_global_regs; ++ ++ FH_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ FH_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ FH_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ /* ++ * Keep track of the starting point. Skip over the start-of-list ++ * entry. ++ */ ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ } ++ orig_qh_ptr = hcd->non_periodic_qh_ptr; ++ ++ /* ++ * Process once through the active list or until no more space is ++ * available in the request queue or the Tx FIFO. ++ */ ++ do { ++ tx_status.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = FH_LIST_ENTRY(hcd->non_periodic_qh_ptr, fh_otg_qh_t, ++ qh_list_entry); ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); ++ ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* Advance to next QH, skipping start-of-list entry. */ ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ ++ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); ++ ++ if (!hcd->core_if->dma_enable) { ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ ++#ifdef DEBUG ++ tx_status.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ FH_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ FH_DEBUGPL(DBG_HCDV, ++ " NP Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ if (more_to_do || no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the non-periodic ++ * Tx FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ FH_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * This function processes the currently active host channels and queues ++ * transactions for these channels to the FH_otg controller. It is called ++ * from HCD interrupt handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * @param tr_type The type(s) of transactions to queue (non-periodic, ++ * periodic, or both). ++ */ ++void fh_otg_hcd_queue_transactions(fh_otg_hcd_t * hcd, ++ fh_otg_transaction_type_e tr_type) ++{ ++#ifdef DEBUG_SOF ++ FH_DEBUGPL(DBG_HCD, "Queue Transactions\n"); ++#endif ++ /* Process host channels associated with periodic transfers. */ ++ if ((tr_type == FH_OTG_TRANSACTION_PERIODIC || ++ tr_type == FH_OTG_TRANSACTION_ALL) && ++ !FH_LIST_EMPTY(&hcd->periodic_sched_assigned)) { ++ ++ process_periodic_channels(hcd); ++ } ++ ++ /* Process host channels associated with non-periodic transfers. */ ++ if (tr_type == FH_OTG_TRANSACTION_NON_PERIODIC || ++ tr_type == FH_OTG_TRANSACTION_ALL) { ++ if (!FH_LIST_EMPTY(&hcd->non_periodic_sched_active)) { ++ process_non_periodic_channels(hcd); ++ } else { ++ /* ++ * Ensure NP Tx FIFO empty interrupt is disabled when ++ * there are no non-periodic transfers to process. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintmsk.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&hcd->core_if-> ++ core_global_regs->gintmsk, gintmsk.d32, ++ 0); ++ } ++ } ++} ++ ++#ifdef FH_HS_ELECT_TST ++/* ++ * Quick and dirty hack to implement the HS Electrical Test ++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. ++ * ++ * This code was copied from our userspace app "hset". It sends a ++ * Get Device Descriptor control sequence in two parts, first the ++ * Setup packet by itself, followed some time later by the In and ++ * Ack packets. Rather than trying to figure out how to add this ++ * functionality to the normal driver code, we just hijack the ++ * hardware, using these two function to drive the hardware ++ * directly. ++ */ ++ ++static fh_otg_core_global_regs_t *global_regs; ++static fh_otg_host_global_regs_t *hc_global_regs; ++static fh_otg_hc_regs_t *hc_regs; ++static uint32_t *data_fifo; ++ ++static void do_setup(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ ++ /* Enable HAINTs */ ++ FH_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ FH_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Send Setup packet (Get Device Descriptor) ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++// hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ fh_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = FH_OTG_HC_PID_SETUP; ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = FH_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ /* Fill FIFO with Setup data for Get Device Descriptor */ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ FH_WRITE_REG32(data_fifo++, 0x01000680); ++ FH_WRITE_REG32(data_fifo++, 0x00080000); ++ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ FH_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ FH_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++} ++ ++static void do_in_ack(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ host_grxsts_data_t grxsts; ++ ++ /* Enable HAINTs */ ++ FH_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ FH_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Receive Control In packet ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ fh_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = FH_OTG_HC_PID_DATA1; ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = FH_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 1; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = FH_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case FH_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer */ ++ if (grxsts.b.bcnt > 0) { ++ int i; ++ int word_count = (grxsts.b.bcnt + 3) / 4; ++ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ ++ for (i = 0; i < word_count; i++) { ++ (void)FH_READ_REG32(data_fifo++); ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = FH_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case FH_GRXSTS_PKTSTS_IN_XFER_COMP: ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++// usleep(100000); ++// mdelay(100); ++ fh_mdelay(1); ++ ++ /* ++ * Send handshake packet ++ */ ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ fh_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 0; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = FH_OTG_HC_PID_DATA1; ++ FH_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = FH_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ FH_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ FH_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ FH_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = FH_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ FH_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ FH_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = FH_READ_REG32(&global_regs->gintsts); ++} ++#endif ++ ++/** Handles hub class-specific requests. */ ++int fh_otg_hcd_hub_control(fh_otg_hcd_t * fh_otg_hcd, ++ uint16_t typeReq, ++ uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, uint16_t wLength) ++{ ++ int retval = 0; ++ ++ fh_otg_core_if_t *core_if = fh_otg_hcd->core_if; ++ usb_hub_descriptor_t *hub_desc; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ uint32_t port_status; ++ ++ switch (typeReq) { ++ case UCR_CLEAR_HUB_FEATURE: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearHubFeature 0x%x\n", wValue); ++ switch (wValue) { ++ case UHF_C_HUB_LOCAL_POWER: ++ case UHF_C_HUB_OVER_CURRENT: ++ /* Nothing required here */ ++ break; ++ default: ++ retval = -FH_E_INVALID; ++ FH_ERROR("FH OTG HCD - " ++ "ClearHubFeature request %xh unknown\n", ++ wValue); ++ } ++ break; ++ case UCR_CLEAR_PORT_FEATURE: ++#ifdef CONFIG_USB_FH_OTG_LPM ++ if (wValue != UHF_PORT_L1) ++#endif ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ switch (wValue) { ++ case UHF_PORT_ENABLE: ++ FH_DEBUGPL(DBG_ANY, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtena = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_SUSPEND: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); ++ ++ if (core_if->power_down == 2) { ++ fh_otg_host_hibernation_restore(core_if, 0, 0); ++ } else { ++ FH_WRITE_REG32(core_if->pcgcctl, 0); ++ fh_mdelay(5); ++ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.b.prtsusp = 0; ++ /* Clear Resume bit */ ++ fh_mdelay(100); ++ hprt0.b.prtres = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ break; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ case UHF_PORT_L1: ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ FH_READ_REG32(&core_if-> ++ core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.prt_sleep_sts = 1; ++ FH_WRITE_REG32(&core_if-> ++ core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, ++ 0); ++ ++ fh_mdelay(5); ++ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ /* This bit will be cleared in wakeup interrupt handle */ ++ break; ++ } ++#endif ++ case UHF_PORT_POWER: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_INDICATOR: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); ++ /* Port inidicator not supported */ ++ break; ++ case UHF_C_PORT_CONNECTION: ++ /* Clears drivers internal connect status change ++ * flag */ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); ++ fh_otg_hcd->flags.b.port_connect_status_change = 0; ++ break; ++ case UHF_C_PORT_RESET: ++ /* Clears the driver's internal Port Reset Change ++ * flag */ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); ++ fh_otg_hcd->flags.b.port_reset_change = 0; ++ break; ++ case UHF_C_PORT_ENABLE: ++ /* Clears the driver's internal Port ++ * Enable/Disable Change flag */ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); ++ fh_otg_hcd->flags.b.port_enable_change = 0; ++ break; ++ case UHF_C_PORT_SUSPEND: ++ /* Clears the driver's internal Port Suspend ++ * Change flag, which is set when resume signaling on ++ * the host port is complete */ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); ++ fh_otg_hcd->flags.b.port_suspend_change = 0; ++ break; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ case UHF_C_PORT_L1: ++ fh_otg_hcd->flags.b.port_l1_change = 0; ++ break; ++#endif ++ case UHF_C_PORT_OVER_CURRENT: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); ++ fh_otg_hcd->flags.b.port_over_current_change = 0; ++ break; ++ default: ++ retval = -FH_E_INVALID; ++ FH_ERROR("FH OTG HCD - " ++ "ClearPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ } ++ break; ++ case UCR_GET_HUB_DESCRIPTOR: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "GetHubDescriptor\n"); ++ hub_desc = (usb_hub_descriptor_t *) buf; ++ hub_desc->bDescLength = 9; ++ hub_desc->bDescriptorType = 0x29; ++ hub_desc->bNbrPorts = 1; ++ USETW(hub_desc->wHubCharacteristics, 0x08); ++ hub_desc->bPwrOn2PwrGood = 1; ++ hub_desc->bHubContrCurrent = 0; ++ hub_desc->DeviceRemovable[0] = 0; ++ hub_desc->DeviceRemovable[1] = 0xff; ++ break; ++ case UCR_GET_HUB_STATUS: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "GetHubStatus\n"); ++ FH_MEMSET(buf, 0, 4); ++ break; ++ case UCR_GET_PORT_STATUS: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", ++ wIndex, fh_otg_hcd->flags.d32); ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ port_status = 0; ++ ++ if (fh_otg_hcd->flags.b.port_connect_status_change) ++ port_status |= (1 << UHF_C_PORT_CONNECTION); ++ ++ if (fh_otg_hcd->flags.b.port_enable_change) ++ port_status |= (1 << UHF_C_PORT_ENABLE); ++ ++ if (fh_otg_hcd->flags.b.port_suspend_change) ++ port_status |= (1 << UHF_C_PORT_SUSPEND); ++ ++ if (fh_otg_hcd->flags.b.port_l1_change) ++ port_status |= (1 << UHF_C_PORT_L1); ++ ++ if (fh_otg_hcd->flags.b.port_reset_change) { ++ port_status |= (1 << UHF_C_PORT_RESET); ++ } ++ ++ if (fh_otg_hcd->flags.b.port_over_current_change) { ++ FH_WARN("Overcurrent change detected\n"); ++ port_status |= (1 << UHF_C_PORT_OVER_CURRENT); ++ } ++ ++ if (!fh_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return 0's for the remainder of the port status ++ * since the port register can't be read if the core ++ * is in device mode. ++ */ ++ *((__le32 *) buf) = fh_cpu_to_le32(&port_status); ++ break; ++ } ++ ++ hprt0.d32 = FH_READ_REG32(core_if->host_if->hprt0); ++ FH_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); ++ ++ if (hprt0.b.prtconnsts) ++ port_status |= (1 << UHF_PORT_CONNECTION); ++ ++ if (hprt0.b.prtena) ++ port_status |= (1 << UHF_PORT_ENABLE); ++ ++ if (hprt0.b.prtsusp) ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ ++ if (hprt0.b.prtovrcurract) ++ port_status |= (1 << UHF_PORT_OVER_CURRENT); ++ ++ if (hprt0.b.prtrst) ++ port_status |= (1 << UHF_PORT_RESET); ++ ++ if (hprt0.b.prtpwr) ++ port_status |= (1 << UHF_PORT_POWER); ++ ++ if (hprt0.b.prtspd == FH_HPRT0_PRTSPD_HIGH_SPEED) ++ port_status |= (1 << UHF_PORT_HIGH_SPEED); ++ else if (hprt0.b.prtspd == FH_HPRT0_PRTSPD_LOW_SPEED) ++ port_status |= (1 << UHF_PORT_LOW_SPEED); ++ ++ if (hprt0.b.prttstctl) ++ port_status |= (1 << UHF_PORT_TEST); ++ if (fh_otg_get_lpm_portsleepstatus(fh_otg_hcd->core_if)) { ++ port_status |= (1 << UHF_PORT_L1); ++ } ++ /* ++ For Synopsys HW emulation of Power down wkup_control asserts the ++ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. ++ We intentionally tell the software that port is in L2Suspend state. ++ Only for STE. ++ */ ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ } ++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ ++ ++ *((__le32 *) buf) = fh_cpu_to_le32(&port_status); ++ ++ break; ++ case UCR_SET_HUB_FEATURE: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "SetHubFeature\n"); ++ /* No HUB features supported */ ++ break; ++ case UCR_SET_PORT_FEATURE: ++ if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1)) ++ goto error; ++ ++ if (!fh_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return without doing anything since the port ++ * register can't be written if the core is in device ++ * mode. ++ */ ++ break; ++ } ++ ++ switch (wValue) { ++ case UHF_PORT_SUSPEND: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (fh_otg_hcd_otg_port(fh_otg_hcd) != wIndex) { ++ goto error; ++ } ++ if (core_if->power_down == 2) { ++ int timeout = 300; ++ fh_irqflags_t flags; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++#ifdef FH_DEV_SRPCAP ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++#endif ++ FH_PRINTF("Preparing for complete power-off\n"); ++ ++ /* Save registers before hibernation */ ++ fh_otg_save_global_regs(core_if); ++ fh_otg_save_host_regs(core_if); ++ ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtena = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Spin hprt0.b.prtsusp to became 1 */ ++ do { ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ if (hprt0.b.prtsusp) { ++ break; ++ } ++ fh_mdelay(1); ++ } while (--timeout); ++ if (!timeout) { ++ FH_WARN("Suspend wasn't genereted\n"); ++ } ++ fh_udelay(10); ++ ++ /* ++ * We need to disable interrupts to prevent servicing of any IRQ ++ * during going to hibernation ++ */ ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &flags); ++ core_if->lx_state = FH_OTG_L2; ++#ifdef FH_DEV_SRPCAP ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ hprt0.b.prtena = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++#endif ++ gusbcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ fh_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ fh_udelay(10); ++ } ++#ifdef FH_DEV_SRPCAP ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++#endif ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ gpwrdn.d32 = 0; ++#ifdef FH_DEV_SRPCAP ++ gpwrdn.b.srp_det_msk = 1; ++#endif ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Enable Power Down Clamp and all interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ fh_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++#ifdef FH_DEV_SRPCAP ++ if (otg_cap_param == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE) ++ { ++ core_if->pwron_timer_started = 1; ++ FH_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); ++ } ++#endif ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ FH_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock,flags); ++ ++ FH_PRINTF("Host hibernation completed\n"); ++ // Exit from case statement ++ break; ++ ++ } ++ if (fh_otg_hcd_otg_port(fh_otg_hcd) == wIndex && ++ fh_otg_hcd->fops->get_b_hnp_enable(fh_otg_hcd)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.hstsethnpen = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gotgctl, 0, gotgctl.d32); ++ core_if->op_state = A_SUSPEND; ++ } ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ { ++ fh_irqflags_t flags; ++ /* Update lx_state */ ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &flags); ++ core_if->lx_state = FH_OTG_L2; ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, flags); ++ } ++ /* Suspend the Phy Clock */ ++ if (core_if->otg_ver == 0) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ fh_udelay(10); ++ } ++ ++ /* For HNP the bus must be suspended for at least 200ms. */ ++ if (fh_otg_hcd->fops->get_b_hnp_enable(fh_otg_hcd)) { ++ if (core_if->otg_ver) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ fh_mdelay(200); ++ } ++ ++ /** @todo - check how sw can wait for 1 sec to check asesvld??? */ ++#if 0 //vahrama !!!!!!!!!!!!!!!!!! ++ if (core_if->adp_enable) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn; ++ ++ while (gotgctl.b.asesvld == 1) { ++ gotgctl.d32 = ++ FH_READ_REG32(&core_if-> ++ core_global_regs-> ++ gotgctl); ++ fh_mdelay(100); ++ } ++ ++ /* Enable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ fh_otg_adp_probe_start(core_if); ++ } ++#endif ++ break; ++ case UHF_PORT_POWER: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_RESET: ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ /* If we are going to exit from Hibernated ++ * state via USB RESET. ++ */ ++ fh_otg_host_hibernation_restore(core_if, 0, 1); ++ } else { ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ ++ FH_DEBUGPL(DBG_HCD, ++ "FH OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.enbl_sleep_gating = 1; ++ pcgcctl.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ FH_WRITE_REG32(core_if->pcgcctl, 0); ++ } ++#ifdef CONFIG_USB_FH_OTG_LPM ++ { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ FH_WRITE_REG32 ++ (&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ fh_mdelay(1); ++ } ++ } ++#endif ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ /* Clear suspend bit if resetting from suspended state. */ ++ hprt0.b.prtsusp = 0; ++ /* When B-Host the Port reset bit is set in ++ * the Start HCD Callback function, so that ++ * the reset is started within 1ms of the HNP ++ * success interrupt. */ ++ if (!fh_otg_hcd_is_b_host(fh_otg_hcd)) { ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtrst = 1; ++ FH_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); ++ FH_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ fh_mdelay(60); ++ hprt0.b.prtrst = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ core_if->lx_state = FH_OTG_L0; /* Now back to the on state */ ++ } ++ break; ++#ifdef FH_HS_ELECT_TST ++ case UHF_PORT_TEST: ++ { ++ uint32_t t; ++ gintmsk_data_t gintmsk; ++ ++ t = (wIndex >> 8); /* MSB wIndex USB */ ++ FH_DEBUGPL(DBG_HCD, ++ "FH OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", ++ t); ++ FH_WARN("USB_PORT_FEAT_TEST %d\n", t); ++ if (t < 6) { ++ hprt0.d32 = fh_otg_read_hprt0(core_if); ++ hprt0.b.prttstctl = t; ++ FH_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } else { ++ /* Setup global vars with reg addresses (quick and ++ * dirty hack, should be cleaned up) ++ */ ++ global_regs = core_if->core_global_regs; ++ hc_global_regs = ++ core_if->host_if->host_global_regs; ++ hc_regs = ++ (fh_otg_hc_regs_t *) ((char *) ++ global_regs + ++ 0x500); ++ data_fifo = ++ (uint32_t *) ((char *)global_regs + ++ 0x1000); ++ ++ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ FH_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ FH_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ fh_mdelay(15000); ++ ++ /* Drive suspend on the root port */ ++ hprt0.d32 = ++ fh_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtres = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* 15 second delay per the test spec */ ++ fh_mdelay(15000); ++ ++ /* Drive resume on the root port */ ++ hprt0.d32 = ++ fh_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 0; ++ hprt0.b.prtres = 1; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ fh_mdelay(100); ++ ++ /* Clear the resume bit */ ++ hprt0.b.prtres = 0; ++ FH_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Restore interrupts */ ++ FH_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ FH_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ FH_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ fh_mdelay(15000); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ fh_mdelay(15000); ++ ++ /* Restore interrupts */ ++ FH_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ FH_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ FH_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ fh_mdelay(15000); ++ ++ /* Send the In and Ack packets */ ++ do_in_ack(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ fh_mdelay(15000); ++ ++ /* Restore interrupts */ ++ FH_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } ++ } ++ break; ++ } ++#endif /* FH_HS_ELECT_TST */ ++ ++ case UHF_PORT_INDICATOR: ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); ++ /* Not supported */ ++ break; ++ default: ++ retval = -FH_E_INVALID; ++ FH_ERROR("FH OTG HCD - " ++ "SetPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ break; ++ } ++ break; ++#ifdef CONFIG_USB_FH_OTG_LPM ++ case UCR_SET_AND_TEST_PORT_FEATURE: ++ if (wValue != UHF_PORT_L1) { ++ goto error; ++ } ++ { ++ int portnum, hird, devaddr, remwake; ++ glpmcfg_data_t lpmcfg; ++ uint32_t time_usecs; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ ++ if (!fh_otg_get_param_lpm_enable(core_if)) { ++ goto error; ++ } ++ if (wValue != UHF_PORT_L1 || wLength != 1) { ++ goto error; ++ } ++ /* Check if the port currently is in SLEEP state */ ++ lpmcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ FH_INFO("Port is already in sleep mode\n"); ++ buf[0] = 0; /* Return success */ ++ break; ++ } ++ ++ portnum = wIndex & 0xf; ++ hird = (wIndex >> 4) & 0xf; ++ devaddr = (wIndex >> 8) & 0x7f; ++ remwake = (wIndex >> 15); ++ ++ if (portnum != 1) { ++ retval = -FH_E_INVALID; ++ FH_WARN ++ ("Wrong port number(%d) in SetandTestPortFeature request\n", ++ portnum); ++ break; ++ } ++ ++ FH_PRINTF ++ ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n", ++ portnum, hird, devaddr, remwake); ++ /* Disable LPM interrupt */ ++ gintmsk.d32 = 0; ++ gintmsk.b.lpmtranrcvd = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ gintmsk.d32, 0); ++ ++ if (fh_otg_hcd_send_lpm ++ (fh_otg_hcd, devaddr, hird, remwake)) { ++ retval = -FH_E_INVALID; ++ break; ++ } ++ ++ time_usecs = 10 * (lpmcfg.b.retry_count + 1); ++ /* We will consider timeout if time_usecs microseconds pass, ++ * and we don't receive LPM transaction status. ++ * After receiving non-error responce(ACK/NYET/STALL) from device, ++ * core will set lpmtranrcvd bit. ++ */ ++ do { ++ gintsts.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.lpmtranrcvd) { ++ break; ++ } ++ fh_udelay(1); ++ } while (--time_usecs); ++ /* lpm_int bit will be cleared in LPM interrupt handler */ ++ ++ /* Now fill status ++ * 0x00 - Success ++ * 0x10 - NYET ++ * 0x11 - Timeout ++ */ ++ if (!gintsts.b.lpmtranrcvd) { ++ buf[0] = 0x3; /* Completion code is Timeout */ ++ fh_otg_hcd_free_hc_from_lpm(fh_otg_hcd); ++ } else { ++ lpmcfg.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.lpm_resp == 0x3) { ++ /* ACK responce from the device */ ++ buf[0] = 0x00; /* Success */ ++ } else if (lpmcfg.b.lpm_resp == 0x2) { ++ /* NYET responce from the device */ ++ buf[0] = 0x2; ++ } else { ++ /* Otherwise responce with Timeout */ ++ buf[0] = 0x3; ++ } ++ } ++ FH_PRINTF("Device responce to LPM trans is %x\n", ++ lpmcfg.b.lpm_resp); ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, ++ gintmsk.d32); ++ ++ break; ++ } ++#endif /* CONFIG_USB_FH_OTG_LPM */ ++ default: ++error: ++ retval = -FH_E_INVALID; ++ FH_WARN("FH OTG HCD - " ++ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", ++ typeReq, wIndex, wValue); ++ break; ++ } ++ ++ return retval; ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++/** Returns index of host channel to perform LPM transaction. */ ++int fh_otg_hcd_get_hc_for_lpm_tran(fh_otg_hcd_t * hcd, uint8_t devaddr) ++{ ++ fh_otg_core_if_t *core_if = hcd->core_if; ++ fh_hc_t *hc; ++ hcchar_data_t hcchar; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (FH_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ FH_PRINTF("No free channel to select for LPM transaction\n"); ++ return -1; ++ } ++ ++ hc = FH_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ ++ /* Mask host channel interrupts. */ ++ gintmsk.b.hcintr = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ /* Fill fields that core needs for LPM transaction */ ++ hcchar.b.devaddr = devaddr; ++ hcchar.b.epnum = 0; ++ hcchar.b.eptype = FH_OTG_EP_TYPE_CONTROL; ++ hcchar.b.mps = 64; ++ hcchar.b.lspddev = (hc->speed == FH_OTG_EP_SPEED_LOW); ++ hcchar.b.epdir = 0; /* OUT */ ++ FH_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, ++ hcchar.d32); ++ ++ /* Remove the host channel from the free list. */ ++ FH_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ FH_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr); ++ ++ return hc->hc_num; ++} ++ ++/** Release hc after performing LPM transaction */ ++void fh_otg_hcd_free_hc_from_lpm(fh_otg_hcd_t * hcd) ++{ ++ fh_hc_t *hc; ++ glpmcfg_data_t lpmcfg; ++ uint8_t hc_num; ++ ++ lpmcfg.d32 = FH_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ hc_num = lpmcfg.b.lpm_chan_index; ++ ++ hc = hcd->hc_ptr_array[hc_num]; ++ ++ FH_PRINTF("Freeing channel %d after LPM\n", hc_num); ++ /* Return host channel to free list */ ++ FH_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++} ++ ++int fh_otg_hcd_send_lpm(fh_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, ++ uint8_t bRemoteWake) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ int channel; ++ ++ channel = fh_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr); ++ if (channel < 0) { ++ return channel; ++ } ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ FH_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Read LPM config register */ ++ lpmcfg.d32 = FH_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ ++ /* Program LPM transaction fields */ ++ lpmcfg.b.rem_wkup_en = bRemoteWake; ++ lpmcfg.b.hird = hird; ++ ++ if(fh_otg_get_param_besl_enable(hcd->core_if)) { ++ lpmcfg.b.hird_thres = 0x16; ++ lpmcfg.b.en_besl = 1; ++ } else { ++ lpmcfg.b.hird_thres = 0x1c; ++ } ++ ++ lpmcfg.b.lpm_chan_index = channel; ++ lpmcfg.b.en_utmi_sleep = 1; ++ /* Program LPM config register */ ++ FH_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ /* Send LPM transaction */ ++ lpmcfg.b.send_lpm = 1; ++ FH_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_USB_FH_OTG_LPM */ ++ ++int fh_otg_hcd_is_status_changed(fh_otg_hcd_t * hcd, int port) ++{ ++ int retval; ++ ++ if (port != 1) { ++ return -FH_E_INVALID; ++ } ++ ++ retval = (hcd->flags.b.port_connect_status_change || ++ hcd->flags.b.port_reset_change || ++ hcd->flags.b.port_enable_change || ++ hcd->flags.b.port_suspend_change || ++ hcd->flags.b.port_over_current_change); ++#ifdef DEBUG ++ if (retval) { ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD HUB STATUS DATA:" ++ " Root port status changed\n"); ++ FH_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", ++ hcd->flags.b.port_connect_status_change); ++ FH_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", ++ hcd->flags.b.port_reset_change); ++ FH_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", ++ hcd->flags.b.port_enable_change); ++ FH_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", ++ hcd->flags.b.port_suspend_change); ++ FH_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", ++ hcd->flags.b.port_over_current_change); ++ } ++#endif ++ return retval; ++} ++ ++int fh_otg_hcd_get_frame_number(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ FH_READ_REG32(&fh_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); ++ ++#ifdef DEBUG_SOF ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD GET FRAME NUMBER %d\n", ++ hfnum.b.frnum); ++#endif ++ return hfnum.b.frnum; ++} ++ ++int fh_otg_hcd_start(fh_otg_hcd_t * hcd, ++ struct fh_otg_hcd_function_ops *fops) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ ++ hcd->fops = fops; ++ if (!fh_otg_is_device_mode(hcd->core_if) && ++ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { ++ fh_otg_hcd_reinit(hcd); ++ } else { ++ if (hcd->core_if->adp_enable) { ++ /* Clear any interrupt pending in the HPRT, sometimes ++ * Port Connect Detected is not being cleared*/ ++ hprt0.d32 = FH_READ_REG32(hcd->core_if->host_if->hprt0); ++ FH_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ retval = -FH_E_NO_DEVICE; ++ } ++ ++ return retval; ++} ++ ++void *fh_otg_hcd_get_priv_data(fh_otg_hcd_t * hcd) ++{ ++ return hcd->priv; ++} ++ ++void fh_otg_hcd_set_priv_data(fh_otg_hcd_t * hcd, void *priv_data) ++{ ++ hcd->priv = priv_data; ++} ++ ++uint32_t fh_otg_hcd_otg_port(fh_otg_hcd_t * hcd) ++{ ++ return hcd->otg_port; ++} ++ ++uint32_t fh_otg_hcd_is_b_host(fh_otg_hcd_t * hcd) ++{ ++ uint32_t is_b_host; ++ if (hcd->core_if->op_state == B_HOST) { ++ is_b_host = 1; ++ } else { ++ is_b_host = 0; ++ } ++ ++ return is_b_host; ++} ++ ++fh_otg_hcd_urb_t *fh_otg_hcd_urb_alloc(fh_otg_hcd_t * hcd, ++ int iso_desc_count, int atomic_alloc) ++{ ++ fh_otg_hcd_urb_t *fh_otg_urb; ++ uint32_t size; ++ ++ size = ++ sizeof(*fh_otg_urb) + ++ iso_desc_count * sizeof(struct fh_otg_hcd_iso_packet_desc); ++ if (atomic_alloc) ++ fh_otg_urb = FH_ALLOC_ATOMIC(size); ++ else ++ fh_otg_urb = FH_ALLOC(size); ++ ++ fh_otg_urb->packet_count = iso_desc_count; ++ ++ return fh_otg_urb; ++} ++ ++void fh_otg_hcd_urb_set_pipeinfo(fh_otg_hcd_urb_t * fh_otg_urb, ++ uint8_t dev_addr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, uint16_t mps) ++{ ++ fh_otg_hcd_fill_pipe(&fh_otg_urb->pipe_info, dev_addr, ep_num, ++ ep_type, ep_dir, mps); ++#if 0 ++ FH_PRINTF ++ ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n", ++ dev_addr, ep_num, ep_dir, ep_type, mps); ++#endif ++} ++ ++void fh_otg_hcd_urb_set_params(fh_otg_hcd_urb_t * fh_otg_urb, ++ void *urb_handle, void *buf, fh_dma_t dma, ++ uint32_t buflen, void *setup_packet, ++ fh_dma_t setup_dma, uint32_t flags, ++ uint16_t interval) ++{ ++ fh_otg_urb->priv = urb_handle; ++ fh_otg_urb->buf = buf; ++ fh_otg_urb->dma = dma; ++ fh_otg_urb->length = buflen; ++ fh_otg_urb->setup_packet = setup_packet; ++ fh_otg_urb->setup_dma = setup_dma; ++ fh_otg_urb->flags = flags; ++ fh_otg_urb->interval = interval; ++ fh_otg_urb->status = -FH_E_IN_PROGRESS; ++} ++ ++uint32_t fh_otg_hcd_urb_get_status(fh_otg_hcd_urb_t * fh_otg_urb) ++{ ++ return fh_otg_urb->status; ++} ++ ++uint32_t fh_otg_hcd_urb_get_actual_length(fh_otg_hcd_urb_t * fh_otg_urb) ++{ ++ return fh_otg_urb->actual_length; ++} ++ ++uint32_t fh_otg_hcd_urb_get_error_count(fh_otg_hcd_urb_t * fh_otg_urb) ++{ ++ return fh_otg_urb->error_count; ++} ++ ++void fh_otg_hcd_urb_set_iso_desc_params(fh_otg_hcd_urb_t * fh_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length) ++{ ++ fh_otg_urb->iso_descs[desc_num].offset = offset; ++ fh_otg_urb->iso_descs[desc_num].length = length; ++} ++ ++uint32_t fh_otg_hcd_urb_get_iso_desc_status(fh_otg_hcd_urb_t * fh_otg_urb, ++ int desc_num) ++{ ++ return fh_otg_urb->iso_descs[desc_num].status; ++} ++ ++uint32_t fh_otg_hcd_urb_get_iso_desc_actual_length(fh_otg_hcd_urb_t * ++ fh_otg_urb, int desc_num) ++{ ++ return fh_otg_urb->iso_descs[desc_num].actual_length; ++} ++ ++int fh_otg_hcd_is_bandwidth_allocated(fh_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int allocated = 0; ++ fh_otg_qh_t *qh = (fh_otg_qh_t *) ep_handle; ++ ++ if (qh) { ++ if (!FH_LIST_EMPTY(&qh->qh_list_entry)) { ++ allocated = 1; ++ } ++ } ++ return allocated; ++} ++ ++int fh_otg_hcd_is_bandwidth_freed(fh_otg_hcd_t * hcd, void *ep_handle) ++{ ++ fh_otg_qh_t *qh = (fh_otg_qh_t *) ep_handle; ++ int freed = 0; ++ FH_ASSERT(qh, "qh is not allocated\n"); ++ ++ if (FH_LIST_EMPTY(&qh->qh_list_entry)) { ++ freed = 1; ++ } ++ ++ return freed; ++} ++ ++uint8_t fh_otg_hcd_get_ep_bandwidth(fh_otg_hcd_t * hcd, void *ep_handle) ++{ ++ fh_otg_qh_t *qh = (fh_otg_qh_t *) ep_handle; ++ FH_ASSERT(qh, "qh is not allocated\n"); ++ return qh->usecs; ++} ++ ++void fh_otg_hcd_dump_state(fh_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int num_channels; ++ int i; ++ gnptxsts_data_t np_tx_status; ++ hptxsts_data_t p_tx_status; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ FH_PRINTF("\n"); ++ FH_PRINTF ++ ("************************************************************\n"); ++ FH_PRINTF("HCD State:\n"); ++ FH_PRINTF(" Num channels: %d\n", num_channels); ++ for (i = 0; i < num_channels; i++) { ++ fh_hc_t *hc = hcd->hc_ptr_array[i]; ++ FH_PRINTF(" Channel %d:\n", i); ++ FH_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ FH_PRINTF(" speed: %d\n", hc->speed); ++ FH_PRINTF(" ep_type: %d\n", hc->ep_type); ++ FH_PRINTF(" max_packet: %d\n", hc->max_packet); ++ FH_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ FH_PRINTF(" multi_count: %d\n", hc->multi_count); ++ FH_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ FH_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ FH_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ FH_PRINTF(" xfer_count: %d\n", hc->xfer_count); ++ FH_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue); ++ FH_PRINTF(" halt_pending: %d\n", hc->halt_pending); ++ FH_PRINTF(" halt_status: %d\n", hc->halt_status); ++ FH_PRINTF(" do_split: %d\n", hc->do_split); ++ FH_PRINTF(" complete_split: %d\n", hc->complete_split); ++ FH_PRINTF(" hub_addr: %d\n", hc->hub_addr); ++ FH_PRINTF(" port_addr: %d\n", hc->port_addr); ++ FH_PRINTF(" xact_pos: %d\n", hc->xact_pos); ++ FH_PRINTF(" requests: %d\n", hc->requests); ++ FH_PRINTF(" qh: %p\n", hc->qh); ++ if (hc->xfer_started) { ++ hfnum_data_t hfnum; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hfnum.d32 = ++ FH_READ_REG32(&hcd->core_if-> ++ host_if->host_global_regs->hfnum); ++ hcchar.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcchar); ++ hctsiz.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hctsiz); ++ hcint.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcint); ++ hcintmsk.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcintmsk); ++ FH_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); ++ FH_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); ++ FH_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); ++ FH_PRINTF(" hcint: 0x%08x\n", hcint.d32); ++ FH_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32); ++ } ++ if (hc->xfer_started && hc->qh) { ++ fh_otg_qtd_t *qtd; ++ fh_otg_hcd_urb_t *urb; ++ ++ FH_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { ++ if (!qtd->in_process) ++ break; ++ ++ urb = qtd->urb; ++ FH_PRINTF(" URB Info:\n"); ++ FH_PRINTF(" qtd: %p, urb: %p\n", qtd, urb); ++ if (urb) { ++ FH_PRINTF(" Dev: %d, EP: %d %s\n", ++ fh_otg_hcd_get_dev_addr(&urb-> ++ pipe_info), ++ fh_otg_hcd_get_ep_num(&urb-> ++ pipe_info), ++ fh_otg_hcd_is_pipe_in(&urb-> ++ pipe_info) ? ++ "IN" : "OUT"); ++ FH_PRINTF(" Max packet size: %d\n", ++ fh_otg_hcd_get_mps(&urb-> ++ pipe_info)); ++ FH_PRINTF(" transfer_buffer: %p\n", ++ urb->buf); ++ FH_PRINTF(" transfer_dma: %p\n", ++ (void *)urb->dma); ++ FH_PRINTF(" transfer_buffer_length: %d\n", ++ urb->length); ++ FH_PRINTF(" actual_length: %d\n", ++ urb->actual_length); ++ } ++ } ++ } ++ } ++ FH_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); ++ FH_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); ++ FH_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); ++ np_tx_status.d32 = ++ FH_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); ++ FH_PRINTF(" NP Tx Req Queue Space Avail: %d\n", ++ np_tx_status.b.nptxqspcavail); ++ FH_PRINTF(" NP Tx FIFO Space Avail: %d\n", ++ np_tx_status.b.nptxfspcavail); ++ p_tx_status.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); ++ FH_PRINTF(" P Tx Req Queue Space Avail: %d\n", ++ p_tx_status.b.ptxqspcavail); ++ FH_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); ++ fh_otg_hcd_dump_frrem(hcd); ++ fh_otg_dump_global_registers(hcd->core_if); ++ fh_otg_dump_host_registers(hcd->core_if); ++ FH_PRINTF ++ ("************************************************************\n"); ++ FH_PRINTF("\n"); ++#endif ++} ++ ++#ifdef DEBUG ++void fh_print_setup_data(uint8_t * setup) ++{ ++ int i; ++ if (CHK_DEBUG_LEVEL(DBG_HCD)) { ++ FH_PRINTF("Setup Data = MSB "); ++ for (i = 7; i >= 0; i--) ++ FH_PRINTF("%02x ", setup[i]); ++ FH_PRINTF("\n"); ++ FH_PRINTF(" bmRequestType Tranfer = %s\n", ++ (setup[0] & 0x80) ? "Device-to-Host" : ++ "Host-to-Device"); ++ FH_PRINTF(" bmRequestType Type = "); ++ switch ((setup[0] & 0x60) >> 5) { ++ case 0: ++ FH_PRINTF("Standard\n"); ++ break; ++ case 1: ++ FH_PRINTF("Class\n"); ++ break; ++ case 2: ++ FH_PRINTF("Vendor\n"); ++ break; ++ case 3: ++ FH_PRINTF("Reserved\n"); ++ break; ++ } ++ FH_PRINTF(" bmRequestType Recipient = "); ++ switch (setup[0] & 0x1f) { ++ case 0: ++ FH_PRINTF("Device\n"); ++ break; ++ case 1: ++ FH_PRINTF("Interface\n"); ++ break; ++ case 2: ++ FH_PRINTF("Endpoint\n"); ++ break; ++ case 3: ++ FH_PRINTF("Other\n"); ++ break; ++ default: ++ FH_PRINTF("Reserved\n"); ++ break; ++ } ++ FH_PRINTF(" bRequest = 0x%0x\n", setup[1]); ++ FH_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2])); ++ FH_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4])); ++ FH_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6])); ++ } ++} ++#endif ++ ++void fh_otg_hcd_dump_frrem(fh_otg_hcd_t * hcd) ++{ ++#if 0 ++ FH_PRINTF("Frame remaining at SOF:\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->frrem_samples, hcd->frrem_accum, ++ (hcd->frrem_samples > 0) ? ++ hcd->frrem_accum / hcd->frrem_samples : 0); ++ ++ FH_PRINTF("\n"); ++ FH_PRINTF("Frame remaining at start_transfer (uframe 7):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_7_samples, ++ hcd->core_if->hfnum_7_frrem_accum, ++ (hcd->core_if->hfnum_7_samples > ++ 0) ? hcd->core_if->hfnum_7_frrem_accum / ++ hcd->core_if->hfnum_7_samples : 0); ++ FH_PRINTF("Frame remaining at start_transfer (uframe 0):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_0_samples, ++ hcd->core_if->hfnum_0_frrem_accum, ++ (hcd->core_if->hfnum_0_samples > ++ 0) ? hcd->core_if->hfnum_0_frrem_accum / ++ hcd->core_if->hfnum_0_samples : 0); ++ FH_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_other_samples, ++ hcd->core_if->hfnum_other_frrem_accum, ++ (hcd->core_if->hfnum_other_samples > ++ 0) ? hcd->core_if->hfnum_other_frrem_accum / ++ hcd->core_if->hfnum_other_samples : 0); ++ ++ FH_PRINTF("\n"); ++ FH_PRINTF("Frame remaining at sample point A (uframe 7):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, ++ (hcd->hfnum_7_samples_a > 0) ? ++ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); ++ FH_PRINTF("Frame remaining at sample point A (uframe 0):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, ++ (hcd->hfnum_0_samples_a > 0) ? ++ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); ++ FH_PRINTF("Frame remaining at sample point A (uframe 1-6):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, ++ (hcd->hfnum_other_samples_a > 0) ? ++ hcd->hfnum_other_frrem_accum_a / ++ hcd->hfnum_other_samples_a : 0); ++ ++ FH_PRINTF("\n"); ++ FH_PRINTF("Frame remaining at sample point B (uframe 7):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, ++ (hcd->hfnum_7_samples_b > 0) ? ++ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); ++ FH_PRINTF("Frame remaining at sample point B (uframe 0):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, ++ (hcd->hfnum_0_samples_b > 0) ? ++ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); ++ FH_PRINTF("Frame remaining at sample point B (uframe 1-6):\n"); ++ FH_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, ++ (hcd->hfnum_other_samples_b > 0) ? ++ hcd->hfnum_other_frrem_accum_b / ++ hcd->hfnum_other_samples_b : 0); ++#endif ++} ++ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.h +new file mode 100644 +index 00000000..bfc3944b +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd.h +@@ -0,0 +1,803 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd.h $ ++ * $Revision: #58 $ ++ * $Date: 2011/09/15 $ ++ * $Change: 1846647 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++#ifndef __FH_HCD_H__ ++#define __FH_HCD_H__ ++ ++#include "fh_otg_os_dep.h" ++#include "../fh_common_port/usb.h" ++#include "../fh_common_port/fh_list.h" ++#include "fh_otg_hcd_if.h" ++#include "fh_otg_core_if.h" ++#include "fh_otg_cil.h" ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Host Contoller Driver (HCD). ++ * ++ * The Host Controller Driver (HCD) is responsible for translating requests ++ * from the USB Driver into the appropriate actions on the FH_otg controller. ++ * It isolates the USBD from the specifics of the controller by providing an ++ * API to the USBD. ++ */ ++ ++struct fh_otg_hcd_pipe_info { ++ uint8_t dev_addr; ++ uint8_t ep_num; ++ uint8_t pipe_type; ++ uint8_t pipe_dir; ++ uint16_t mps; ++}; ++ ++struct fh_otg_hcd_iso_packet_desc { ++ uint32_t offset; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct fh_otg_qtd; ++ ++struct fh_otg_hcd_urb { ++ void *priv; ++ struct fh_otg_qtd *qtd; ++ void *buf; ++ fh_dma_t dma; ++ void *setup_packet; ++ fh_dma_t setup_dma; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++ uint32_t error_count; ++ uint32_t packet_count; ++ uint32_t flags; ++ uint16_t interval; ++ struct fh_otg_hcd_pipe_info pipe_info; ++ struct fh_otg_hcd_iso_packet_desc iso_descs[0]; ++}; ++ ++static inline uint8_t fh_otg_hcd_get_ep_num(struct fh_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->ep_num; ++} ++ ++static inline uint8_t fh_otg_hcd_get_pipe_type(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->pipe_type; ++} ++ ++static inline uint16_t fh_otg_hcd_get_mps(struct fh_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->mps; ++} ++ ++static inline uint8_t fh_otg_hcd_get_dev_addr(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->dev_addr; ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_isoc(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_ISOCHRONOUS); ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_int(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_INTERRUPT); ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_bulk(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_BULK); ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_control(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_CONTROL); ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_in(struct fh_otg_hcd_pipe_info *pipe) ++{ ++ return (pipe->pipe_dir == UE_DIR_IN); ++} ++ ++static inline uint8_t fh_otg_hcd_is_pipe_out(struct fh_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (!fh_otg_hcd_is_pipe_in(pipe)); ++} ++ ++static inline void fh_otg_hcd_fill_pipe(struct fh_otg_hcd_pipe_info *pipe, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t pipe_type, uint8_t pipe_dir, ++ uint16_t mps) ++{ ++ pipe->dev_addr = devaddr; ++ pipe->ep_num = ep_num; ++ pipe->pipe_type = pipe_type; ++ pipe->pipe_dir = pipe_dir; ++ pipe->mps = mps; ++} ++ ++/** ++ * Phases for control transfers. ++ */ ++typedef enum fh_otg_control_phase { ++ FH_OTG_CONTROL_SETUP, ++ FH_OTG_CONTROL_DATA, ++ FH_OTG_CONTROL_STATUS ++} fh_otg_control_phase_e; ++ ++/** Transaction types. */ ++typedef enum fh_otg_transaction_type { ++ FH_OTG_TRANSACTION_NONE, ++ FH_OTG_TRANSACTION_PERIODIC, ++ FH_OTG_TRANSACTION_NON_PERIODIC, ++ FH_OTG_TRANSACTION_ALL ++} fh_otg_transaction_type_e; ++ ++struct fh_otg_qh; ++ ++/** ++ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, ++ * interrupt, or isochronous transfer. A single QTD is created for each URB ++ * (of one of these types) submitted to the HCD. The transfer associated with ++ * a QTD may require one or multiple transactions. ++ * ++ * A QTD is linked to a Queue Head, which is entered in either the ++ * non-periodic or periodic schedule for execution. When a QTD is chosen for ++ * execution, some or all of its transactions may be executed. After ++ * execution, the state of the QTD is updated. The QTD may be retired if all ++ * its transactions are complete or if an error occurred. Otherwise, it ++ * remains in the schedule so more transactions can be executed later. ++ */ ++typedef struct fh_otg_qtd { ++ /** ++ * Determines the PID of the next data packet for the data phase of ++ * control transfers. Ignored for other transfer types.<br> ++ * One of the following values: ++ * - FH_OTG_HC_PID_DATA0 ++ * - FH_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Current phase for control transfers (Setup, Data, or Status). */ ++ fh_otg_control_phase_e control_phase; ++ ++ /** Keep track of the current split type ++ * for FS/LS endpoints on a HS Hub */ ++ uint8_t complete_split; ++ ++ /** How many bytes transferred during SSPLIT OUT */ ++ uint32_t ssplit_out_xfer_count; ++ ++ /** ++ * Holds the number of bus errors that have occurred for a transaction ++ * within this transfer. ++ */ ++ uint8_t error_count; ++ ++ /** ++ * Index of the next frame descriptor for an isochronous transfer. A ++ * frame descriptor describes the buffer position and length of the ++ * data to be transferred in the next scheduled (micro)frame of an ++ * isochronous transfer. It also holds status for that transaction. ++ * The frame index starts at 0. ++ */ ++ uint16_t isoc_frame_index; ++ ++ /** Position of the ISOC split on full/low speed */ ++ uint8_t isoc_split_pos; ++ ++ /** Position of the ISOC split in the buffer for the current frame */ ++ uint16_t isoc_split_offset; ++ ++ /** URB for this transfer */ ++ struct fh_otg_hcd_urb *urb; ++ ++ struct fh_otg_qh *qh; ++ ++ /** This list of QTDs */ ++ FH_CIRCLEQ_ENTRY(fh_otg_qtd) qtd_list_entry; ++ ++ /** Indicates if this QTD is currently processed by HW. */ ++ uint8_t in_process; ++ ++ /** Number of DMA descriptors for this QTD */ ++ uint8_t n_desc; ++ ++ /** ++ * Last activated frame(packet) index. ++ * Used in Descriptor DMA mode only. ++ */ ++ uint16_t isoc_frame_index_last; ++ ++} fh_otg_qtd_t; ++ ++FH_CIRCLEQ_HEAD(fh_otg_qtd_list, fh_otg_qtd); ++ ++/** ++ * A Queue Head (QH) holds the static characteristics of an endpoint and ++ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may ++ * be entered in either the non-periodic or periodic schedule. ++ */ ++typedef struct fh_otg_qh { ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - UE_CONTROL ++ * - UE_BULK ++ * - UE_INTERRUPT ++ * - UE_ISOCHRONOUS ++ */ ++ uint8_t ep_type; ++ uint8_t ep_is_in; ++ ++ /** wMaxPacketSize Field of Endpoint Descriptor. */ ++ uint16_t maxp; ++ ++ /** ++ * Device speed. ++ * One of the following values: ++ * - FH_OTG_EP_SPEED_LOW ++ * - FH_OTG_EP_SPEED_FULL ++ * - FH_OTG_EP_SPEED_HIGH ++ */ ++ uint8_t dev_speed; ++ ++ /** ++ * Determines the PID of the next data packet for non-control ++ * transfers. Ignored for control transfers.<br> ++ * One of the following values: ++ * - FH_OTG_HC_PID_DATA0 ++ * - FH_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Ping state if 1. */ ++ uint8_t ping_state; ++ ++ /** ++ * List of QTDs for this QH. ++ */ ++ struct fh_otg_qtd_list qtd_list; ++ ++ /** Host channel currently processing transfers for this QH. */ ++ struct fh_hc *channel; ++ ++ /** Full/low speed endpoint on high-speed hub requires split. */ ++ uint8_t do_split; ++ ++ /** @name Periodic schedule information */ ++ /** @{ */ ++ ++ /** Bandwidth in microseconds per (micro)frame. */ ++ uint16_t usecs; ++ ++ /** Interval between transfers in (micro)frames. */ ++ uint16_t interval; ++ ++ /** ++ * (micro)frame to initialize a periodic transfer. The transfer ++ * executes in the following (micro)frame. ++ */ ++ uint16_t sched_frame; ++ ++ /** (micro)frame at which last start split was initialized. */ ++ uint16_t start_split_frame; ++ ++ /** @} */ ++ ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ */ ++ uint8_t *dw_align_buf; ++ fh_dma_t dw_align_buf_dma; ++ ++ /** Entry for QH in either the periodic or non-periodic schedule. */ ++ fh_list_link_t qh_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Descriptor List. */ ++ fh_otg_host_dma_desc_t *desc_list; ++ ++ /** Descriptor List physical address. */ ++ fh_dma_t desc_list_dma; ++ ++ /** ++ * Xfer Bytes array. ++ * Each element corresponds to a descriptor and indicates ++ * original XferSize size value for the descriptor. ++ */ ++ uint32_t *n_bytes; ++ ++ /** Actual number of transfer descriptors in a list. */ ++ uint16_t ntd; ++ ++ /** First activated isochronous transfer descriptor index. */ ++ uint8_t td_first; ++ /** Last activated isochronous transfer descriptor index. */ ++ uint8_t td_last; ++ ++ /** @} */ ++ ++} fh_otg_qh_t; ++ ++FH_CIRCLEQ_HEAD(hc_list, fh_hc); ++ ++/** ++ * This structure holds the state of the HCD, including the non-periodic and ++ * periodic schedules. ++ */ ++struct fh_otg_hcd { ++ /** The FH otg device pointer */ ++ struct fh_otg_device *otg_dev; ++ /** FH OTG Core Interface Layer */ ++ fh_otg_core_if_t *core_if; ++ ++ /** Function HCD driver callbacks */ ++ struct fh_otg_hcd_function_ops *fops; ++ ++ /** Internal FH HCD Flags */ ++ volatile union fh_otg_hcd_internal_flags { ++ uint32_t d32; ++ struct { ++ unsigned port_connect_status_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_reset_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_over_current_change:1; ++ unsigned port_l1_change:1; ++ unsigned reserved:26; ++ } b; ++ } flags; ++ ++ /** ++ * Inactive items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are not ++ * currently assigned to a host channel. ++ */ ++ fh_list_link_t non_periodic_sched_inactive; ++ ++ /** ++ * Active items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are ++ * currently assigned to a host channel. ++ */ ++ fh_list_link_t non_periodic_sched_active; ++ ++ /** ++ * Pointer to the next Queue Head to process in the active ++ * non-periodic schedule. ++ */ ++ fh_list_link_t *non_periodic_qh_ptr; ++ ++ /** ++ * Inactive items in the periodic schedule. This is a list of QHs for ++ * periodic transfers that are _not_ scheduled for the next frame. ++ * Each QH in the list has an interval counter that determines when it ++ * needs to be scheduled for execution. This scheduling mechanism ++ * allows only a simple calculation for periodic bandwidth used (i.e. ++ * must assume that all periodic transfers may need to execute in the ++ * same frame). However, it greatly simplifies scheduling and should ++ * be sufficient for the vast majority of OTG hosts, which need to ++ * connect to a small number of peripherals at one time. ++ * ++ * Items move from this list to periodic_sched_ready when the QH ++ * interval counter is 0 at SOF. ++ */ ++ fh_list_link_t periodic_sched_inactive; ++ ++ /** ++ * List of periodic QHs that are ready for execution in the next ++ * frame, but have not yet been assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_assigned as host ++ * channels become available during the current frame. ++ */ ++ fh_list_link_t periodic_sched_ready; ++ ++ /** ++ * List of periodic QHs to be executed in the next frame that are ++ * assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_queued as the ++ * transactions for the QH are queued to the FH_otg controller. ++ */ ++ fh_list_link_t periodic_sched_assigned; ++ ++ /** ++ * List of periodic QHs that have been queued for execution. ++ * ++ * Items move from this list to either periodic_sched_inactive or ++ * periodic_sched_ready when the channel associated with the transfer ++ * is released. If the interval for the QH is 1, the item moves to ++ * periodic_sched_ready because it must be rescheduled for the next ++ * frame. Otherwise, the item moves to periodic_sched_inactive. ++ */ ++ fh_list_link_t periodic_sched_queued; ++ ++ /** ++ * Total bandwidth claimed so far for periodic transfers. This value ++ * is in microseconds per (micro)frame. The assumption is that all ++ * periodic transfers may occur in the same (micro)frame. ++ */ ++ uint16_t periodic_usecs; ++ ++ /** ++ * Frame number read from the core at SOF. The value ranges from 0 to ++ * FH_HFNUM_MAX_FRNUM. ++ */ ++ uint16_t frame_number; ++ ++ /** ++ * Count of periodic QHs, if using several eps. For SOF enable/disable. ++ */ ++ uint16_t periodic_qh_count; ++ ++ /** ++ * Free host channels in the controller. This is a list of ++ * fh_hc_t items. ++ */ ++ struct hc_list free_hc_list; ++ /** ++ * Number of host channels assigned to periodic transfers. Currently ++ * assuming that there is a dedicated host channel for each periodic ++ * transaction and at least one host channel available for ++ * non-periodic transactions. ++ */ ++ int periodic_channels; ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int non_periodic_channels; ++ ++ /** ++ * Array of pointers to the host channel descriptors. Allows accessing ++ * a host channel descriptor given the host channel number. This is ++ * useful in interrupt handlers. ++ */ ++ struct fh_hc *hc_ptr_array[MAX_EPS_CHANNELS]; ++ ++ /** ++ * Buffer to use for any data received during the status phase of a ++ * control transfer. Normally no data is transferred during the status ++ * phase. This buffer is used as a bit bucket. ++ */ ++ uint8_t *status_buf; ++ ++ /** ++ * DMA address for status_buf. ++ */ ++ dma_addr_t status_buf_dma; ++#define FH_OTG_HCD_STATUS_BUF_SIZE 64 ++ ++ /** ++ * Connection timer. An OTG host must display a message if the device ++ * does not connect. Started when the VBus power is turned on via ++ * sysfs attribute "buspower". ++ */ ++ fh_timer_t *conn_timer; ++ ++ /* Tasket to do a reset */ ++ fh_tasklet_t *reset_tasklet; ++ ++ /* */ ++ fh_spinlock_t *lock; ++ ++ /** ++ * Private data that could be used by OS wrapper. ++ */ ++ void *priv; ++ ++ uint8_t otg_port; ++ ++ /** Frame List */ ++ uint32_t *frame_list; ++ ++ /** Frame List DMA address */ ++ dma_addr_t frame_list_dma; ++ ++#ifdef DEBUG ++ uint32_t frrem_samples; ++ uint64_t frrem_accum; ++ ++ uint32_t hfnum_7_samples_a; ++ uint64_t hfnum_7_frrem_accum_a; ++ uint32_t hfnum_0_samples_a; ++ uint64_t hfnum_0_frrem_accum_a; ++ uint32_t hfnum_other_samples_a; ++ uint64_t hfnum_other_frrem_accum_a; ++ ++ uint32_t hfnum_7_samples_b; ++ uint64_t hfnum_7_frrem_accum_b; ++ uint32_t hfnum_0_samples_b; ++ uint64_t hfnum_0_frrem_accum_b; ++ uint32_t hfnum_other_samples_b; ++ uint64_t hfnum_other_frrem_accum_b; ++#endif ++}; ++ ++/** @name Transaction Execution Functions */ ++/** @{ */ ++extern fh_otg_transaction_type_e fh_otg_hcd_select_transactions(fh_otg_hcd_t ++ * hcd); ++extern void fh_otg_hcd_queue_transactions(fh_otg_hcd_t * hcd, ++ fh_otg_transaction_type_e tr_type); ++ ++/** @} */ ++ ++/** @name Interrupt Handler Functions */ ++/** @{ */ ++extern int32_t fh_otg_hcd_handle_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_sof_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_rx_status_q_level_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_np_tx_fifo_empty_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_perio_tx_fifo_empty_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_incomplete_periodic_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_port_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_conn_id_status_change_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_disconnect_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_hc_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_hc_n_intr(fh_otg_hcd_t * fh_otg_hcd, ++ uint32_t num); ++extern int32_t fh_otg_hcd_handle_session_req_intr(fh_otg_hcd_t * fh_otg_hcd); ++extern int32_t fh_otg_hcd_handle_wakeup_detected_intr(fh_otg_hcd_t * ++ fh_otg_hcd); ++/** @} */ ++ ++/** @name Schedule Queue Functions */ ++/** @{ */ ++ ++/* Implemented in fh_otg_hcd_queue.c */ ++extern fh_otg_qh_t *fh_otg_hcd_qh_create(fh_otg_hcd_t * hcd, ++ fh_otg_hcd_urb_t * urb, int atomic_alloc); ++extern void fh_otg_hcd_qh_free(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++extern int fh_otg_hcd_qh_add(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++extern void fh_otg_hcd_qh_remove(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++extern void fh_otg_hcd_qh_deactivate(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, ++ int sched_csplit); ++ ++/** Remove and free a QH */ ++static inline void fh_otg_hcd_qh_remove_and_free(fh_otg_hcd_t * hcd, ++ fh_otg_qh_t * qh) ++{ ++ fh_irqflags_t flags; ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ fh_otg_hcd_qh_remove(hcd, qh); ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ fh_otg_hcd_qh_free(hcd, qh); ++} ++ ++/** Allocates memory for a QH structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline fh_otg_qh_t *fh_otg_hcd_qh_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (fh_otg_qh_t *) FH_ALLOC_ATOMIC(sizeof(fh_otg_qh_t)); ++ else ++ return (fh_otg_qh_t *) FH_ALLOC(sizeof(fh_otg_qh_t)); ++} ++ ++extern fh_otg_qtd_t *fh_otg_hcd_qtd_create(fh_otg_hcd_urb_t * urb, ++ int atomic_alloc); ++extern void fh_otg_hcd_qtd_init(fh_otg_qtd_t * qtd, fh_otg_hcd_urb_t * urb); ++extern int fh_otg_hcd_qtd_add(fh_otg_qtd_t * qtd, fh_otg_hcd_t * fh_otg_hcd, ++ fh_otg_qh_t ** qh, int atomic_alloc); ++ ++/** Allocates memory for a QTD structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline fh_otg_qtd_t *fh_otg_hcd_qtd_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (fh_otg_qtd_t *) FH_ALLOC_ATOMIC(sizeof(fh_otg_qtd_t)); ++ else ++ return (fh_otg_qtd_t *) FH_ALLOC(sizeof(fh_otg_qtd_t)); ++} ++ ++/** Frees the memory for a QTD structure. QTD should already be removed from ++ * list. ++ * @param qtd QTD to free.*/ ++static inline void fh_otg_hcd_qtd_free(fh_otg_qtd_t * qtd) ++{ ++ FH_FREE(qtd); ++} ++ ++/** Removes a QTD from list. ++ * @param hcd HCD instance. ++ * @param qtd QTD to remove from list. ++ * @param qh QTD belongs to. ++ */ ++static inline void fh_otg_hcd_qtd_remove(fh_otg_hcd_t * hcd, ++ fh_otg_qtd_t * qtd, ++ fh_otg_qh_t * qh) ++{ ++ FH_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++} ++ ++/** Remove and free a QTD ++ * Need to disable IRQ and hold hcd lock while calling this function out of ++ * interrupt servicing chain */ ++static inline void fh_otg_hcd_qtd_remove_and_free(fh_otg_hcd_t * hcd, ++ fh_otg_qtd_t * qtd, ++ fh_otg_qh_t * qh) ++{ ++ fh_otg_hcd_qtd_remove(hcd, qtd, qh); ++ fh_otg_hcd_qtd_free(qtd); ++} ++ ++/** @} */ ++ ++/** @name Descriptor DMA Supporting Functions */ ++/** @{ */ ++ ++extern void fh_otg_hcd_start_xfer_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++extern void fh_otg_hcd_complete_xfer_ddma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_halt_status_e halt_status); ++ ++extern int fh_otg_hcd_qh_init_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++extern void fh_otg_hcd_qh_free_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh); ++ ++/** @} */ ++ ++/** @name Internal Functions */ ++/** @{ */ ++fh_otg_qh_t *fh_urb_to_qh(fh_otg_hcd_urb_t * urb); ++/** @} */ ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++extern int fh_otg_hcd_get_hc_for_lpm_tran(fh_otg_hcd_t * hcd, ++ uint8_t devaddr); ++extern void fh_otg_hcd_free_hc_from_lpm(fh_otg_hcd_t * hcd); ++#endif ++ ++/** Gets the QH that contains the list_head */ ++#define fh_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, fh_otg_qh_t, qh_list_entry) ++ ++/** Gets the QTD that contains the list_head */ ++#define fh_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, fh_otg_qtd_t, qtd_list_entry) ++ ++/** Check if QH is non-periodic */ ++#define fh_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ ++ (_qh_ptr_->ep_type == UE_CONTROL)) ++ ++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ ++#define fh_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) ++ ++/** Packet size for any kind of endpoint descriptor */ ++#define fh_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) ++ ++/** ++ * Returns true if _frame1 is less than or equal to _frame2. The comparison is ++ * done modulo FH_HFNUM_MAX_FRNUM. This accounts for the rollover of the ++ * frame number when the max frame number is reached. ++ */ ++static inline int fh_frame_num_le(uint16_t frame1, uint16_t frame2) ++{ ++ return ((frame2 - frame1) & FH_HFNUM_MAX_FRNUM) <= ++ (FH_HFNUM_MAX_FRNUM >> 1); ++} ++ ++/** ++ * Returns true if _frame1 is greater than _frame2. The comparison is done ++ * modulo FH_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame ++ * number when the max frame number is reached. ++ */ ++static inline int fh_frame_num_gt(uint16_t frame1, uint16_t frame2) ++{ ++ return (frame1 != frame2) && ++ (((frame1 - frame2) & FH_HFNUM_MAX_FRNUM) < ++ (FH_HFNUM_MAX_FRNUM >> 1)); ++} ++ ++/** ++ * Increments _frame by the amount specified by _inc. The addition is done ++ * modulo FH_HFNUM_MAX_FRNUM. Returns the incremented value. ++ */ ++static inline uint16_t fh_frame_num_inc(uint16_t frame, uint16_t inc) ++{ ++ return (frame + inc) & FH_HFNUM_MAX_FRNUM; ++} ++ ++static inline uint16_t fh_full_frame_num(uint16_t frame) ++{ ++ return (frame & FH_HFNUM_MAX_FRNUM) >> 3; ++} ++ ++static inline uint16_t fh_micro_frame_num(uint16_t frame) ++{ ++ return frame & 0x7; ++} ++ ++void fh_otg_hcd_save_data_toggle(fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd); ++ ++#ifdef DEBUG ++/** ++ * Macro to sample the remaining PHY clocks left in the current frame. This ++ * may be used during debugging to determine the average time it takes to ++ * execute sections of code. There are two possible sample points, "a" and ++ * "b", so the _letter argument must be one of these values. ++ * ++ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For ++ * example, "cat /sys/devices/lm0/hcd_frrem". ++ */ ++#define fh_sample_frrem(_hcd, _qh, _letter) \ ++{ \ ++ hfnum_data_t hfnum; \ ++ fh_otg_qtd_t *qtd; \ ++ qtd = list_entry(_qh->qtd_list.next, fh_otg_qtd_t, qtd_list_entry); \ ++ if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ ++ hfnum.d32 = FH_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ ++ switch (hfnum.b.frnum & 0x7) { \ ++ case 7: \ ++ _hcd->hfnum_7_samples_##_letter++; \ ++ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ case 0: \ ++ _hcd->hfnum_0_samples_##_letter++; \ ++ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ default: \ ++ _hcd->hfnum_other_samples_##_letter++; \ ++ _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ } \ ++ } \ ++} ++#else ++#define fh_sample_frrem(_hcd, _qh, _letter) ++#endif ++#endif ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_ddma.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_ddma.c +new file mode 100644 +index 00000000..921c55d5 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_ddma.c +@@ -0,0 +1,1128 @@ ++/*========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd_ddma.c $ ++ * $Revision: #11 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150761 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++ ++/** @file ++ * This file contains Descriptor DMA support implementation for host mode. ++ */ ++ ++#include "fh_otg_hcd.h" ++#include "fh_otg_regs.h" ++ ++static inline uint8_t frame_list_idx(uint16_t frame) ++{ ++ return (frame & (MAX_FRLIST_EN_NUM - 1)); ++} ++ ++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx + inc) & ++ (((speed == ++ FH_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx - inc) & ++ (((speed == ++ FH_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t max_desc_num(fh_otg_qh_t * qh) ++{ ++ return (((qh->ep_type == UE_ISOCHRONOUS) ++ && (qh->dev_speed == FH_OTG_EP_SPEED_HIGH)) ++ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); ++} ++static inline uint16_t frame_incr_val(fh_otg_qh_t * qh) ++{ ++ return ((qh->dev_speed == FH_OTG_EP_SPEED_HIGH) ++ ? ((qh->interval + 8 - 1) / 8) ++ : qh->interval); ++} ++ ++static int desc_list_alloc(fh_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ qh->desc_list = (fh_otg_host_dma_desc_t *) ++ FH_DMA_ALLOC(sizeof(fh_otg_host_dma_desc_t) * max_desc_num(qh), ++ &qh->desc_list_dma); ++ ++ if (!qh->desc_list) { ++ retval = -FH_E_NO_MEMORY; ++ FH_ERROR("%s: DMA descriptor list allocation failed\n", __func__); ++ ++ } ++ ++ fh_memset(qh->desc_list, 0x00, ++ sizeof(fh_otg_host_dma_desc_t) * max_desc_num(qh)); ++ ++ qh->n_bytes = ++ (uint32_t *) FH_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); ++ ++ if (!qh->n_bytes) { ++ retval = -FH_E_NO_MEMORY; ++ FH_ERROR ++ ("%s: Failed to allocate array for descriptors' size actual values\n", ++ __func__); ++ ++ } ++ return retval; ++ ++} ++ ++static void desc_list_free(fh_otg_qh_t * qh) ++{ ++ if (qh->desc_list) { ++ FH_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ qh->desc_list_dma); ++ qh->desc_list = NULL; ++ } ++ ++ if (qh->n_bytes) { ++ FH_FREE(qh->n_bytes); ++ qh->n_bytes = NULL; ++ } ++} ++ ++static int frame_list_alloc(fh_otg_hcd_t * hcd) ++{ ++ int retval = 0; ++ if (hcd->frame_list) ++ return 0; ++ ++ hcd->frame_list = FH_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ &hcd->frame_list_dma); ++ if (!hcd->frame_list) { ++ retval = -FH_E_NO_MEMORY; ++ FH_ERROR("%s: Frame List allocation failed\n", __func__); ++ } ++ ++ fh_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); ++ ++ return retval; ++} ++ ++static void frame_list_free(fh_otg_hcd_t * hcd) ++{ ++ if (!hcd->frame_list) ++ return; ++ ++ FH_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ hcd->frame_list = NULL; ++} ++ ++static void per_sched_enable(fh_otg_hcd_t * hcd, uint16_t fr_list_en) ++{ ++ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = FH_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (hcfg.b.perschedena) { ++ /* already enabled */ ++ return; ++ } ++ ++ FH_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, ++ hcd->frame_list_dma); ++ ++ switch (fr_list_en) { ++ case 64: ++ hcfg.b.frlisten = 3; ++ break; ++ case 32: ++ hcfg.b.frlisten = 2; ++ break; ++ case 16: ++ hcfg.b.frlisten = 1; ++ break; ++ case 8: ++ hcfg.b.frlisten = 0; ++ break; ++ default: ++ break; ++ } ++ ++ hcfg.b.perschedena = 1; ++ ++ FH_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); ++ FH_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ ++} ++ ++static void per_sched_disable(fh_otg_hcd_t * hcd) ++{ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = FH_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (!hcfg.b.perschedena) { ++ /* already disabled */ ++ return; ++ } ++ hcfg.b.perschedena = 0; ++ ++ FH_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); ++ FH_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/* ++ * Activates/Deactivates FrameList entries for the channel ++ * based on endpoint servicing period. ++ */ ++void update_frame_list(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, uint8_t enable) ++{ ++ uint16_t i, j, inc; ++ fh_hc_t *hc = NULL; ++ ++ if (!qh->channel) { ++ FH_ERROR("qh->channel = %p", qh->channel); ++ return; ++ } ++ ++ if (!hcd) { ++ FH_ERROR("------hcd = %p", hcd); ++ return; ++ } ++ ++ if (!hcd->frame_list) { ++ FH_ERROR("-------hcd->frame_list = %p", hcd->frame_list); ++ return; ++ } ++ ++ hc = qh->channel; ++ inc = frame_incr_val(qh); ++ if (qh->ep_type == UE_ISOCHRONOUS) ++ i = frame_list_idx(qh->sched_frame); ++ else ++ i = 0; ++ ++ j = i; ++ do { ++ if (enable) ++ hcd->frame_list[j] |= (1 << hc->hc_num); ++ else ++ hcd->frame_list[j] &= ~(1 << hc->hc_num); ++ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); ++ } ++ while (j != i); ++ if (!enable) ++ return; ++ hc->schinfo = 0; ++ if (qh->channel->speed == FH_OTG_EP_SPEED_HIGH) { ++ j = 1; ++ /* TODO - check this */ ++ inc = (8 + qh->interval - 1) / qh->interval; ++ for (i = 0; i < inc; i++) { ++ hc->schinfo |= j; ++ j = j << qh->interval; ++ } ++ } else { ++ hc->schinfo = 0xff; ++ } ++} ++ ++#if 1 ++void dump_frame_list(fh_otg_hcd_t * hcd) ++{ ++ int i = 0; ++ FH_PRINTF("--FRAME LIST (hex) --\n"); ++ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { ++ FH_PRINTF("%x\t", hcd->frame_list[i]); ++ if (!(i % 8) && i) ++ FH_PRINTF("\n"); ++ } ++ FH_PRINTF("\n----\n"); ++ ++} ++#endif ++ ++static void release_channel_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ fh_hc_t *hc = qh->channel; ++ if (fh_qh_is_non_per(qh)) ++ hcd->non_periodic_channels--; ++ else ++ update_frame_list(hcd, qh, 0); ++ ++ /* ++ * The condition is added to prevent double cleanup try in case of device ++ * disconnect. See channel cleanup in fh_otg_hcd_disconnect_cb(). ++ */ ++ if (hc->qh) { ++ fh_otg_hc_cleanup(hcd->core_if, hc); ++ FH_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc->qh = NULL; ++ } ++ ++ qh->channel = NULL; ++ qh->ntd = 0; ++ ++ if (qh->desc_list) { ++ fh_memset(qh->desc_list, 0x00, ++ sizeof(fh_otg_host_dma_desc_t) * max_desc_num(qh)); ++ } ++} ++ ++/** ++ * Initializes a QH structure's Descriptor DMA related members. ++ * Allocates memory for descriptor list. ++ * On first periodic QH, allocates memory for FrameList ++ * and enables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int fh_otg_hcd_qh_init_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ if (qh->do_split) { ++ FH_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); ++ return -1; ++ } ++ ++ retval = desc_list_alloc(qh); ++ ++ if ((retval == 0) ++ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { ++ if (!hcd->frame_list) { ++ retval = frame_list_alloc(hcd); ++ /* Enable periodic schedule on first periodic QH */ ++ if (retval == 0) ++ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); ++ } ++ } ++ ++ qh->ntd = 0; ++ ++ return retval; ++} ++ ++/** ++ * Frees descriptor list memory associated with the QH. ++ * If QH is periodic and the last, frees FrameList memory ++ * and disables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh The QH to init. ++ */ ++void fh_otg_hcd_qh_free_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ desc_list_free(qh); ++ ++ /* ++ * Channel still assigned due to some reasons. ++ * Seen on Isoc URB dequeue. Channel halted but no subsequent ++ * ChHalted interrupt to release the channel. Afterwards ++ * when it comes here from endpoint disable routine ++ * channel remains assigned. ++ */ ++ if (qh->channel) ++ release_channel_ddma(hcd, qh); ++ ++ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) ++ && !hcd->periodic_channels && hcd->frame_list) { ++ ++ per_sched_disable(hcd); ++ frame_list_free(hcd); ++ } ++} ++ ++static uint8_t frame_to_desc_idx(fh_otg_qh_t * qh, uint16_t frame_idx) ++{ ++ if (qh->dev_speed == FH_OTG_EP_SPEED_HIGH) { ++ /* ++ * Descriptor set(8 descriptors) index ++ * which is 8-aligned. ++ */ ++ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; ++ } else { ++ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); ++ } ++} ++ ++/* ++ * Determine starting frame for Isochronous transfer. ++ * Few frames skipped to prevent race condition with HC. ++ */ ++static uint8_t calc_starting_frame(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, ++ uint8_t * skip_frames) ++{ ++ uint16_t frame = 0; ++ hcd->frame_number = fh_otg_hcd_get_frame_number(hcd); ++ ++ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ ++ ++ /* ++ * skip_frames is used to limit activated descriptors number ++ * to avoid the situation when HC services the last activated ++ * descriptor firstly. ++ * Example for FS: ++ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor ++ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 ++ * will be fetched. If the number of descriptors is max=64 (or greather) the ++ * list will be fully programmed with Active descriptors and it is possible ++ * case(rare) that the latest descriptor(considering rollback) corresponding ++ * to frame 2 will be serviced first. HS case is more probable because, in fact, ++ * up to 11 uframes(16 in the code) may be skipped. ++ */ ++ if (qh->dev_speed == FH_OTG_EP_SPEED_HIGH) { ++ /* ++ * Consider uframe counter also, to start xfer asap. ++ * If half of the frame elapsed skip 2 frames otherwise ++ * just 1 frame. ++ * Starting descriptor index must be 8-aligned, so ++ * if the current frame is near to complete the next one ++ * is skipped as well. ++ */ ++ ++ if (fh_micro_frame_num(hcd->frame_number) >= 5) { ++ *skip_frames = 2 * 8; ++ frame = fh_frame_num_inc(hcd->frame_number, *skip_frames); ++ } else { ++ *skip_frames = 1 * 8; ++ frame = fh_frame_num_inc(hcd->frame_number, *skip_frames); ++ } ++ ++ frame = fh_full_frame_num(frame); ++ } else { ++ /* ++ * Two frames are skipped for FS - the current and the next. ++ * But for descriptor programming, 1 frame(descriptor) is enough, ++ * see example above. ++ */ ++ *skip_frames = 1; ++ frame = fh_frame_num_inc(hcd->frame_number, 2); ++ } ++ ++ return frame; ++} ++ ++/* ++ * Calculate initial descriptor index for isochronous transfer ++ * based on scheduled frame. ++ */ ++static uint8_t recalc_initial_desc_idx(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ uint16_t frame = 0, fr_idx, fr_idx_tmp; ++ uint8_t skip_frames = 0; ++ /* ++ * With current ISOC processing algorithm the channel is being ++ * released when no more QTDs in the list(qh->ntd == 0). ++ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. ++ * ++ * So qh->channel != NULL branch is not used and just not removed from the ++ * source file. It is required for another possible approach which is, ++ * do not disable and release the channel when ISOC session completed, ++ * just move QH to inactive schedule until new QTD arrives. ++ * On new QTD, the QH moved back to 'ready' schedule, ++ * starting frame and therefore starting desc_index are recalculated. ++ * In this case channel is released only on ep_disable. ++ */ ++ ++ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ ++ if (qh->channel) { ++ frame = calc_starting_frame(hcd, qh, &skip_frames); ++ /* ++ * Calculate initial descriptor index based on FrameList current bitmap ++ * and servicing period. ++ */ ++ fr_idx_tmp = frame_list_idx(frame); ++ fr_idx = ++ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - ++ fr_idx_tmp) ++ % frame_incr_val(qh); ++ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; ++ } else { ++ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); ++ fr_idx = frame_list_idx(qh->sched_frame); ++ } ++ ++ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); ++ ++ return skip_frames; ++} ++ ++#define ISOC_URB_GIVEBACK_ASAP ++ ++#define MAX_ISOC_XFER_SIZE_FS 1023 ++#define MAX_ISOC_XFER_SIZE_HS 3072 ++#define DESCNUM_THRESHOLD 4 ++ ++static void init_isoc_dma_desc(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, ++ uint8_t skip_frames) ++{ ++ struct fh_otg_hcd_iso_packet_desc *frame_desc; ++ fh_otg_qtd_t *qtd; ++ fh_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; ++ ++ idx = qh->td_last; ++ inc = qh->interval; ++ n_desc = 0; ++ ++ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; ++ if (skip_frames && !qh->channel) ++ ntd_max = ntd_max - skip_frames / qh->interval; ++ ++ max_xfer_size = ++ (qh->dev_speed == ++ FH_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : ++ MAX_ISOC_XFER_SIZE_FS; ++ ++ FH_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ while ((qh->ntd < ntd_max) ++ && (qtd->isoc_frame_index_last < ++ qtd->urb->packet_count)) { ++ ++ dma_desc = &qh->desc_list[idx]; ++ fh_memset(dma_desc, 0x00, sizeof(fh_otg_host_dma_desc_t)); ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; ++ ++ if (frame_desc->length > max_xfer_size) ++ qh->n_bytes[idx] = max_xfer_size; ++ else ++ qh->n_bytes[idx] = frame_desc->length; ++ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; ++ dma_desc->status.b_isoc.a = 1; ++ dma_desc->status.b_isoc.sts = 0; ++ ++ dma_desc->buf = qtd->urb->dma + frame_desc->offset; ++ ++ qh->ntd++; ++ ++ qtd->isoc_frame_index_last++; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* ++ * Set IOC for each descriptor corresponding to the ++ * last frame of the URB. ++ */ ++ if (qtd->isoc_frame_index_last == ++ qtd->urb->packet_count) ++ dma_desc->status.b_isoc.ioc = 1; ++ ++#endif ++ idx = desclist_idx_inc(idx, inc, qh->dev_speed); ++ n_desc++; ++ ++ } ++ qtd->in_process = 1; ++ } ++ ++ qh->td_last = idx; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* Set IOC for the last descriptor if descriptor list is full */ ++ if (qh->ntd == ntd_max) { ++ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++ } ++#else ++ /* ++ * Set IOC bit only for one descriptor. ++ * Always try to be ahead of HW processing, ++ * i.e. on IOC generation driver activates next descriptors but ++ * core continues to process descriptors followed the one with IOC set. ++ */ ++ ++ if (n_desc > DESCNUM_THRESHOLD) { ++ /* ++ * Move IOC "up". Required even if there is only one QTD ++ * in the list, cause QTDs migth continue to be queued, ++ * but during the activation it was only one queued. ++ * Actually more than one QTD might be in the list if this function called ++ * from XferCompletion - QTDs was queued during HW processing of the previous ++ * descriptor chunk. ++ */ ++ idx = fh_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); ++ } else { ++ /* ++ * Set the IOC for the latest descriptor ++ * if either number of descriptor is not greather than threshold ++ * or no more new descriptors activated. ++ */ ++ idx = fh_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ } ++ ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++#endif ++} ++ ++static void init_non_isoc_dma_desc(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ ++ fh_hc_t *hc; ++ fh_otg_host_dma_desc_t *dma_desc; ++ fh_otg_qtd_t *qtd; ++ int num_packets, len, n_desc = 0; ++ ++ hc = qh->channel; ++ ++ /* ++ * Start with hc->xfer_buff initialized in ++ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, ++ * this pointer re-assigned to the buffer of the currently processed QTD. ++ * For non-SG request there is always one QTD active. ++ */ ++ ++ FH_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ ++ if (n_desc) { ++ /* SG request - more than 1 QTDs */ ++ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; ++ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; ++ } ++ ++ qtd->n_desc = 0; ++ ++ do { ++ dma_desc = &qh->desc_list[n_desc]; ++ len = hc->xfer_len; ++ ++ if (len > MAX_DMA_DESC_SIZE) ++ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; ++ ++ if (hc->ep_is_in) { ++ if (len > 0) { ++ num_packets = (len + hc->max_packet - 1) / hc->max_packet; ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ /* Always program an integral # of max packets for IN transfers. */ ++ len = num_packets * hc->max_packet; ++ } ++ ++ dma_desc->status.b.n_bytes = len; ++ ++ qh->n_bytes[n_desc] = len; ++ ++ if ((qh->ep_type == UE_CONTROL) ++ && (qtd->control_phase == FH_OTG_CONTROL_SETUP)) ++ dma_desc->status.b.sup = 1; /* Setup Packet */ ++ ++ dma_desc->status.b.a = 1; /* Active descriptor */ ++ dma_desc->status.b.sts = 0; ++ ++ dma_desc->buf = ++ ((unsigned long)hc->xfer_buff & 0xffffffff); ++ ++ /* ++ * Last descriptor(or single) of IN transfer ++ * with actual size less than MaxPacket. ++ */ ++ if (len > hc->xfer_len) { ++ hc->xfer_len = 0; ++ } else { ++ hc->xfer_buff += len; ++ hc->xfer_len -= len; ++ } ++ ++ qtd->n_desc++; ++ n_desc++; ++ } ++ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); ++ ++ ++ qtd->in_process = 1; ++ ++ if (qh->ep_type == UE_CONTROL) ++ break; ++ ++ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) ++ break; ++ ++ if (qh->ep_is_in && (qh->ep_type == UE_BULK)) ++ break; ++ } ++ ++ if (n_desc) { ++ /* Request Transfer Complete interrupt for the last descriptor */ ++ qh->desc_list[n_desc - 1].status.b.ioc = 1; ++ /* End of List indicator */ ++ qh->desc_list[n_desc - 1].status.b.eol = 1; ++ ++ hc->ntd = n_desc; ++ } ++} ++ ++/** ++ * For Control and Bulk endpoints initializes descriptor list ++ * and starts the transfer. ++ * ++ * For Interrupt and Isochronous endpoints initializes descriptor list ++ * then updates FrameList, marking appropriate entries as active. ++ * In case of Isochronous, the starting descriptor index is calculated based ++ * on the scheduled frame, but only on the first transfer descriptor within a session. ++ * Then starts the transfer via enabling the channel. ++ * For Isochronous endpoint the channel is not halted on XferComplete ++ * interrupt so remains assigned to the endpoint(QH) until session is done. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++void fh_otg_hcd_start_xfer_ddma(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ /* Channel is already assigned */ ++ fh_hc_t *hc = qh->channel; ++ uint8_t skip_frames = 0; ++ ++ switch (hc->ep_type) { ++ case FH_OTG_EP_TYPE_CONTROL: ++ case FH_OTG_EP_TYPE_BULK: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ fh_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case FH_OTG_EP_TYPE_INTR: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ update_frame_list(hcd, qh, 1); ++ ++ fh_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case FH_OTG_EP_TYPE_ISOC: ++ ++ if (!qh->ntd) ++ skip_frames = recalc_initial_desc_idx(hcd, qh); ++ ++ init_isoc_dma_desc(hcd, qh, skip_frames); ++ ++ if (!hc->xfer_started) { ++ ++ update_frame_list(hcd, qh, 1); ++ ++ /* ++ * Always set to max, instead of actual size. ++ * Otherwise ntd will be changed with ++ * channel being enabled. Not recommended. ++ * ++ */ ++ hc->ntd = max_desc_num(qh); ++ /* Enable channel only once for ISOC */ ++ fh_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ } ++ ++ break; ++ default: ++ ++ break; ++ } ++} ++ ++static void complete_isoc_xfer_ddma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_halt_status_e halt_status) ++{ ++ struct fh_otg_hcd_iso_packet_desc *frame_desc; ++ fh_otg_qtd_t *qtd, *qtd_tmp; ++ fh_otg_qh_t *qh; ++ fh_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, remain; ++ uint8_t urb_compl; ++ ++ qh = hc->qh; ++ idx = qh->td_first; ++ ++ if (hc->halt_status == FH_OTG_HC_XFER_URB_DEQUEUE) { ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) ++ qtd->in_process = 0; ++ return; ++ } else if ((halt_status == FH_OTG_HC_XFER_AHB_ERR) || ++ (halt_status == FH_OTG_HC_XFER_BABBLE_ERR)) { ++ /* ++ * Channel is halted in these error cases. ++ * Considered as serious issues. ++ * Complete all URBs marking all frames as failed, ++ * irrespective whether some of the descriptors(frames) succeeded or no. ++ * Pass error code to completion routine as well, to ++ * update urb->status, some of class drivers might use it to stop ++ * queing transfer requests. ++ */ ++ int err = (halt_status == FH_OTG_HC_XFER_AHB_ERR) ++ ? (-FH_E_IO) ++ : (-FH_E_OVERFLOW); ++ ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ for (idx = 0; idx < qtd->urb->packet_count; idx++) { ++ frame_desc = &qtd->urb->iso_descs[idx]; ++ frame_desc->status = err; ++ } ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); ++ fh_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ return; ++ } ++ ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ ++ if (!qtd->in_process) ++ break; ++ ++ urb_compl = 0; ++ ++ do { ++ ++ dma_desc = &qh->desc_list[idx]; ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; ++ ++ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { ++ /* ++ * XactError or, unable to complete all the transactions ++ * in the scheduled micro-frame/frame, ++ * both indicated by DMA_DESC_STS_PKTERR. ++ */ ++ qtd->urb->error_count++; ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = -FH_E_PROTOCOL; ++ } else { ++ /* Success */ ++ ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = 0; ++ } ++ ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers here. ++ * The individual frame_desc status are used instead. ++ */ ++ ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ fh_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ /* ++ * This check is necessary because urb_dequeue can be called ++ * from urb complete callback(sound driver example). ++ * All pending URBs are dequeued there, so no need for ++ * further processing. ++ */ ++ if (hc->halt_status == FH_OTG_HC_XFER_URB_DEQUEUE) { ++ return; ++ } ++ ++ urb_compl = 1; ++ ++ } ++ ++ qh->ntd--; ++ ++ /* Stop if IOC requested descriptor reached */ ++ if (dma_desc->status.b_isoc.ioc) { ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ goto stop_scan; ++ } ++ ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ ++ if (urb_compl) ++ break; ++ } ++ while (idx != qh->td_first); ++ } ++stop_scan: ++ qh->td_first = idx; ++} ++ ++uint8_t update_non_isoc_urb_state_ddma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_qtd_t * qtd, ++ fh_otg_host_dma_desc_t * dma_desc, ++ fh_otg_halt_status_e halt_status, ++ uint32_t n_bytes, uint8_t * xfer_done) ++{ ++ ++ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ ++ if (halt_status == FH_OTG_HC_XFER_AHB_ERR) { ++ urb->status = -FH_E_IO; ++ return 1; ++ } ++ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { ++ switch (halt_status) { ++ case FH_OTG_HC_XFER_STALL: ++ urb->status = -FH_E_PIPE; ++ break; ++ case FH_OTG_HC_XFER_BABBLE_ERR: ++ urb->status = -FH_E_OVERFLOW; ++ break; ++ case FH_OTG_HC_XFER_XACT_ERR: ++ urb->status = -FH_E_PROTOCOL; ++ break; ++ default: ++ FH_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, ++ halt_status); ++ break; ++ } ++ return 1; ++ } ++ ++ if (dma_desc->status.b.a == 1) { ++ FH_DEBUGPL(DBG_HCDV, ++ "Active descriptor encountered on channel %d\n", ++ hc->hc_num); ++ return 0; ++ } ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_CONTROL) { ++ if (qtd->control_phase == FH_OTG_CONTROL_DATA) { ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length >= urb->length) { ++ /* ++ * For Control Data stage do not set urb->status=0 to prevent ++ * URB callback. Set it when Status phase done. See below. ++ */ ++ *xfer_done = 1; ++ } ++ ++ } else if (qtd->control_phase == FH_OTG_CONTROL_STATUS) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ /* No handling for SETUP stage */ ++ } else { ++ /* BULK and INTR */ ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length >= urb->length) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void complete_non_isoc_xfer_ddma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_halt_status_e halt_status) ++{ ++ fh_otg_hcd_urb_t *urb = NULL; ++ fh_otg_qtd_t *qtd, *qtd_tmp; ++ fh_otg_qh_t *qh; ++ fh_otg_host_dma_desc_t *dma_desc; ++ uint32_t n_bytes, n_desc, i, tmp_desc; ++ uint8_t failed = 0, xfer_done; ++ ++ n_desc = 0; ++ ++ qh = hc->qh; ++ ++ if (hc->halt_status == FH_OTG_HC_XFER_URB_DEQUEUE) { ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ qtd->in_process = 0; ++ } ++ return; ++ } ++ ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ ++ urb = qtd->urb; ++ ++ n_bytes = 0; ++ xfer_done = 0; ++ tmp_desc = qtd->n_desc; ++ ++ for (i = 0; i < tmp_desc; i++) { ++ dma_desc = &qh->desc_list[n_desc]; ++ ++ n_bytes = qh->n_bytes[n_desc]; ++ ++ failed = ++ update_non_isoc_urb_state_ddma(hcd, hc, qtd, ++ dma_desc, ++ halt_status, n_bytes, ++ &xfer_done); ++ ++ if (failed ++ || (xfer_done ++ && (urb->status != -FH_E_IN_PROGRESS))) { ++ ++ hcd->fops->complete(hcd, urb->priv, urb, ++ urb->status); ++ fh_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ if (failed) ++ goto stop_scan; ++ } else if (qh->ep_type == UE_CONTROL) { ++ if (qtd->control_phase == FH_OTG_CONTROL_SETUP) { ++ if (urb->length > 0) { ++ qtd->control_phase = FH_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = FH_OTG_CONTROL_STATUS; ++ } ++ FH_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); ++ } else if (qtd->control_phase == FH_OTG_CONTROL_DATA) { ++ if (xfer_done) { ++ qtd->control_phase = FH_OTG_CONTROL_STATUS; ++ FH_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); ++ } else if (i + 1 == tmp_desc) { ++ /* ++ * Last descriptor for Control data stage which is ++ * not completed yet. ++ */ ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ } ++ } ++ ++ n_desc++; ++ if (n_desc >= tmp_desc) ++ break; ++ } ++ ++ } ++ ++stop_scan: ++ ++ if (qh->ep_type != UE_CONTROL) { ++ /* ++ * Resetting the data toggle for bulk ++ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() ++ */ ++ if (halt_status == FH_OTG_HC_XFER_STALL) ++ qh->data_toggle = FH_OTG_HC_PID_DATA0; ++ else ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ ++ if (halt_status == FH_OTG_HC_XFER_COMPLETE) { ++ hcint_data_t hcint; ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. It ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ } ++ ++} ++ ++/** ++ * This function is called from interrupt handlers. ++ * Scans the descriptor list, updates URB's status and ++ * calls completion routine for the URB if it's done. ++ * Releases the channel to be used by other transfers. ++ * In case of Isochronous endpoint the channel is not halted until ++ * the end of the session, i.e. QTD list is empty. ++ * If periodic channel released the FrameList is updated accordingly. ++ * ++ * Calls transaction selection routines to activate pending transfers. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param hc Host channel, the transfer is completed on. ++ * @param hc_regs Host channel registers. ++ * @param halt_status Reason the channel is being halted, ++ * or just XferComplete for isochronous transfer ++ */ ++void fh_otg_hcd_complete_xfer_ddma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_halt_status_e halt_status) ++{ ++ uint8_t continue_isoc_xfer = 0; ++ fh_otg_transaction_type_e tr_type; ++ fh_otg_qh_t *qh = hc->qh; ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ ++ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ /* Release the channel if halted or session completed */ ++ if (halt_status != FH_OTG_HC_XFER_COMPLETE || ++ FH_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ ++ /* Halt the channel if session completed */ ++ if (halt_status == FH_OTG_HC_XFER_COMPLETE) { ++ fh_otg_hc_halt(hcd->core_if, hc, halt_status); ++ } ++ ++ release_channel_ddma(hcd, qh); ++ fh_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* Keep in assigned schedule to continue transfer */ ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ continue_isoc_xfer = 1; ++ ++ } ++ /** @todo Consider the case when period exceeds FrameList size. ++ * Frame Rollover interrupt should be used. ++ */ ++ } else { ++ /* Scan descriptor list to complete the URB(s), then release the channel */ ++ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ release_channel_ddma(hcd, qh); ++ fh_otg_hcd_qh_remove(hcd, qh); ++ ++ if (!FH_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule on normal completion */ ++ fh_otg_hcd_qh_add(hcd, qh); ++ } ++ ++ } ++ tr_type = fh_otg_hcd_select_transactions(hcd); ++ if (tr_type != FH_OTG_TRANSACTION_NONE || continue_isoc_xfer) { ++ if (continue_isoc_xfer) { ++ if (tr_type == FH_OTG_TRANSACTION_NONE) { ++ tr_type = FH_OTG_TRANSACTION_PERIODIC; ++ } else if (tr_type == FH_OTG_TRANSACTION_NON_PERIODIC) { ++ tr_type = FH_OTG_TRANSACTION_ALL; ++ } ++ } ++ fh_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_if.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_if.h +new file mode 100644 +index 00000000..55a0d658 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_if.h +@@ -0,0 +1,412 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd_if.h $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++#ifndef __FH_HCD_IF_H__ ++#define __FH_HCD_IF_H__ ++ ++#include "fh_otg_core_if.h" ++ ++/** @file ++ * This file defines FH_OTG HCD Core API. ++ */ ++ ++struct fh_otg_hcd; ++typedef struct fh_otg_hcd fh_otg_hcd_t; ++ ++struct fh_otg_hcd_urb; ++typedef struct fh_otg_hcd_urb fh_otg_hcd_urb_t; ++ ++/** @name HCD Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function is called whenever core switches to host mode. */ ++typedef int (*fh_otg_hcd_start_cb_t) (fh_otg_hcd_t * hcd); ++ ++/** This function is called when device has been disconnected */ ++typedef int (*fh_otg_hcd_disconnect_cb_t) (fh_otg_hcd_t * hcd); ++ ++/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */ ++typedef int (*fh_otg_hcd_hub_info_from_urb_cb_t) (fh_otg_hcd_t * hcd, ++ void *urb_handle, ++ uint32_t * hub_addr, ++ uint32_t * port_addr); ++/** Via this function HCD core gets device speed */ ++typedef int (*fh_otg_hcd_speed_from_urb_cb_t) (fh_otg_hcd_t * hcd, ++ void *urb_handle); ++ ++/** This function is called when urb is completed */ ++typedef int (*fh_otg_hcd_complete_urb_cb_t) (fh_otg_hcd_t * hcd, ++ void *urb_handle, ++ fh_otg_hcd_urb_t * fh_otg_urb, ++ int32_t status); ++ ++/** Via this function HCD core gets b_hnp_enable parameter */ ++typedef int (*fh_otg_hcd_get_b_hnp_enable) (fh_otg_hcd_t * hcd); ++ ++struct fh_otg_hcd_function_ops { ++ fh_otg_hcd_start_cb_t start; ++ fh_otg_hcd_disconnect_cb_t disconnect; ++ fh_otg_hcd_hub_info_from_urb_cb_t hub_info; ++ fh_otg_hcd_speed_from_urb_cb_t speed; ++ fh_otg_hcd_complete_urb_cb_t complete; ++ fh_otg_hcd_get_b_hnp_enable get_b_hnp_enable; ++}; ++/** @} */ ++ ++/** @name HCD Core API */ ++/** @{ */ ++/** This function allocates fh_otg_hcd structure and returns pointer on it. */ ++extern fh_otg_hcd_t *fh_otg_hcd_alloc_hcd(void); ++ ++/** This function should be called to initiate HCD Core. ++ * ++ * @param hcd The HCD ++ * @param core_if The FH_OTG Core ++ * ++ * Returns -FH_E_NO_MEMORY if no enough memory. ++ * Returns 0 on success ++ */ ++extern int fh_otg_hcd_init(fh_otg_hcd_t * hcd, fh_otg_core_if_t * core_if); ++ ++/** Frees HCD ++ * ++ * @param hcd The HCD ++ */ ++extern void fh_otg_hcd_remove(fh_otg_hcd_t * hcd); ++ ++/** This function should be called on every hardware interrupt. ++ * ++ * @param fh_otg_hcd The HCD ++ * ++ * Returns non zero if interrupt is handled ++ * Return 0 if interrupt is not handled ++ */ ++extern int32_t fh_otg_hcd_handle_intr(fh_otg_hcd_t * fh_otg_hcd); ++ ++/** ++ * Returns private data set by ++ * fh_otg_hcd_set_priv_data function. ++ * ++ * @param hcd The HCD ++ */ ++extern void *fh_otg_hcd_get_priv_data(fh_otg_hcd_t * hcd); ++ ++/** ++ * Set private data. ++ * ++ * @param hcd The HCD ++ * @param priv_data pointer to be stored in private data ++ */ ++extern void fh_otg_hcd_set_priv_data(fh_otg_hcd_t * hcd, void *priv_data); ++ ++/** ++ * This function initializes the HCD Core. ++ * ++ * @param hcd The HCD ++ * @param fops The Function Driver Operations data structure containing pointers to all callbacks. ++ * ++ * Returns -FH_E_NO_DEVICE if Core is currently is in device mode. ++ * Returns 0 on success ++ */ ++extern int fh_otg_hcd_start(fh_otg_hcd_t * hcd, ++ struct fh_otg_hcd_function_ops *fops); ++ ++/** ++ * Halts the FH_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ * ++ * @param hcd The HCD ++ */ ++extern void fh_otg_hcd_stop(fh_otg_hcd_t * hcd); ++ ++/** ++ * Handles hub class-specific requests. ++ * ++ * @param fh_otg_hcd The HCD ++ * @param typeReq Request Type ++ * @param wValue wValue from control request ++ * @param wIndex wIndex from control request ++ * @param buf data buffer ++ * @param wLength data buffer length ++ * ++ * Returns -FH_E_INVALID if invalid argument is passed ++ * Returns 0 on success ++ */ ++extern int fh_otg_hcd_hub_control(fh_otg_hcd_t * fh_otg_hcd, ++ uint16_t typeReq, uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, ++ uint16_t wLength); ++ ++/** ++ * Returns otg port number. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t fh_otg_hcd_otg_port(fh_otg_hcd_t * hcd); ++ ++/** ++ * Returns OTG version - either 1.3 or 2.0. ++ * ++ * @param core_if The core_if structure pointer ++ */ ++extern uint16_t fh_otg_get_otg_version(fh_otg_core_if_t * core_if); ++ ++/** ++ * Returns 1 if currently core is acting as B host, and 0 otherwise. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t fh_otg_hcd_is_b_host(fh_otg_hcd_t * hcd); ++ ++/** ++ * Returns current frame number. ++ * ++ * @param hcd The HCD ++ */ ++extern int fh_otg_hcd_get_frame_number(fh_otg_hcd_t * hcd); ++ ++/** ++ * Dumps hcd state. ++ * ++ * @param hcd The HCD ++ */ ++extern void fh_otg_hcd_dump_state(fh_otg_hcd_t * hcd); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ * Currently this function is not implemented. ++ * ++ * @param hcd The HCD ++ */ ++extern void fh_otg_hcd_dump_frrem(fh_otg_hcd_t * hcd); ++ ++/** ++ * Sends LPM transaction to the local device. ++ * ++ * @param hcd The HCD ++ * @param devaddr Device Address ++ * @param hird Host initiated resume duration ++ * @param bRemoteWake Value of bRemoteWake field in LPM transaction ++ * ++ * Returns negative value if sending LPM transaction was not succeeded. ++ * Returns 0 on success. ++ */ ++extern int fh_otg_hcd_send_lpm(fh_otg_hcd_t * hcd, uint8_t devaddr, ++ uint8_t hird, uint8_t bRemoteWake); ++ ++/* URB interface */ ++ ++/** ++ * Allocates memory for fh_otg_hcd_urb structure. ++ * Allocated memory should be freed by call of FH_FREE. ++ * ++ * @param hcd The HCD ++ * @param iso_desc_count Count of ISOC descriptors ++ * @param atomic_alloc Specefies whether to perform atomic allocation. ++ */ ++extern fh_otg_hcd_urb_t *fh_otg_hcd_urb_alloc(fh_otg_hcd_t * hcd, ++ int iso_desc_count, ++ int atomic_alloc); ++ ++/** ++ * Set pipe information in URB. ++ * ++ * @param hcd_urb FH_OTG URB ++ * @param devaddr Device Address ++ * @param ep_num Endpoint Number ++ * @param ep_type Endpoint Type ++ * @param ep_dir Endpoint Direction ++ * @param mps Max Packet Size ++ */ ++extern void fh_otg_hcd_urb_set_pipeinfo(fh_otg_hcd_urb_t * hcd_urb, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, ++ uint16_t mps); ++ ++/* Transfer flags */ ++#define URB_GIVEBACK_ASAP 0x1 ++#define URB_SEND_ZERO_PACKET 0x2 ++ ++/** ++ * Sets fh_otg_hcd_urb parameters. ++ * ++ * @param urb FH_OTG URB allocated by fh_otg_hcd_urb_alloc function. ++ * @param urb_handle Unique handle for request, this will be passed back ++ * to function driver in completion callback. ++ * @param buf The buffer for the data ++ * @param dma The DMA buffer for the data ++ * @param buflen Transfer length ++ * @param sp Buffer for setup data ++ * @param sp_dma DMA address of setup data buffer ++ * @param flags Transfer flags ++ * @param interval Polling interval for interrupt or isochronous transfers. ++ */ ++extern void fh_otg_hcd_urb_set_params(fh_otg_hcd_urb_t * urb, ++ void *urb_handle, void *buf, ++ fh_dma_t dma, uint32_t buflen, void *sp, ++ fh_dma_t sp_dma, uint32_t flags, ++ uint16_t interval); ++ ++/** Gets status from fh_otg_hcd_urb ++ * ++ * @param fh_otg_urb FH_OTG URB ++ */ ++extern uint32_t fh_otg_hcd_urb_get_status(fh_otg_hcd_urb_t * fh_otg_urb); ++ ++/** Gets actual length from fh_otg_hcd_urb ++ * ++ * @param fh_otg_urb FH_OTG URB ++ */ ++extern uint32_t fh_otg_hcd_urb_get_actual_length(fh_otg_hcd_urb_t * ++ fh_otg_urb); ++ ++/** Gets error count from fh_otg_hcd_urb. Only for ISOC URBs ++ * ++ * @param fh_otg_urb FH_OTG URB ++ */ ++extern uint32_t fh_otg_hcd_urb_get_error_count(fh_otg_hcd_urb_t * ++ fh_otg_urb); ++ ++/** Set ISOC descriptor offset and length ++ * ++ * @param fh_otg_urb FH_OTG URB ++ * @param desc_num ISOC descriptor number ++ * @param offset Offset from beginig of buffer. ++ * @param length Transaction length ++ */ ++extern void fh_otg_hcd_urb_set_iso_desc_params(fh_otg_hcd_urb_t * fh_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length); ++ ++/** Get status of ISOC descriptor, specified by desc_num ++ * ++ * @param fh_otg_urb FH_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t fh_otg_hcd_urb_get_iso_desc_status(fh_otg_hcd_urb_t * ++ fh_otg_urb, int desc_num); ++ ++/** Get actual length of ISOC descriptor, specified by desc_num ++ * ++ * @param fh_otg_urb FH_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t fh_otg_hcd_urb_get_iso_desc_actual_length(fh_otg_hcd_urb_t * ++ fh_otg_urb, ++ int desc_num); ++ ++/** Queue URB. After transfer is completes, the complete callback will be called with the URB status ++ * ++ * @param fh_otg_hcd The HCD ++ * @param fh_otg_urb FH_OTG URB ++ * @param ep_handle Out parameter for returning endpoint handle ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * Returns -FH_E_NO_DEVICE if no device is connected. ++ * Returns -FH_E_NO_MEMORY if there is no enough memory. ++ * Returns 0 on success. ++ */ ++extern int fh_otg_hcd_urb_enqueue(fh_otg_hcd_t * fh_otg_hcd, ++ fh_otg_hcd_urb_t * fh_otg_urb, ++ void **ep_handle, int atomic_alloc); ++ ++/** De-queue the specified URB ++ * ++ * @param fh_otg_hcd The HCD ++ * @param fh_otg_urb FH_OTG URB ++ */ ++extern int fh_otg_hcd_urb_dequeue(fh_otg_hcd_t * fh_otg_hcd, ++ fh_otg_hcd_urb_t * fh_otg_urb); ++ ++/** Frees resources in the FH_otg controller related to a given endpoint. ++ * Any URBs for the endpoint must already be dequeued. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by fh_otg_hcd_urb_enqueue function ++ * @param retry Number of retries if there are queued transfers. ++ * ++ * Returns -FH_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int fh_otg_hcd_endpoint_disable(fh_otg_hcd_t * hcd, void *ep_handle, ++ int retry); ++ ++/* Resets the data toggle in qh structure. This function can be called from ++ * usb_clear_halt routine. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by fh_otg_hcd_urb_enqueue function ++ * ++ * Returns -FH_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int fh_otg_hcd_endpoint_reset(fh_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns 1 if status of specified port is changed and 0 otherwise. ++ * ++ * @param hcd The HCD ++ * @param port Port number ++ */ ++extern int fh_otg_hcd_is_status_changed(fh_otg_hcd_t * hcd, int port); ++ ++/** Call this function to check if bandwidth was allocated for specified endpoint. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int fh_otg_hcd_is_bandwidth_allocated(fh_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** Call this function to check if bandwidth was freed for specified endpoint. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int fh_otg_hcd_is_bandwidth_freed(fh_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns bandwidth allocated for specified endpoint in microseconds. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern uint8_t fh_otg_hcd_get_ep_bandwidth(fh_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** @} */ ++ ++#endif /* __FH_HCD_IF_H__ */ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_intr.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_intr.c +new file mode 100644 +index 00000000..e891950f +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_intr.c +@@ -0,0 +1,2107 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd_intr.c $ ++ * $Revision: #94 $ ++ * $Date: 2013/01/31 $ ++ * $Change: 2155605 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++ ++#include "fh_otg_hcd.h" ++#include "fh_otg_regs.h" ++ ++/** @file ++ * This file contains the implementation of the HCD Interrupt handlers. ++ */ ++ ++/** This function handles interrupts for the HCD. */ ++int32_t fh_otg_hcd_handle_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ int retval = 0; ++ ++ fh_otg_core_if_t *core_if = fh_otg_hcd->core_if; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ ++ if (fh_otg_check_haps_status(core_if) == -1 ) { ++ FH_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++ FH_SPINLOCK(fh_otg_hcd->lock); ++ /* Check if HOST Mode */ ++ if (fh_otg_is_host_mode(core_if)) { ++ gintsts.d32 = fh_otg_read_core_intr(core_if); ++ if (!gintsts.d32) { ++ FH_SPINUNLOCK(fh_otg_hcd->lock); ++ return 0; ++ } ++#ifdef DEBUG ++ /* Don't print debug message in the interrupt handler on SOF */ ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != FH_SOF_INTR_MASK) ++#endif ++ FH_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != FH_SOF_INTR_MASK) ++#endif ++ FH_DEBUGPL(DBG_HCD, ++ "FH OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x\n", ++ gintsts.d32); ++#endif ++ ++ if (gintsts.b.sofintr) { ++ retval |= fh_otg_hcd_handle_sof_intr(fh_otg_hcd); ++ } ++ if (gintsts.b.rxstsqlvl) { ++ retval |= ++ fh_otg_hcd_handle_rx_status_q_level_intr ++ (fh_otg_hcd); ++ } ++ if (gintsts.b.nptxfempty) { ++ retval |= ++ fh_otg_hcd_handle_np_tx_fifo_empty_intr ++ (fh_otg_hcd); ++ } ++ if (gintsts.b.i2cintr) { ++ /** @todo Implement i2cintr handler. */ ++ } ++ if (gintsts.b.portintr) { ++ retval |= fh_otg_hcd_handle_port_intr(fh_otg_hcd); ++ } ++ if (gintsts.b.hcintr) { ++ retval |= fh_otg_hcd_handle_hc_intr(fh_otg_hcd); ++ } ++ if (gintsts.b.ptxfempty) { ++ retval |= ++ fh_otg_hcd_handle_perio_tx_fifo_empty_intr ++ (fh_otg_hcd); ++ } ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != FH_SOF_INTR_MASK) ++#endif ++ { ++ FH_DEBUGPL(DBG_HCD, ++ "FH OTG HCD Finished Servicing Interrupts\n"); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD gintsts=0x%08x\n", ++ FH_READ_REG32(&global_regs->gintsts)); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD gintmsk=0x%08x\n", ++ FH_READ_REG32(&global_regs->gintmsk)); ++ } ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != FH_SOF_INTR_MASK) ++#endif ++ FH_DEBUGPL(DBG_HCD, "\n"); ++#endif ++ ++ } ++ FH_SPINUNLOCK(fh_otg_hcd->lock); ++ return retval; ++} ++ ++#ifdef FH_TRACK_MISSED_SOFS ++#warning Compiling code to track missed SOFs ++#define FRAME_NUM_ARRAY_SIZE 1000 ++/** ++ * This function is for debug only. ++ */ ++static inline void track_missed_sofs(uint16_t curr_frame_number) ++{ ++ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static int frame_num_idx = 0; ++ static uint16_t last_frame_num = FH_HFNUM_MAX_FRNUM; ++ static int dumped_frame_num_array = 0; ++ ++ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { ++ if (((last_frame_num + 1) & FH_HFNUM_MAX_FRNUM) != ++ curr_frame_number) { ++ frame_num_array[frame_num_idx] = curr_frame_number; ++ last_frame_num_array[frame_num_idx++] = last_frame_num; ++ } ++ } else if (!dumped_frame_num_array) { ++ int i; ++ FH_PRINTF("Frame Last Frame\n"); ++ FH_PRINTF("----- ----------\n"); ++ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { ++ FH_PRINTF("0x%04x 0x%04x\n", ++ frame_num_array[i], last_frame_num_array[i]); ++ } ++ dumped_frame_num_array = 1; ++ } ++ last_frame_num = curr_frame_number; ++} ++#endif ++ ++/** ++ * Handles the start-of-frame interrupt in host mode. Non-periodic ++ * transactions may be queued to the FH_otg controller for the current ++ * (micro)frame. Periodic transactions may be queued to the controller for the ++ * next (micro)frame. ++ */ ++int32_t fh_otg_hcd_handle_sof_intr(fh_otg_hcd_t * hcd) ++{ ++ hfnum_data_t hfnum; ++ fh_list_link_t *qh_entry; ++ fh_otg_qh_t *qh; ++ fh_otg_transaction_type_e tr_type; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ hfnum.d32 = ++ FH_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ ++#ifdef DEBUG_SOF ++ FH_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); ++#endif ++ hcd->frame_number = hfnum.b.frnum; ++ ++#ifdef DEBUG ++ hcd->frrem_accum += hfnum.b.frrem; ++ hcd->frrem_samples++; ++#endif ++ ++#ifdef FH_TRACK_MISSED_SOFS ++ track_missed_sofs(hcd->frame_number); ++#endif ++ /* Determine whether any periodic QHs should be executed. */ ++ qh_entry = FH_LIST_FIRST(&hcd->periodic_sched_inactive); ++ while (qh_entry != &hcd->periodic_sched_inactive) { ++ qh = FH_LIST_ENTRY(qh_entry, fh_otg_qh_t, qh_list_entry); ++ qh_entry = qh_entry->next; ++ if (fh_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ /* ++ * Move QH to the ready list to be executed next ++ * (micro)frame. ++ */ ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } ++ } ++ tr_type = fh_otg_hcd_select_transactions(hcd); ++ if (tr_type != FH_OTG_TRANSACTION_NONE) { ++ fh_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.b.sofintr = 1; ++ FH_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at ++ * least one packet in the Rx FIFO. The packets are moved from the FIFO to ++ * memory if the FH_otg controller is operating in Slave mode. */ ++int32_t fh_otg_hcd_handle_rx_status_q_level_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ host_grxsts_data_t grxsts; ++ fh_hc_t *hc = NULL; ++ ++ FH_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); ++ ++ grxsts.d32 = ++ FH_READ_REG32(&fh_otg_hcd->core_if->core_global_regs->grxstsp); ++ ++ hc = fh_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ if (!hc) { ++ FH_ERROR("Unable to get corresponding channel\n"); ++ return 0; ++ } ++ ++ /* Packet Status */ ++ FH_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); ++ FH_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); ++ FH_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, ++ hc->data_pid_start); ++ FH_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); ++ ++ switch (grxsts.b.pktsts) { ++ case FH_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer. */ ++ if (grxsts.b.bcnt > 0) { ++ fh_otg_read_packet(fh_otg_hcd->core_if, ++ hc->xfer_buff, grxsts.b.bcnt); ++ ++ /* Update the HC fields for the next packet received. */ ++ hc->xfer_count += grxsts.b.bcnt; ++ hc->xfer_buff += grxsts.b.bcnt; ++ } ++ ++ case FH_GRXSTS_PKTSTS_IN_XFER_COMP: ++ case FH_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: ++ case FH_GRXSTS_PKTSTS_CH_HALTED: ++ /* Handled in interrupt, just ignore data */ ++ break; ++ default: ++ FH_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", ++ grxsts.b.pktsts); ++ break; ++ } ++ ++ return 1; ++} ++ ++/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More ++ * data packets may be written to the FIFO for OUT transfers. More requests ++ * may be written to the non-periodic request queue for IN transfers. This ++ * interrupt is enabled only in Slave mode. */ ++int32_t fh_otg_hcd_handle_np_tx_fifo_empty_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); ++ fh_otg_hcd_queue_transactions(fh_otg_hcd, ++ FH_OTG_TRANSACTION_NON_PERIODIC); ++ return 1; ++} ++ ++/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data ++ * packets may be written to the FIFO for OUT transfers. More requests may be ++ * written to the periodic request queue for IN transfers. This interrupt is ++ * enabled only in Slave mode. */ ++int32_t fh_otg_hcd_handle_perio_tx_fifo_empty_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); ++ fh_otg_hcd_queue_transactions(fh_otg_hcd, ++ FH_OTG_TRANSACTION_PERIODIC); ++ return 1; ++} ++ ++/** There are multiple conditions that can cause a port interrupt. This function ++ * determines which interrupt conditions have occurred and handles them ++ * appropriately. */ ++int32_t fh_otg_hcd_handle_port_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ hprt0_data_t hprt0_modify; ++ ++ hprt0.d32 = FH_READ_REG32(fh_otg_hcd->core_if->host_if->hprt0); ++ hprt0_modify.d32 = FH_READ_REG32(fh_otg_hcd->core_if->host_if->hprt0); ++ ++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in ++ * GINTSTS */ ++ ++ hprt0_modify.b.prtena = 0; ++ hprt0_modify.b.prtconndet = 0; ++ hprt0_modify.b.prtenchng = 0; ++ hprt0_modify.b.prtovrcurrchng = 0; ++ ++ /* Port Connect Detected ++ * Set flag and clear if detected */ ++ if (fh_otg_hcd->core_if->hibernation_suspend == 1) { ++ // Dont modify port status if we are in hibernation state ++ hprt0_modify.b.prtconndet = 1; ++ hprt0_modify.b.prtenchng = 1; ++ FH_WRITE_REG32(fh_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ hprt0.d32 = FH_READ_REG32(fh_otg_hcd->core_if->host_if->hprt0); ++ return retval; ++ } ++ ++ if (hprt0.b.prtconndet) { ++ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ ++ if (fh_otg_hcd->core_if->adp_enable && ++ fh_otg_hcd->core_if->adp.vbuson_timer_started == 1) { ++ FH_PRINTF("PORT CONNECT DETECTED ----------------\n"); ++ FH_TIMER_CANCEL(fh_otg_hcd->core_if->adp.vbuson_timer); ++ fh_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ /* TODO - check if this is required, as ++ * host initialization was already performed ++ * after initial ADP probing ++ */ ++ /*fh_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ fh_otg_core_init(fh_otg_hcd->core_if); ++ fh_otg_enable_global_interrupts(fh_otg_hcd->core_if); ++ cil_hcd_start(fh_otg_hcd->core_if);*/ ++ } else { ++ hprt0_data_t hprt0_local; ++ FH_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " ++ "Port Connect Detected--\n", hprt0.d32); ++ fh_otg_hcd->flags.b.port_connect_status_change = 1; ++ fh_otg_hcd->flags.b.port_connect_status = 1; ++ hprt0_modify.b.prtconndet = 1; ++ /* PET testing */ ++ if (fh_otg_hcd->core_if->otg_ver && (fh_otg_hcd->core_if->test_mode == 7)) { ++ hprt0_local.d32 = fh_otg_read_hprt0(fh_otg_hcd->core_if); ++ hprt0_local.b.prtrst = 1; ++ FH_WRITE_REG32(fh_otg_hcd->core_if->host_if->hprt0, hprt0_local.d32); ++ fh_mdelay(60); ++ hprt0.d32 = fh_otg_read_hprt0(fh_otg_hcd->core_if); ++ hprt0.b.prtrst = 0; ++ FH_WRITE_REG32(fh_otg_hcd->core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ FH_TIMER_CANCEL(fh_otg_hcd->conn_timer); ++ } ++ /* The Hub driver asserts a reset when it sees port connect ++ * status change flag */ ++ retval |= 1; ++ } ++ ++ /* Port Enable Changed ++ * Clear if detected - Set internal flag if disabled */ ++ if (hprt0.b.prtenchng) { ++ FH_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Enable Changed--\n", hprt0.d32); ++ hprt0_modify.b.prtenchng = 1; ++ if (hprt0.b.prtena == 1) { ++ hfir_data_t hfir; ++ int do_reset = 0; ++ fh_otg_core_params_t *params = ++ fh_otg_hcd->core_if->core_params; ++ fh_otg_core_global_regs_t *global_regs = ++ fh_otg_hcd->core_if->core_global_regs; ++ fh_otg_host_if_t *host_if = ++ fh_otg_hcd->core_if->host_if; ++ ++ /* Every time when port enables calculate ++ * HFIR.FrInterval ++ */ ++ hfir.d32 = FH_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.frint = calc_frame_interval(fh_otg_hcd->core_if); ++ FH_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ ++ /* Check if we need to adjust the PHY clock speed for ++ * low power and adjust it */ ++ if (params->host_support_fs_ls_low_power) { ++ gusbcfg_data_t usbcfg; ++ ++ usbcfg.d32 = ++ FH_READ_REG32(&global_regs->gusbcfg); ++ ++ if (hprt0.b.prtspd == FH_HPRT0_PRTSPD_LOW_SPEED ++ || hprt0.b.prtspd == ++ FH_HPRT0_PRTSPD_FULL_SPEED) { ++ /* ++ * Low power ++ */ ++ hcfg_data_t hcfg; ++ if (usbcfg.b.phylpwrclksel == 0) { ++ /* Set PHY low power clock select for FS/LS devices */ ++ usbcfg.b.phylpwrclksel = 1; ++ FH_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ ++ hcfg.d32 = ++ FH_READ_REG32 ++ (&host_if->host_global_regs->hcfg); ++ ++ if (hprt0.b.prtspd == ++ FH_HPRT0_PRTSPD_LOW_SPEED ++ && params->host_ls_low_power_phy_clk ++ == ++ FH_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) ++ { ++ /* 6 MHZ */ ++ FH_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); ++ if (hcfg.b.fslspclksel != ++ FH_HCFG_6_MHZ) { ++ hcfg.b.fslspclksel = ++ FH_HCFG_6_MHZ; ++ FH_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } else { ++ /* 48 MHZ */ ++ FH_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 48 MHz ()\n"); ++ if (hcfg.b.fslspclksel != ++ FH_HCFG_48_MHZ) { ++ hcfg.b.fslspclksel = ++ FH_HCFG_48_MHZ; ++ FH_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } ++ } else { ++ /* ++ * Not low power ++ */ ++ if (usbcfg.b.phylpwrclksel == 1) { ++ usbcfg.b.phylpwrclksel = 0; ++ FH_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ } ++ ++ if (do_reset) { ++ FH_TASK_SCHEDULE(fh_otg_hcd->reset_tasklet); ++ } ++ } ++ ++ if (!do_reset) { ++ /* Port has been enabled set the reset change flag */ ++ fh_otg_hcd->flags.b.port_reset_change = 1; ++ } ++ } else { ++ fh_otg_hcd->flags.b.port_enable_change = 1; ++ } ++ retval |= 1; ++ } ++ ++ /** Overcurrent Change Interrupt */ ++ if (hprt0.b.prtovrcurrchng) { ++ FH_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Overcurrent Changed--\n", hprt0.d32); ++ fh_otg_hcd->flags.b.port_over_current_change = 1; ++ hprt0_modify.b.prtovrcurrchng = 1; ++ retval |= 1; ++ } ++ ++ /* Clear Port Interrupts */ ++ FH_WRITE_REG32(fh_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ ++ return retval; ++} ++ ++/** This interrupt indicates that one or more host channels has a pending ++ * interrupt. There are multiple conditions that can cause each host channel ++ * interrupt. This function determines which conditions have occurred for each ++ * host channel interrupt and handles them appropriately. */ ++int32_t fh_otg_hcd_handle_hc_intr(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ int i; ++ int retval = 0; ++ haint_data_t haint; ++ ++ /* Clear appropriate bits in HCINTn to clear the interrupt bit in ++ * GINTSTS */ ++ ++ haint.d32 = fh_otg_read_host_all_channels_intr(fh_otg_hcd->core_if); ++ ++ for (i = 0; i < fh_otg_hcd->core_if->core_params->host_channels; i++) { ++ if (haint.b2.chint & (1 << i)) { ++ retval |= fh_otg_hcd_handle_hc_n_intr(fh_otg_hcd, i); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Gets the actual length of a transfer after the transfer halts. _halt_status ++ * holds the reason for the halt. ++ * ++ * For IN transfers where halt_status is FH_OTG_HC_XFER_COMPLETE, ++ * *short_read is set to 1 upon return if less than the requested ++ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon ++ * return. short_read may also be NULL on entry, in which case it remains ++ * unchanged. ++ */ ++static uint32_t get_actual_xfer_length(fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd, ++ fh_otg_halt_status_e halt_status, ++ int *short_read) ++{ ++ hctsiz_data_t hctsiz; ++ uint32_t length; ++ ++ if (short_read != NULL) { ++ *short_read = 0; ++ } ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ ++ if (halt_status == FH_OTG_HC_XFER_COMPLETE) { ++ if (hc->ep_is_in) { ++ length = hc->xfer_len - hctsiz.b.xfersize; ++ if (short_read != NULL) { ++ *short_read = (hctsiz.b.xfersize != 0); ++ } ++ } else if (hc->qh->do_split) { ++ length = qtd->ssplit_out_xfer_count; ++ } else { ++ length = hc->xfer_len; ++ } ++ } else { ++ /* ++ * Must use the hctsiz.pktcnt field to determine how much data ++ * has been transferred. This field reflects the number of ++ * packets that have been transferred via the USB. This is ++ * always an integral number of packets if the transfer was ++ * halted before its normal completion. (Can't use the ++ * hctsiz.xfersize field because that reflects the number of ++ * bytes transferred via the AHB, not the USB). ++ */ ++ length = ++ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; ++ } ++ ++ return length; ++} ++ ++/** ++ * Updates the state of the URB after a Transfer Complete interrupt on the ++ * host channel. Updates the actual_length field of the URB based on the ++ * number of bytes transferred via the host channel. Sets the URB status ++ * if the data transfer is finished. ++ * ++ * @return 1 if the data transfer specified by the URB is completely finished, ++ * 0 otherwise. ++ */ ++static int update_urb_state_xfer_comp(fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_hcd_urb_t * urb, ++ fh_otg_qtd_t * qtd) ++{ ++ int xfer_done = 0; ++ int short_read = 0; ++ ++ int xfer_length; ++ ++ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_COMPLETE, ++ &short_read); ++ ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && xfer_length && hc->ep_is_in) { ++ fh_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ xfer_length); ++ } ++ ++ urb->actual_length += xfer_length; ++ ++ if (xfer_length && (hc->ep_type == FH_OTG_EP_TYPE_BULK) && ++ (urb->flags & URB_SEND_ZERO_PACKET) ++ && (urb->actual_length >= urb->length) ++ && !(urb->length % hc->max_packet)) { ++ xfer_done = 0; ++ } else if (short_read || urb->actual_length >= urb->length) { ++ xfer_done = 1; ++ urb->status = 0; ++ } ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ FH_DEBUGPL(DBG_HCDV, "FH_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); ++ FH_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", ++ hctsiz.b.xfersize); ++ FH_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ FH_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ FH_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", ++ short_read, xfer_done); ++ } ++#endif ++ ++ return xfer_done; ++} ++ ++/* ++ * Save the starting data toggle for the next transfer. The data toggle is ++ * saved in the QH for non-control transfers and it's saved in the QTD for ++ * control transfers. ++ */ ++void fh_otg_hcd_save_data_toggle(fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, fh_otg_qtd_t * qtd) ++{ ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ ++ if (hc->ep_type != FH_OTG_EP_TYPE_CONTROL) { ++ fh_otg_qh_t *qh = hc->qh; ++ if (hctsiz.b.pid == FH_HCTSIZ_DATA0) { ++ qh->data_toggle = FH_OTG_HC_PID_DATA0; ++ } else { ++ qh->data_toggle = FH_OTG_HC_PID_DATA1; ++ } ++ } else { ++ if (hctsiz.b.pid == FH_HCTSIZ_DATA0) { ++ qtd->data_toggle = FH_OTG_HC_PID_DATA0; ++ } else { ++ qtd->data_toggle = FH_OTG_HC_PID_DATA1; ++ } ++ } ++} ++ ++/** ++ * Updates the state of an Isochronous URB when the transfer is stopped for ++ * any reason. The fields of the current entry in the frame descriptor array ++ * are set based on the transfer state and the input _halt_status. Completes ++ * the Isochronous URB if all the URB frames have been completed. ++ * ++ * @return FH_OTG_HC_XFER_COMPLETE if there are more frames remaining to be ++ * transferred in the URB. Otherwise return FH_OTG_HC_XFER_URB_COMPLETE. ++ */ ++static fh_otg_halt_status_e ++update_isoc_urb_state(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd, fh_otg_halt_status_e halt_status) ++{ ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ fh_otg_halt_status_e ret_val = halt_status; ++ struct fh_otg_hcd_iso_packet_desc *frame_desc; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ switch (halt_status) { ++ case FH_OTG_HC_XFER_COMPLETE: ++ frame_desc->status = 0; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ fh_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ ++ break; ++ case FH_OTG_HC_XFER_FRAME_OVERRUN: ++ urb->error_count++; ++ if (hc->ep_is_in) { ++ frame_desc->status = -FH_E_NO_STREAM_RES; ++ } else { ++ frame_desc->status = -FH_E_COMMUNICATION; ++ } ++ frame_desc->actual_length = 0; ++ break; ++ case FH_OTG_HC_XFER_BABBLE_ERR: ++ urb->error_count++; ++ frame_desc->status = -FH_E_OVERFLOW; ++ /* Don't need to update actual_length in this case. */ ++ break; ++ case FH_OTG_HC_XFER_XACT_ERR: ++ urb->error_count++; ++ frame_desc->status = -FH_E_PROTOCOL; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ fh_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ /* Skip whole frame */ ++ if (hc->qh->do_split && (hc->ep_type == FH_OTG_EP_TYPE_ISOC) && ++ hc->ep_is_in && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ break; ++ default: ++ FH_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); ++ break; ++ } ++ if (++qtd->isoc_frame_index == urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers. ++ * The individual frame_desc statuses are used instead. ++ */ ++ hcd->fops->complete(hcd, urb->priv, urb, 0); ++ ret_val = FH_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ ret_val = FH_OTG_HC_XFER_COMPLETE; ++ } ++ return ret_val; ++} ++ ++/** ++ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic ++ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are ++ * still linked to the QH, the QH is added to the end of the inactive ++ * non-periodic schedule. For periodic QHs, removes the QH from the periodic ++ * schedule if no more QTDs are linked to the QH. ++ */ ++static void deactivate_qh(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, int free_qtd) ++{ ++ int continue_split = 0; ++ fh_otg_qtd_t *qtd; ++ ++ FH_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); ++ ++ qtd = FH_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ if (qtd->complete_split) { ++ continue_split = 1; ++ } else if (qtd->isoc_split_pos == FH_HCSPLIT_XACTPOS_MID || ++ qtd->isoc_split_pos == FH_HCSPLIT_XACTPOS_END) { ++ continue_split = 1; ++ } ++ ++ if (free_qtd) { ++ fh_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ continue_split = 0; ++ } ++ ++ qh->channel = NULL; ++ fh_otg_hcd_qh_deactivate(hcd, qh, continue_split); ++} ++ ++/** ++ * Releases a host channel for use by other transfers. Attempts to select and ++ * queue more transactions since at least one host channel is available. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc The host channel to release. ++ * @param qtd The QTD associated with the host channel. This QTD may be freed ++ * if the transfer is complete or an error has occurred. ++ * @param halt_status Reason the channel is being released. This status ++ * determines the actions taken by this function. ++ */ ++static void release_channel(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_qtd_t * qtd, ++ fh_otg_halt_status_e halt_status) ++{ ++ fh_otg_transaction_type_e tr_type; ++ int free_qtd; ++ ++ FH_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n", ++ __func__, hc->hc_num, halt_status); ++ ++ switch (halt_status) { ++ case FH_OTG_HC_XFER_URB_COMPLETE: ++ free_qtd = 1; ++ break; ++ case FH_OTG_HC_XFER_AHB_ERR: ++ case FH_OTG_HC_XFER_STALL: ++ case FH_OTG_HC_XFER_BABBLE_ERR: ++ free_qtd = 1; ++ break; ++ case FH_OTG_HC_XFER_XACT_ERR: ++ if (qtd->error_count >= 3) { ++ FH_DEBUGPL(DBG_HCDV, ++ " Complete URB with transaction error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -FH_E_PROTOCOL; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -FH_E_PROTOCOL); ++ } else { ++ free_qtd = 0; ++ } ++ break; ++ case FH_OTG_HC_XFER_URB_DEQUEUE: ++ /* ++ * The QTD has already been removed and the QH has been ++ * deactivated. Don't want to do anything except release the ++ * host channel and try to queue more transfers. ++ */ ++ goto cleanup; ++ case FH_OTG_HC_XFER_NO_HALT_STATUS: ++ free_qtd = 0; ++ break; ++ case FH_OTG_HC_XFER_PERIODIC_INCOMPLETE: ++ FH_DEBUGPL(DBG_HCDV, ++ " Complete URB with I/O error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -FH_E_IO; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -FH_E_IO); ++ break; ++ default: ++ free_qtd = 0; ++ break; ++ } ++ ++ deactivate_qh(hcd, hc->qh, free_qtd); ++ ++cleanup: ++ /* ++ * Release the host channel for use by other transfers. The cleanup ++ * function clears the channel interrupt enables and conditions, so ++ * there's no need to clear the Channel Halted interrupt separately. ++ */ ++ fh_otg_hc_cleanup(hcd->core_if, hc); ++ FH_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ switch (hc->ep_type) { ++ case FH_OTG_EP_TYPE_CONTROL: ++ case FH_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; ++ ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ ++ /* Try to queue more transfers now that there's a free channel. */ ++ tr_type = fh_otg_hcd_select_transactions(hcd); ++ if (tr_type != FH_OTG_TRANSACTION_NONE) { ++ fh_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++/** ++ * Halts a host channel. If the channel cannot be halted immediately because ++ * the request queue is full, this function ensures that the FIFO empty ++ * interrupt for the appropriate queue is enabled so that the halt request can ++ * be queued when there is space in the request queue. ++ * ++ * This function may also be called in DMA mode. In that case, the channel is ++ * simply released since the core always halts the channel automatically in ++ * DMA mode. ++ */ ++static void halt_channel(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_qtd_t * qtd, fh_otg_halt_status_e halt_status) ++{ ++ if (hcd->core_if->dma_enable) { ++ release_channel(hcd, hc, qtd, halt_status); ++ return; ++ } ++ ++ /* Slave mode processing... */ ++ fh_otg_hc_halt(hcd->core_if, hc, halt_status); ++ ++ if (hc->halt_on_queue) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ fh_otg_core_global_regs_t *global_regs; ++ global_regs = hcd->core_if->core_global_regs; ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == FH_OTG_EP_TYPE_BULK) { ++ /* ++ * Make sure the Non-periodic Tx FIFO empty interrupt ++ * is enabled so that the non-periodic schedule will ++ * be processed. ++ */ ++ gintmsk.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } else { ++ /* ++ * Move the QH from the periodic queued schedule to ++ * the periodic assigned schedule. This allows the ++ * halt to be queued when the periodic schedule is ++ * processed. ++ */ ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &hc->qh->qh_list_entry); ++ ++ /* ++ * Make sure the Periodic Tx FIFO Empty interrupt is ++ * enabled so that the periodic schedule will be ++ * processed. ++ */ ++ gintmsk.b.ptxfempty = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ } ++} ++ ++/** ++ * Performs common cleanup for non-periodic transfers after a Transfer ++ * Complete interrupt. This function should be called after any endpoint type ++ * specific handling is finished to release the host channel. ++ */ ++static void complete_non_periodic_xfer(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd, ++ fh_otg_halt_status_e halt_status) ++{ ++ hcint_data_t hcint; ++ ++ qtd->error_count = 0; ++ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. This ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ hc->qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ /* ++ * Always halt and release the host channel to make it available for ++ * more transfers. There may still be more phases for a control ++ * transfer or more data packets for a bulk transfer at this point, ++ * but the host channel is still halted. A channel will be reassigned ++ * to the transfer when the non-periodic schedule is processed after ++ * the channel is released. This allows transactions to be queued ++ * properly via fh_otg_hcd_queue_transactions, which also enables the ++ * Tx FIFO Empty interrupt if necessary. ++ */ ++ if (hc->ep_is_in) { ++ /* ++ * IN transfers in Slave mode require an explicit disable to ++ * halt the channel. (In DMA mode, this call simply releases ++ * the channel.) ++ */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* ++ * The channel is automatically disabled by the core for OUT ++ * transfers in Slave mode. ++ */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Performs common cleanup for periodic transfers after a Transfer Complete ++ * interrupt. This function should be called after any endpoint type specific ++ * handling is finished to release the host channel. ++ */ ++static void complete_periodic_xfer(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd, ++ fh_otg_halt_status_e halt_status) ++{ ++ hctsiz_data_t hctsiz; ++ qtd->error_count = 0; ++ ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { ++ /* Core halts channel in these cases. */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* Flush any outstanding requests from the Tx queue. */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++static int32_t handle_xfercomp_isoc_split_in(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ uint32_t len; ++ struct fh_otg_hcd_iso_packet_desc *frame_desc; ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ ++ len = get_actual_xfer_length(hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_COMPLETE, NULL); ++ ++ if (!len) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ return 0; ++ } ++ frame_desc->actual_length += len; ++ ++ if (hc->align_buff && len) ++ fh_memcpy(qtd->urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); ++ qtd->isoc_split_offset += len; ++ ++ if (frame_desc->length == frame_desc->actual_length) { ++ frame_desc->status = 0; ++ qtd->isoc_frame_index++; ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, FH_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ ++ return 1; /* Indicates that channel released */ ++} ++ ++/** ++ * Handles a host channel Transfer Complete interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xfercomp_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ int urb_xfer_done; ++ fh_otg_halt_status_e halt_status = FH_OTG_HC_XFER_COMPLETE; ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = fh_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transfer Complete--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ if (pipe_type == UE_ISOCHRONOUS) { ++ /* Do not disable the interrupt, just clear it */ ++ clear_hc_int(hc_regs, xfercomp); ++ return 1; ++ } ++ goto handle_xfercomp_done; ++ } ++ ++ /* ++ * Handle xfer complete on CSPLIT. ++ */ ++ ++ if (hc->qh->do_split) { ++ if ((hc->ep_type == FH_OTG_EP_TYPE_ISOC) && hc->ep_is_in ++ && hcd->core_if->dma_enable) { ++ if (qtd->complete_split ++ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, ++ qtd)) ++ goto handle_xfercomp_done; ++ } else { ++ qtd->complete_split = 0; ++ } ++ } ++ ++ /* Update the QTD and URB states. */ ++ switch (pipe_type) { ++ case UE_CONTROL: ++ switch (qtd->control_phase) { ++ case FH_OTG_CONTROL_SETUP: ++ if (urb->length > 0) { ++ qtd->control_phase = FH_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = FH_OTG_CONTROL_STATUS; ++ } ++ FH_DEBUGPL(DBG_HCDV, ++ " Control setup transaction done\n"); ++ halt_status = FH_OTG_HC_XFER_COMPLETE; ++ break; ++ case FH_OTG_CONTROL_DATA:{ ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, ++ qtd); ++ if (urb_xfer_done) { ++ qtd->control_phase = ++ FH_OTG_CONTROL_STATUS; ++ FH_DEBUGPL(DBG_HCDV, ++ " Control data transfer done\n"); ++ } else { ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ halt_status = FH_OTG_HC_XFER_COMPLETE; ++ break; ++ } ++ case FH_OTG_CONTROL_STATUS: ++ FH_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); ++ if (urb->status == -FH_E_IN_PROGRESS) { ++ urb->status = 0; ++ } ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = FH_OTG_HC_XFER_URB_COMPLETE; ++ if (!hcd->core_if->dma_enable && hcd->core_if->otg_ver == 1) ++ qtd->urb = NULL; ++ break; ++ } ++ ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_BULK: ++ FH_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = FH_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = FH_OTG_HC_XFER_COMPLETE; ++ } ++ ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_INTERRUPT: ++ FH_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ ++ /* ++ * Interrupt URB is done on the first transfer complete ++ * interrupt. ++ */ ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = FH_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = FH_OTG_HC_XFER_COMPLETE; ++ } ++ ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_ISOCHRONOUS: ++ FH_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); ++ if (qtd->isoc_split_pos == FH_HCSPLIT_XACTPOS_ALL) { ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_COMPLETE); ++ } ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ } ++ ++handle_xfercomp_done: ++ disable_hc_int(hc_regs, xfercompl); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel STALL interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_stall_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = fh_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "STALL Received--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, FH_OTG_HC_XFER_STALL); ++ goto handle_stall_done; ++ } ++ ++ if (pipe_type == UE_CONTROL) { ++ hcd->fops->complete(hcd, urb->priv, urb, -FH_E_PIPE); ++ } ++ ++ if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) { ++ hcd->fops->complete(hcd, urb->priv, urb, -FH_E_PIPE); ++ /* ++ * USB protocol requires resetting the data toggle for bulk ++ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) ++ * setup command is issued to the endpoint. Anticipate the ++ * CLEAR_FEATURE command since a STALL has occurred and reset ++ * the data toggle now. ++ */ ++ hc->qh->data_toggle = 0; ++ } ++ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_STALL); ++ ++handle_stall_done: ++ disable_hc_int(hc_regs, stall); ++ ++ return 1; ++} ++ ++/* ++ * Updates the state of the URB when a transfer has been stopped due to an ++ * abnormal condition before the transfer completes. Modifies the ++ * actual_length field of the URB to reflect the number of bytes that have ++ * actually been transferred via the host channel. ++ */ ++static void update_urb_state_xfer_intr(fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_hcd_urb_t * urb, ++ fh_otg_qtd_t * qtd, ++ fh_otg_halt_status_e halt_status) ++{ ++ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && bytes_transferred && hc->ep_is_in) { ++ fh_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ bytes_transferred); ++ } ++ ++ urb->actual_length += bytes_transferred; ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ FH_DEBUGPL(DBG_HCDV, "FH_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ FH_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", ++ hc->start_pkt_count); ++ FH_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); ++ FH_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); ++ FH_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", ++ bytes_transferred); ++ FH_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ FH_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ } ++#endif ++} ++ ++/** ++ * Handles a host channel NAK interrupt. This handler may be called in either ++ * DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nak_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NAK Received--\n", hc->hc_num); ++ ++ /* ++ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and ++ * interrupt. Re-start the SSPLIT transfer. ++ */ ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ qtd->error_count = 0; ++ } ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NAK); ++ goto handle_nak_done; ++ } ++ ++ switch (fh_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ if (hcd->core_if->dma_enable && hc->ep_is_in) { ++ /* ++ * NAK interrupts are enabled on bulk/control IN ++ * transfers in DMA mode for the sole purpose of ++ * resetting the error count after a transaction error ++ * occurs. The core will continue transferring data. ++ */ ++ qtd->error_count = 0; ++ goto handle_nak_done; ++ } ++ ++ /* ++ * NAK interrupts normally occur during OUT transfers in DMA ++ * or Slave mode. For IN transfers, more requests will be ++ * queued as request queue space is available. ++ */ ++ qtd->error_count = 0; ++ ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ FH_OTG_HC_XFER_NAK); ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ if (hc->speed == FH_OTG_EP_SPEED_HIGH) ++ hc->qh->ping_state = 1; ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will ++ * start/continue. ++ */ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NAK); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count = 0; ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NAK); ++ break; ++ case UE_ISOCHRONOUS: ++ /* Should never get called for isochronous transfers. */ ++ FH_ASSERT(1, "NACK interrupt for ISOC transfer\n"); ++ break; ++ } ++ ++handle_nak_done: ++ disable_hc_int(hc_regs, nak); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel ACK interrupt. This interrupt is enabled when ++ * performing the PING protocol in Slave mode, when errors occur during ++ * either Slave mode or DMA mode, and during Start Split transactions. ++ */ ++static int32_t handle_hc_ack_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "ACK Received--\n", hc->hc_num); ++ ++ if (hc->do_split) { ++ /* ++ * Handle ACK on SSPLIT. ++ * ACK should not occur in CSPLIT. ++ */ ++ if (!hc->ep_is_in && hc->data_pid_start != FH_OTG_HC_PID_SETUP) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (!(hc->ep_type == FH_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { ++ /* Don't need complete for isochronous out transfers. */ ++ qtd->complete_split = 1; ++ } ++ ++ /* ISOC OUT */ ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ switch (hc->xact_pos) { ++ case FH_HCSPLIT_XACTPOS_ALL: ++ break; ++ case FH_HCSPLIT_XACTPOS_END: ++ qtd->isoc_split_pos = FH_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ break; ++ case FH_HCSPLIT_XACTPOS_BEGIN: ++ case FH_HCSPLIT_XACTPOS_MID: ++ /* ++ * For BEGIN or MID, calculate the length for ++ * the next microframe to determine the correct ++ * SSPLIT token, either MID or END. ++ */ ++ { ++ struct fh_otg_hcd_iso_packet_desc ++ *frame_desc; ++ ++ frame_desc = ++ &qtd->urb-> ++ iso_descs[qtd->isoc_frame_index]; ++ qtd->isoc_split_offset += 188; ++ ++ if ((frame_desc->length - ++ qtd->isoc_split_offset) <= 188) { ++ qtd->isoc_split_pos = ++ FH_HCSPLIT_XACTPOS_END; ++ } else { ++ qtd->isoc_split_pos = ++ FH_HCSPLIT_XACTPOS_MID; ++ } ++ ++ } ++ break; ++ } ++ } else { ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_ACK); ++ } ++ } else { ++ qtd->error_count = 0; ++ ++ if (hc->qh->ping_state) { ++ hc->qh->ping_state = 0; ++ /* ++ * Halt the channel so the transfer can be re-started ++ * from the appropriate point. This only happens in ++ * Slave mode. In DMA mode, the ping_state is cleared ++ * when the transfer is started because the core ++ * automatically executes the PING, then the transfer. ++ */ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_ACK); ++ } ++ } ++ ++ /* ++ * If the ACK occurred when _not_ in the PING state, let the channel ++ * continue transferring data after clearing the error count. ++ */ ++ ++ disable_hc_int(hc_regs, ack); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel NYET interrupt. This interrupt should only occur on ++ * Bulk and Control OUT endpoints and for complete split transactions. If a ++ * NYET occurs at the same time as a Transfer Complete interrupt, it is ++ * handled in the xfercomp interrupt handler, not here. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nyet_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "NYET Received--\n", hc->hc_num); ++ ++ /* ++ * NYET on CSPLIT ++ * re-do the CSPLIT immediately on non-periodic ++ */ ++ if (hc->do_split && hc->complete_split) { ++ if (hc->ep_is_in && (hc->ep_type == FH_OTG_EP_TYPE_ISOC) ++ && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, FH_OTG_HC_XFER_URB_COMPLETE); ++ } ++ else ++ release_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NO_HALT_STATUS); ++ goto handle_nyet_done; ++ } ++ ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ int frnum = fh_otg_hcd_get_frame_number(hcd); ++ ++ if (fh_full_frame_num(frnum) != ++ fh_full_frame_num(hc->qh->sched_frame)) { ++ /* ++ * No longer in the same full speed frame. ++ * Treat this as a transaction error. ++ */ ++#if 0 ++ /** @todo Fix system performance so this can ++ * be treated as an error. Right now complete ++ * splits cannot be scheduled precisely enough ++ * due to other system activity, so this error ++ * occurs regularly in Slave mode. ++ */ ++ qtd->error_count++; ++#endif ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, ++ FH_OTG_HC_XFER_XACT_ERR); ++ /** @todo add support for isoc release */ ++ goto handle_nyet_done; ++ } ++ } ++ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NYET); ++ goto handle_nyet_done; ++ } ++ ++ hc->qh->ping_state = 1; ++ qtd->error_count = 0; ++ ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, ++ FH_OTG_HC_XFER_NYET); ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ /* ++ * Halt the channel and re-start the transfer so the PING ++ * protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_NYET); ++ ++handle_nyet_done: ++ disable_hc_int(hc_regs, nyet); ++ return 1; ++} ++ ++/** ++ * Handles a host channel babble interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_babble_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Babble Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ FH_OTG_HC_XFER_BABBLE_ERR); ++ goto handle_babble_done; ++ } ++ ++ if (hc->ep_type != FH_OTG_EP_TYPE_ISOC) { ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -FH_E_OVERFLOW); ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_BABBLE_ERR); ++ } else { ++ fh_otg_halt_status_e halt_status; ++ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_BABBLE_ERR); ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ ++handle_babble_done: ++ disable_hc_int(hc_regs, bblerr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel AHB error interrupt. This handler is only called in ++ * DMA mode. ++ */ ++static int32_t handle_hc_ahberr_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ char *pipetype, *speed; ++ ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "AHB Error--\n", hc->hc_num); ++ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = FH_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ hcdma = FH_READ_REG32(&hc_regs->hcdma); ++ ++ FH_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); ++ FH_ERROR("AHB ERROR, Xfer size %d\n", hc->xfer_len); ++ FH_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); ++ FH_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD URB Enqueue\n"); ++ FH_ERROR(" Device address: %d\n", ++ fh_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ FH_ERROR(" Endpoint: %d, %s\n", ++ fh_otg_hcd_get_ep_num(&urb->pipe_info), ++ (fh_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); ++ ++ switch (fh_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case UE_BULK: ++ pipetype = "BULK"; ++ break; ++ case UE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case UE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ ++ FH_ERROR(" Endpoint type: %s\n", pipetype); ++ ++ switch (hc->speed) { ++ case FH_OTG_EP_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case FH_OTG_EP_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case FH_OTG_EP_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ }; ++ ++ FH_ERROR(" Speed: %s\n", speed); ++ ++ FH_ERROR(" Max packet size: %d\n", ++ fh_otg_hcd_get_mps(&urb->pipe_info)); ++ FH_ERROR(" Data buffer length: %d\n", urb->length); ++ FH_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->buf, (void *)urb->dma); ++ FH_ERROR(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ FH_ERROR(" Interval: %d\n", urb->interval); ++ ++ /* Core haltes the channel for Descriptor DMA mode */ ++ if (hcd->core_if->dma_desc_enable) { ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ FH_OTG_HC_XFER_AHB_ERR); ++ goto handle_ahberr_done; ++ } ++ ++ hcd->fops->complete(hcd, urb->priv, urb, -FH_E_IO); ++ ++ /* ++ * Force a channel halt. Don't call halt_channel because that won't ++ * write to the HCCHARn register in DMA mode to force the halt. ++ */ ++ fh_otg_hc_halt(hcd->core_if, hc, FH_OTG_HC_XFER_AHB_ERR); ++handle_ahberr_done: ++ disable_hc_int(hc_regs, ahberr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel transaction error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xacterr_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Transaction Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ FH_OTG_HC_XFER_XACT_ERR); ++ goto handle_xacterr_done; ++ } ++ ++ switch (fh_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ qtd->error_count++; ++ if (!hc->qh->ping_state) { ++ ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ FH_OTG_HC_XFER_XACT_ERR); ++ fh_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ if (!hc->ep_is_in && hc->speed == FH_OTG_EP_SPEED_HIGH) { ++ hc->qh->ping_state = 1; ++ } ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count++; ++ if (hc->do_split && hc->complete_split) { ++ qtd->complete_split = 0; ++ } ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ fh_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_XACT_ERR); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++handle_xacterr_done: ++ disable_hc_int(hc_regs, xacterr); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel frame overrun interrupt. This handler may be called ++ * in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_frmovrun_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Frame Overrun--\n", hc->hc_num); ++ ++ switch (fh_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ break; ++ case UE_INTERRUPT: ++ halt_channel(hcd, hc, qtd, FH_OTG_HC_XFER_FRAME_OVERRUN); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ fh_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ FH_OTG_HC_XFER_FRAME_OVERRUN); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++ ++ disable_hc_int(hc_regs, frmovrun); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel data toggle error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_datatglerr_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Data Toggle Error--\n", hc->hc_num); ++ ++ if (hc->ep_is_in) { ++ qtd->error_count = 0; ++ } else { ++ FH_ERROR("Data Toggle Error on OUT transfer," ++ "channel %d\n", hc->hc_num); ++ } ++ ++ disable_hc_int(hc_regs, datatglerr); ++ ++ return 1; ++} ++ ++#ifdef DEBUG ++/** ++ * This function is for debug only. It checks that a valid halt status is set ++ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is ++ * taken and a warning is issued. ++ * @return 1 if halt status is ok, 0 otherwise. ++ */ ++static inline int halt_status_ok(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hcsplt_data_t hcsplt; ++ ++ if (hc->halt_status == FH_OTG_HC_XFER_NO_HALT_STATUS) { ++ /* ++ * This code is here only as a check. This condition should ++ * never happen. Ignore the halt if it does occur. ++ */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ hctsiz.d32 = FH_READ_REG32(&hc_regs->hctsiz); ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = FH_READ_REG32(&hc_regs->hcintmsk); ++ hcsplt.d32 = FH_READ_REG32(&hc_regs->hcsplt); ++ FH_WARN ++ ("%s: hc->halt_status == FH_OTG_HC_XFER_NO_HALT_STATUS, " ++ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " ++ "hcint 0x%08x, hcintmsk 0x%08x, " ++ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, ++ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, ++ hcintmsk.d32, hcsplt.d32, qtd->complete_split); ++ ++ FH_WARN("%s: no halt status, channel %d, ignoring interrupt\n", ++ __func__, hc->hc_num); ++ FH_WARN("\n"); ++ clear_hc_int(hc_regs, chhltd); ++ return 0; ++ } ++ ++ /* ++ * This code is here only as a check. hcchar.chdis should ++ * never be set when the halt interrupt occurs. Halt the ++ * channel again if it does occur. ++ */ ++ hcchar.d32 = FH_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ FH_WARN("%s: hcchar.chdis set unexpectedly, " ++ "hcchar 0x%08x, trying to halt again\n", ++ __func__, hcchar.d32); ++ clear_hc_int(hc_regs, chhltd); ++ hc->halt_pending = 0; ++ halt_channel(hcd, hc, qtd, hc->halt_status); ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/** ++ * Handles a host Channel Halted interrupt in DMA mode. This handler ++ * determines the reason the channel halted and proceeds accordingly. ++ */ ++static void handle_hc_chhltd_intr_dma(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ int out_nak_enh = 0; ++ ++ /* For core with OUT NAK enhancement, the flow for high- ++ * speed CONTROL/BULK OUT is handled a little differently. ++ */ ++ if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) { ++ if (hc->speed == FH_OTG_EP_SPEED_HIGH && !hc->ep_is_in && ++ (hc->ep_type == FH_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == FH_OTG_EP_TYPE_BULK)) { ++ out_nak_enh = 1; ++ } ++ } ++ ++ if (hc->halt_status == FH_OTG_HC_XFER_URB_DEQUEUE || ++ (hc->halt_status == FH_OTG_HC_XFER_AHB_ERR ++ && !hcd->core_if->dma_desc_enable)) { ++ /* ++ * Just release the channel. A dequeue can happen on a ++ * transfer timeout. In the case of an AHB Error, the channel ++ * was forced to halt because there's no way to gracefully ++ * recover. ++ */ ++ if (hcd->core_if->dma_desc_enable) ++ fh_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ hc->halt_status); ++ else ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ return; ++ } ++ ++ /* Read the HCINTn register to determine the cause for the halt. */ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = FH_READ_REG32(&hc_regs->hcintmsk); ++ ++ if (hcint.b.xfercomp) { ++ /** @todo This is here because of a possible hardware bug. Spec ++ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT ++ * interrupt w/ACK bit set should occur, but I only see the ++ * XFERCOMP bit, even with it masked out. This is a workaround ++ * for that behavior. Should fix this when hardware is fixed. ++ */ ++ if (hc->ep_type == FH_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { ++ if (out_nak_enh) { ++ if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { ++ FH_DEBUG("XactErr with NYET/NAK/ACK\n"); ++ qtd->error_count = 0; ++ } else { ++ FH_DEBUG("XactErr without NYET/NAK/ACK\n"); ++ } ++ } ++ ++ /* ++ * Must handle xacterr before nak or ack. Could get a xacterr ++ * at the same time as either of these on a BULK/CONTROL OUT ++ * that started with a PING. The xacterr takes precedence. ++ */ ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.bblerr) { ++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.frmovrun) { ++ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); ++ } else if (!out_nak_enh) { ++ if (hcint.b.nyet) { ++ /* ++ * Must handle nyet before nak or ack. Could get a nyet at the ++ * same time as either of those on a BULK/CONTROL OUT that ++ * started with a PING. The nyet takes precedence. ++ */ ++ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak && !hcintmsk.b.nak) { ++ /* ++ * If nak is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the nak is handled by ++ * the nak interrupt handler, not here. Handle nak here for ++ * BULK/CONTROL OUT transfers, which halt on a NAK to allow ++ * rewinding the buffer pointer. ++ */ ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ack && !hcintmsk.b.ack) { ++ /* ++ * If ack is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the ack is handled by ++ * the ack interrupt handler, not here. Handle ack here for ++ * split transfers. Start splits halt on ACK. ++ */ ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ if (hc->ep_type == FH_OTG_EP_TYPE_INTR || ++ hc->ep_type == FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * A periodic transfer halted with no other channel ++ * interrupts set. Assume it was halted by the core ++ * because it could not be completed in its scheduled ++ * (micro)frame. ++ */ ++#ifdef DEBUG ++ FH_PRINTF ++ ("%s: Halt channel %d (assume incomplete periodic transfer)\n", ++ __func__, hc->hc_num); ++#endif ++ halt_channel(hcd, hc, qtd, ++ FH_OTG_HC_XFER_PERIODIC_INCOMPLETE); ++ } else { ++ FH_ERROR ++ ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " ++ "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", ++ __func__, hc->hc_num, hcint.d32, ++ FH_READ_REG32(&hcd-> ++ core_if->core_global_regs-> ++ gintsts)); ++ disable_hc_int(hc_regs, chhltd); ++ } ++ ++ } ++ } else { ++ FH_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", ++ hcint.d32); ++ disable_hc_int(hc_regs, chhltd); ++ } ++} ++ ++/** ++ * Handles a host channel Channel Halted interrupt. ++ * ++ * In slave mode, this handler is called only when the driver specifically ++ * requests a halt. This occurs during handling other host channel interrupts ++ * (e.g. nak, xacterr, stall, nyet, etc.). ++ * ++ * In DMA mode, this is the interrupt that occurs when the core has finished ++ * processing a transfer on a channel. Other host channel interrupts (except ++ * ahberr) are disabled in DMA mode. ++ */ ++static int32_t handle_hc_chhltd_intr(fh_otg_hcd_t * hcd, ++ fh_hc_t * hc, ++ fh_otg_hc_regs_t * hc_regs, ++ fh_otg_qtd_t * qtd) ++{ ++ FH_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "Channel Halted--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_enable) { ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ } else { ++#ifdef DEBUG ++ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { ++ return 1; ++ } ++#endif ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ } ++ ++ return 1; ++} ++ ++/** Handles interrupt for a specific Host Channel */ ++int32_t fh_otg_hcd_handle_hc_n_intr(fh_otg_hcd_t * fh_otg_hcd, uint32_t num) ++{ ++ int retval = 0; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ fh_hc_t *hc; ++ fh_otg_hc_regs_t *hc_regs; ++ fh_otg_qtd_t *qtd; ++ ++ FH_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); ++ ++ hc = fh_otg_hcd->hc_ptr_array[num]; ++ hc_regs = fh_otg_hcd->core_if->host_if->hc_regs[num]; ++ qtd = FH_CIRCLEQ_FIRST(&hc->qh->qtd_list); ++ ++ hcint.d32 = FH_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = FH_READ_REG32(&hc_regs->hcintmsk); ++ FH_DEBUGPL(DBG_HCDV, ++ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", ++ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); ++ hcint.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (!fh_otg_hcd->core_if->dma_enable) { ++ if (hcint.b.chhltd && hcint.d32 != 0x2) { ++ hcint.b.chhltd = 0; ++ } ++ } ++ ++ if (hcint.b.xfercomp) { ++ retval |= ++ handle_hc_xfercomp_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ /* ++ * If NYET occurred at same time as Xfer Complete, the NYET is ++ * handled by the Xfer Complete interrupt handler. Don't want ++ * to call the NYET interrupt handler in this case. ++ */ ++ hcint.b.nyet = 0; ++ } ++ if (hcint.b.chhltd) { ++ retval |= handle_hc_chhltd_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ahberr) { ++ retval |= handle_hc_ahberr_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.stall) { ++ retval |= handle_hc_stall_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nak) { ++ retval |= handle_hc_nak_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ack) { ++ retval |= handle_hc_ack_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nyet) { ++ retval |= handle_hc_nyet_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.xacterr) { ++ retval |= handle_hc_xacterr_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.bblerr) { ++ retval |= handle_hc_babble_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.frmovrun) { ++ retval |= ++ handle_hc_frmovrun_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.datatglerr) { ++ retval |= ++ handle_hc_datatglerr_intr(fh_otg_hcd, hc, hc_regs, qtd); ++ } ++ ++ return retval; ++} ++ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_linux.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_linux.c +new file mode 100755 +index 00000000..01ffd025 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_linux.c +@@ -0,0 +1,873 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd_linux.c $ ++ * $Revision: #25 $ ++ * $Date: 2015/09/08 $ ++ * $Change: 2943025 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the implementation of the HCD. In Linux, the HCD ++ * implements the hc_driver API. ++ */ ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/errno.h> ++#include <linux/list.h> ++#include <linux/interrupt.h> ++#include <linux/string.h> ++#include <linux/dma-mapping.h> ++#include <linux/version.h> ++#include <asm/io.h> ++#include <linux/usb.h> ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include <../drivers/usb/core/hcd.h> ++#else ++#include <linux/usb/hcd.h> ++#endif ++ ++#include "fh_otg_hcd_if.h" ++#include "fh_otg_dbg.h" ++#include "fh_otg_driver.h" ++#include "fh_otg_hcd.h" ++/** ++ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is ++ * qualified with its direction (possible 32 endpoints per device). ++ */ ++#define fh_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ ++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) ++ ++static const char fh_otg_hcd_name[] = "fh_otg_hcd"; ++ ++/** @name Linux HC Driver API Functions */ ++/** @{ */ ++static int urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); ++#endif ++ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#endif ++static irqreturn_t fh_otg_hcd_irq(struct usb_hcd *hcd); ++extern int hcd_start(struct usb_hcd *hcd); ++extern void hcd_stop(struct usb_hcd *hcd); ++static int get_frame_number(struct usb_hcd *hcd); ++extern int hub_status_data(struct usb_hcd *hcd, char *buf); ++extern int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, ++ u16 wValue, u16 wIndex, char *buf, u16 wLength); ++ ++struct wrapper_priv_data { ++ fh_otg_hcd_t *fh_otg_hcd; ++}; ++ ++/** @} */ ++ ++static struct hc_driver fh_otg_hc_driver = { ++ ++ .description = fh_otg_hcd_name, ++ .product_desc = "FH OTG Controller", ++ .hcd_priv_size = sizeof(struct wrapper_priv_data), ++ ++ .irq = fh_otg_hcd_irq, ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,12,0) ++ .flags = HCD_MEMORY | HCD_USB2, ++#else ++ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, ++#endif ++ ++ ++ .start = hcd_start, ++ .stop = hcd_stop, ++ ++ .urb_enqueue = urb_enqueue, ++ .urb_dequeue = urb_dequeue, ++ .endpoint_disable = endpoint_disable, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ .endpoint_reset = endpoint_reset, ++#endif ++ .get_frame_number = get_frame_number, ++ ++ .hub_status_data = hub_status_data, ++ .hub_control = hub_control, ++ //.bus_suspend = ++ //.bus_resume = ++}; ++ ++/** Gets the fh_otg_hcd from a struct usb_hcd */ ++static inline fh_otg_hcd_t *hcd_to_fh_otg_hcd(struct usb_hcd *hcd) ++{ ++ struct wrapper_priv_data *p; ++ p = (struct wrapper_priv_data *)(hcd->hcd_priv); ++ return p->fh_otg_hcd; ++} ++ ++/** Gets the struct usb_hcd that contains a fh_otg_hcd_t. */ ++static inline struct usb_hcd *fh_otg_hcd_to_hcd(fh_otg_hcd_t * fh_otg_hcd) ++{ ++ return fh_otg_hcd_get_priv_data(fh_otg_hcd); ++} ++ ++/** Gets the usb_host_endpoint associated with an URB. */ ++inline struct usb_host_endpoint *fh_urb_to_endpoint(struct urb *urb) ++{ ++ struct usb_device *dev = urb->dev; ++ int ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (usb_pipein(urb->pipe)) ++ return dev->ep_in[ep_num]; ++ else ++ return dev->ep_out[ep_num]; ++} ++ ++static int _disconnect(fh_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = fh_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = 0; ++ return 0; ++} ++ ++static int _start(fh_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = fh_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = fh_otg_hcd_is_b_host(hcd); ++ hcd_start(usb_hcd); ++ ++ return 0; ++} ++ ++static int _hub_info(fh_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, ++ uint32_t * port_addr) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ if (urb->dev->tt) { ++ *hub_addr = urb->dev->tt->hub->devnum; ++ } else { ++ *hub_addr = 0; ++ } ++ *port_addr = urb->dev->ttport; ++ return 0; ++} ++ ++static int _speed(fh_otg_hcd_t * hcd, void *urb_handle) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ return urb->dev->speed; ++} ++ ++static int _get_b_hnp_enable(fh_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = fh_otg_hcd_to_hcd(hcd); ++ return usb_hcd->self.b_hnp_enable; ++} ++ ++static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs++; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs++; ++ } ++} ++ ++static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs--; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs--; ++ } ++} ++ ++/** ++ * Sets the final status of an URB and returns it to the device driver. Any ++ * required cleanup of the URB is performed. ++ */ ++static int _complete(fh_otg_hcd_t * hcd, void *urb_handle, ++ fh_otg_hcd_urb_t * fh_otg_urb, int32_t status) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ FH_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", ++ __func__, urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT", status); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ FH_PRINTF(" ISO Desc %d status: %d\n", ++ i, urb->iso_frame_desc[i].status); ++ } ++ } ++ } ++#endif ++ ++ urb->actual_length = fh_otg_hcd_urb_get_actual_length(fh_otg_urb); ++ /* Convert status value. */ ++ switch (status) { ++ case -FH_E_PROTOCOL: ++ status = -EPROTO; ++ break; ++ case -FH_E_IN_PROGRESS: ++ status = -EINPROGRESS; ++ break; ++ case -FH_E_PIPE: ++ status = -EPIPE; ++ break; ++ case -FH_E_IO: ++ status = -EIO; ++ break; ++ case -FH_E_TIMEOUT: ++ status = -ETIMEDOUT; ++ break; ++ case -FH_E_OVERFLOW: ++ status = -EOVERFLOW; ++ break; ++ default: ++ if (status) { ++ FH_PRINTF("Uknown urb status %d\n", status); ++ ++ } ++ } ++ ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ ++ urb->error_count = fh_otg_hcd_urb_get_error_count(fh_otg_urb); ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ urb->iso_frame_desc[i].actual_length = ++ fh_otg_hcd_urb_get_iso_desc_actual_length ++ (fh_otg_urb, i); ++ urb->iso_frame_desc[i].status = ++ fh_otg_hcd_urb_get_iso_desc_status(fh_otg_urb, i); ++ } ++ } ++ ++ urb->status = status; ++ if (!status) { ++ if ((urb->transfer_flags & URB_SHORT_NOT_OK) && ++ (urb->actual_length < urb->transfer_buffer_length)) { ++ urb->status = -EREMOTEIO; ++ } ++ } ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) || ++ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ struct usb_host_endpoint *ep = fh_urb_to_endpoint(urb); ++ if (ep) { ++ free_bus_bandwidth(fh_otg_hcd_to_hcd(hcd), ++ fh_otg_hcd_get_ep_bandwidth(hcd, ++ ep->hcpriv), ++ urb); ++ } ++ } ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,7) ++ usb_hcd_unlink_urb_from_ep(fh_otg_hcd_to_hcd(hcd), urb); ++#endif ++ ++ urb->hcpriv = NULL; ++ FH_FREE(fh_otg_urb); ++ ++ //printk("\nfuck...\n"); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ FH_SPINUNLOCK(hcd->lock); ++ usb_hcd_giveback_urb(fh_otg_hcd_to_hcd(hcd), urb); ++ FH_SPINLOCK(hcd->lock); ++#elseif LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,7) ++ FH_SPINUNLOCK(hcd->lock); ++ usb_hcd_giveback_urb(fh_otg_hcd_to_hcd(hcd), urb, status); ++ FH_SPINLOCK(hcd->lock); ++#else ++ usb_hcd_giveback_urb(fh_otg_hcd_to_hcd(hcd), urb, status); ++#endif ++ ++ return 0; ++} ++ ++static struct fh_otg_hcd_function_ops hcd_fops = { ++ .start = _start, ++ .disconnect = _disconnect, ++ .hub_info = _hub_info, ++ .speed = _speed, ++ .complete = _complete, ++ .get_b_hnp_enable = _get_b_hnp_enable, ++}; ++ ++/** ++ * Initializes the HCD. This function allocates memory for and initializes the ++ * static parts of the usb_hcd and fh_otg_hcd structures. It also registers the ++ * USB bus with the core and calls the hc_driver->start() function. It returns ++ * a negative error on failure. ++ */ ++int hcd_init(struct platform_device *dev, int irq) ++{ ++ struct usb_hcd *hcd = NULL; ++ fh_otg_hcd_t *fh_otg_hcd = NULL; ++ fh_otg_device_t *otg_dev = platform_get_drvdata(dev); ++ ++ int retval = 0; ++ ++ printk(KERN_ERR "FH OTG HCD INIT (%p)\n", otg_dev); ++ ++ /* Set device flags indicating whether the HCD supports DMA */ ++ if (otg_dev->core_if->dma_enable > 0) { ++ if (dma_set_mask(&dev->dev, DMA_BIT_MASK(32)) < 0) ++ printk(KERN_ERR "can't set DMA mask\n"); ++ if (dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)) < 0) ++ printk(KERN_ERR "can't set coherent DMA mask\n"); ++ } ++ ++ /* ++ * Allocate memory for the base HCD plus the FH OTG HCD. ++ * Initialize the base HCD. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ hcd = usb_create_hcd(&fh_otg_hc_driver, &dev->dev, dev->dev.bus_id); ++#else ++ hcd = usb_create_hcd(&fh_otg_hc_driver, &dev->dev, dev_name(&dev->dev)); ++ ++ hcd->has_tt = 1; ++// hcd->uses_new_polling = 1; ++// hcd->poll_rh = 0; ++#endif ++ if (!hcd) { ++ retval = -ENOMEM; ++ goto error1; ++ } ++ ++ printk(KERN_ERR "hcd regs before base(%p)\n", otg_dev->os_dep.base); ++ hcd->regs = otg_dev->os_dep.base; ++ ++ /* Initialize the FH OTG HCD. */ ++ fh_otg_hcd = fh_otg_hcd_alloc_hcd(); ++ if (!fh_otg_hcd) { ++ goto error2; ++ } ++ ((struct wrapper_priv_data *)(hcd->hcd_priv))->fh_otg_hcd = ++ fh_otg_hcd; ++ otg_dev->hcd = fh_otg_hcd; ++ ++ if (fh_otg_hcd_init(fh_otg_hcd, otg_dev->core_if)) { ++ goto error2; ++ } ++ ++ otg_dev->hcd->otg_dev = otg_dev; ++ hcd->self.otg_port = fh_otg_hcd_otg_port(fh_otg_hcd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ++ //hcd->self.otg_version = fh_otg_get_otg_version(otg_dev->core_if); ++ /* Don't support SG list at this point */ ++ hcd->self.sg_tablesize = 0; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ /* Do not to do HNP polling if not capable */ ++ if (otg_dev->core_if->otg_ver) ++ hcd->self.is_hnp_cap = fh_otg_get_hnpcapable(otg_dev->core_if); ++#endif ++ /* ++ * Finish generic HCD initialization and start the HCD. This function ++ * allocates the DMA buffer pool, registers the USB bus, requests the ++ * IRQ line, and calls hcd_start method. ++ */ ++ retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); ++ if (retval < 0) { ++ goto error2; ++ } ++ ++ fh_otg_hcd_set_priv_data(fh_otg_hcd, hcd); ++ platform_set_drvdata(dev, otg_dev); ++ return 0; ++ ++error2: ++ usb_put_hcd(hcd); ++error1: ++ return retval; ++} ++ ++/** ++ * Removes the HCD. ++ * Frees memory and resources associated with the HCD and deregisters the bus. ++ */ ++void hcd_remove(struct platform_device *dev) ++{ ++ fh_otg_device_t *otg_dev = platform_get_drvdata(dev); ++ ++ ++ fh_otg_hcd_t *fh_otg_hcd; ++ struct usb_hcd *hcd; ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD REMOVE\n"); ++ ++ if (!otg_dev) { ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return; ++ } ++ ++ fh_otg_hcd = otg_dev->hcd; ++ ++ if (!fh_otg_hcd) { ++ FH_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ return; ++ } ++ ++ hcd = fh_otg_hcd_to_hcd(fh_otg_hcd); ++ ++ if (!hcd) { ++ FH_DEBUGPL(DBG_ANY, ++ "%s: fh_otg_hcd_to_hcd(fh_otg_hcd) NULL!\n", ++ __func__); ++ return; ++ } ++ usb_remove_hcd(hcd); ++ fh_otg_hcd_set_priv_data(fh_otg_hcd, NULL); ++ fh_otg_hcd_remove(fh_otg_hcd); ++ usb_put_hcd(hcd); ++} ++ ++/* ========================================================================= ++ * Linux HC Driver Functions ++ * ========================================================================= */ ++ ++/** Initializes the FH_otg controller and its root hub and prepares it for host ++ * mode operation. Activates the root port. Returns 0 on success and a negative ++ * error code on failure. */ ++int hcd_start(struct usb_hcd *hcd) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ struct usb_bus *bus; ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD START\n"); ++ bus = hcd_to_bus(hcd); ++ ++ hcd->state = HC_STATE_RUNNING; ++ if (fh_otg_hcd_start(fh_otg_hcd, &hcd_fops)) { ++ if (fh_otg_hcd->core_if->otg_ver && fh_otg_is_device_mode(fh_otg_hcd->core_if)) ++ fh_otg_hcd->core_if->op_state = B_PERIPHERAL; ++ return 0; ++ } ++ ++ /* Initialize and connect root hub if one is not already attached */ ++ if (bus->root_hub) { ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD Has Root Hub\n"); ++ /* Inform the HUB driver to resume. */ ++ usb_hcd_resume_root_hub(hcd); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Halts the FH_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void hcd_stop(struct usb_hcd *hcd) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ ++ fh_otg_hcd_stop(fh_otg_hcd); ++} ++ ++/** Returns the current frame number. */ ++static int get_frame_number(struct usb_hcd *hcd) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ ++ return fh_otg_hcd_get_frame_number(fh_otg_hcd); ++} ++ ++#ifdef DEBUG ++static void dump_urb_info(struct urb *urb, char *fn_name) ++{ ++ printk("%s, urb %p\n", fn_name, urb); ++ printk(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ printk(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ printk(" Endpoint type: %s\n", ( { ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++case PIPE_CONTROL: ++pipetype = "CONTROL"; break; case PIPE_BULK: ++pipetype = "BULK"; break; case PIPE_INTERRUPT: ++pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS: ++pipetype = "ISOCHRONOUS"; break; default: ++ pipetype = "UNKNOWN"; break;}; ++ pipetype;} ++ )) ; ++ printk(" Speed: %s\n", ( { ++ char *speed; switch (urb->dev->speed) { ++case USB_SPEED_HIGH: ++speed = "HIGH"; break; case USB_SPEED_FULL: ++speed = "FULL"; break; case USB_SPEED_LOW: ++speed = "LOW"; break; default: ++ speed = "UNKNOWN"; break;}; ++ speed;} ++ )) ; ++ printk(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); ++ printk(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ printk(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->transfer_buffer, (void *)urb->transfer_dma); ++ printk(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ printk(" Interval: %d\n", urb->interval); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ printk(" ISO Desc %d:\n", i); ++ printk(" offset: %d, length %d\n", ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].length); ++ } ++ } ++} ++#endif ++ ++/** Starts processing a USB transfer request specified by a USB Request Block ++ * (URB). mem_flags indicates the type of memory allocation to use while ++ * processing this URB. */ ++static int ___urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags) ++{ ++ int retval = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep = urb->ep; ++#endif ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ fh_otg_hcd_urb_t *fh_otg_urb; ++ int i; ++ int alloc_bandwidth = 0; ++ uint8_t ep_type = 0; ++ uint32_t flags = 0; ++ void *buf; ++ ++ //dump_urb_info(urb, "urb_enqueue"); ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_enqueue"); ++ } ++#endif ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ++ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ if (!fh_otg_hcd_is_bandwidth_allocated ++ (fh_otg_hcd, &ep->hcpriv)) { ++ alloc_bandwidth = 1; ++ } ++ } ++ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ ep_type = USB_ENDPOINT_XFER_CONTROL; ++ break; ++ case PIPE_ISOCHRONOUS: ++ ep_type = USB_ENDPOINT_XFER_ISOC; ++ break; ++ case PIPE_BULK: ++ ep_type = USB_ENDPOINT_XFER_BULK; ++ break; ++ case PIPE_INTERRUPT: ++ ep_type = USB_ENDPOINT_XFER_INT; ++ break; ++ default: ++ FH_WARN("Wrong ep type\n"); ++ } ++ ++ fh_otg_urb = fh_otg_hcd_urb_alloc(fh_otg_hcd, ++ urb->number_of_packets, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ ++ fh_otg_hcd_urb_set_pipeinfo(fh_otg_urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ep_type, ++ usb_pipein(urb->pipe), ++ usb_maxpacket(urb->dev, urb->pipe, ++ !(usb_pipein(urb->pipe)))); ++ ++ buf = urb->transfer_buffer; ++ if (hcd->self.uses_dma) { ++ /* ++ * Calculate virtual address from physical address, ++ * because some class driver may not fill transfer_buffer. ++ * In Buffer DMA mode virual address is used, ++ * when handling non DWORD aligned buffers. ++ */ ++ buf = phys_to_virt(urb->transfer_dma); ++ } ++ ++ if (!(urb->transfer_flags & URB_NO_INTERRUPT)) ++ flags |= URB_GIVEBACK_ASAP; ++ if (urb->transfer_flags & URB_ZERO_PACKET) ++ flags |= URB_SEND_ZERO_PACKET; ++ ++ fh_otg_hcd_urb_set_params(fh_otg_urb, urb, buf, ++ urb->transfer_dma, ++ urb->transfer_buffer_length, ++ urb->setup_packet, ++ urb->setup_dma, flags, urb->interval); ++ ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ fh_otg_hcd_urb_set_iso_desc_params(fh_otg_urb, i, ++ urb-> ++ iso_frame_desc[i].offset, ++ urb-> ++ iso_frame_desc[i].length); ++ } ++ ++ urb->hcpriv = fh_otg_urb; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,7) ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &irqflags); ++ retval = usb_hcd_link_urb_to_ep(hcd, urb); ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, irqflags); ++ if (retval){ ++ goto fail1; ++ } ++#endif ++ ++ retval = fh_otg_hcd_urb_enqueue(fh_otg_hcd, fh_otg_urb, &ep->hcpriv, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ if (retval){ ++ goto fail2; ++ } ++ ++ if (alloc_bandwidth) { ++ allocate_bus_bandwidth(hcd, ++ fh_otg_hcd_get_ep_bandwidth ++ (fh_otg_hcd, ep->hcpriv), urb); ++ } ++ ++ return 0; ++ ++fail2: ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,7) ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &irqflags); ++ fh_otg_urb->priv = NULL; ++ usb_hcd_unlink_urb_from_ep(hcd, urb); ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, irqflags); ++#endif ++#ifdef DEBUG ++fail1: ++#endif ++ urb->hcpriv = NULL; ++ FH_FREE(fh_otg_urb); ++ ++ return retval; ++} ++ ++static int urb_enqueue(struct usb_hcd *hcd, ++ struct urb *urb, gfp_t mem_flags) ++{ ++ int ret; ++ unsigned long flagxx; ++ ++ local_irq_save(flagxx); ++ ret = ___urb_enqueue(hcd, urb, GFP_ATOMIC); ++ local_irq_restore(flagxx); ++ ++ return ret; ++} ++ ++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate ++ * success. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ++#else ++static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++#endif ++{ ++ fh_irqflags_t flags; ++ fh_otg_hcd_t *fh_otg_hcd; ++ int rc = 0; ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD URB Dequeue\n"); ++ ++ fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "urb_dequeue"); ++ } ++#endif ++ ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &flags); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,7) ++ rc = usb_hcd_check_unlink_urb(hcd, urb, status); ++ if (rc) ++ goto out; ++#endif ++ ++ if (!urb->hcpriv) { ++ FH_DEBUGPL(DBG_HCD, "urb->hcpriv is NULL\n"); ++ goto out; ++ } ++ ++ rc = fh_otg_hcd_urb_dequeue(fh_otg_hcd, urb->hcpriv); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,7,7) ++ usb_hcd_unlink_urb_from_ep(hcd, urb); ++#endif ++ ++ FH_FREE(urb->hcpriv); ++ urb->hcpriv = NULL; ++ ++ /* Higher layer software sets URB status. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(hcd, urb); ++#else ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, flags); //mvardan ++ usb_hcd_giveback_urb(hcd, urb, status); ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &flags); //mvardan ++#endif ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ FH_PRINTF("Called usb_hcd_giveback_urb()\n"); ++ FH_PRINTF(" urb->status = %d\n", urb->status); ++ } ++out: ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, flags); ++ ++ return rc; ++} ++ ++/* Frees resources in the FH_otg controller related to a given endpoint. Also ++ * clears state in the HCD related to the endpoint. Any URBs for the endpoint ++ * must already be dequeued. */ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ ++ FH_DEBUGPL(DBG_HCD, ++ "FH OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " ++ "endpoint=%d\n", ep->desc.bEndpointAddress, ++ fh_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); ++ fh_otg_hcd_endpoint_disable(fh_otg_hcd, ep->hcpriv, 250); ++ ep->hcpriv = NULL; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++/* Resets endpoint specific parameter values, in current version used to reset ++ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ fh_irqflags_t flags; ++ struct usb_device *udev = NULL; ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ int is_control = usb_endpoint_xfer_control(&ep->desc); ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ struct platform_device *_dev = fh_otg_hcd->otg_dev->os_dep.pdev; ++ ++ if (_dev) ++ udev = to_usb_device(&_dev->dev); ++ else ++ return; ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); ++ ++ FH_SPINLOCK_IRQSAVE(fh_otg_hcd->lock, &flags); ++ usb_settoggle(udev, epnum, is_out, 0); ++ if (is_control) ++ usb_settoggle(udev, epnum, !is_out, 0); ++ ++ if (ep->hcpriv) { ++ fh_otg_hcd_endpoint_reset(fh_otg_hcd, ep->hcpriv); ++ } ++ FH_SPINUNLOCK_IRQRESTORE(fh_otg_hcd->lock, flags); ++} ++#endif ++ ++/** Handles host mode interrupts for the FH_otg controller. Returns IRQ_NONE if ++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid ++ * interrupt. ++ * ++ * This function is called by the USB core when an interrupt occurs */ ++static irqreturn_t fh_otg_hcd_irq(struct usb_hcd *hcd) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ int32_t retval = fh_otg_hcd_handle_intr(fh_otg_hcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** Creates Status Change bitmap for the root hub and root port. The bitmap is ++ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 ++ * is the status change indicator for the single root port. Returns 1 if either ++ * change indicator is 1, otherwise returns 0. */ ++int hub_status_data(struct usb_hcd *hcd, char *buf) ++{ ++ fh_otg_hcd_t *fh_otg_hcd = hcd_to_fh_otg_hcd(hcd); ++ ++ buf[0] = 0; ++ buf[0] |= (fh_otg_hcd_is_status_changed(fh_otg_hcd, 1)) << 1; ++ ++ return (buf[0] != 0); ++} ++ ++/** Handles hub class-specific requests. */ ++int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) ++{ ++ int retval; ++ ++ retval = fh_otg_hcd_hub_control(hcd_to_fh_otg_hcd(hcd), ++ typeReq, wValue, wIndex, buf, wLength); ++ ++ switch (retval) { ++ case -FH_E_INVALID: ++ retval = -EINVAL; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_queue.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_queue.c +new file mode 100644 +index 00000000..37e085db +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_hcd_queue.c +@@ -0,0 +1,731 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_hcd_queue.c $ ++ * $Revision: #45 $ ++ * $Date: 2013/01/24 $ ++ * $Change: 2150293 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the functions to manage Queue Heads and Queue ++ * Transfer Descriptors. ++ */ ++ ++#include "fh_otg_hcd.h" ++#include "fh_otg_regs.h" ++ ++/** ++ * Free each QTD in the QH's QTD-list then free the QH. QH should already be ++ * removed from a list. QTD list should already be empty if called from URB ++ * Dequeue. ++ * ++ * @param hcd HCD instance. ++ * @param qh The QH to free. ++ */ ++void fh_otg_hcd_qh_free(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ fh_otg_qtd_t *qtd, *qtd_tmp; ++ fh_irqflags_t flags; ++ ++ /* Free each QTD in the QTD list */ ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ FH_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ FH_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++ fh_otg_hcd_qtd_free(qtd); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ fh_otg_hcd_qh_free_ddma(hcd, qh); ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } else if (qh->dw_align_buf) { ++ uint32_t buf_size; ++ if (qh->ep_type == UE_ISOCHRONOUS) { ++ buf_size = 4096; ++ } else { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ FH_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } ++ ++ FH_FREE(qh); ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ return; ++} ++ ++#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6) ++#define HS_HOST_DELAY 5 /* nanoseconds */ ++#define FS_LS_HOST_DELAY 1000 /* nanoseconds */ ++#define HUB_LS_SETUP 333 /* nanoseconds */ ++#define NS_TO_US(ns) ((ns + 500) / 1000) ++ /* convert & round nanoseconds to microseconds */ ++ ++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) ++{ ++ unsigned long retval; ++ ++ switch (speed) { ++ case USB_SPEED_HIGH: ++ if (is_isoc) { ++ retval = ++ ((38 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } else { ++ retval = ++ ((55 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } ++ break; ++ case USB_SPEED_FULL: ++ if (is_isoc) { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ if (is_in) { ++ retval = 7268 + FS_LS_HOST_DELAY + retval; ++ } else { ++ retval = 6265 + FS_LS_HOST_DELAY + retval; ++ } ++ } else { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ retval = 9107 + FS_LS_HOST_DELAY + retval; ++ } ++ break; ++ case USB_SPEED_LOW: ++ if (is_in) { ++ retval = ++ (67667 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } else { ++ retval = ++ (66700 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } ++ break; ++ default: ++ FH_WARN("Unknown device speed\n"); ++ retval = -1; ++ } ++ ++ return NS_TO_US(retval); ++} ++ ++/** ++ * Initializes a QH structure. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh The QH to init. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ */ ++#define SCHEDULE_SLOP 10 ++void qh_init(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, fh_otg_hcd_urb_t * urb) ++{ ++ char *speed, *type; ++ int dev_speed; ++ uint32_t hub_addr, hub_port; ++ ++ fh_memset(qh, 0, sizeof(fh_otg_qh_t)); ++ ++ /* Initialize QH */ ++ qh->ep_type = fh_otg_hcd_get_pipe_type(&urb->pipe_info); ++ qh->ep_is_in = fh_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; ++ ++ qh->data_toggle = FH_OTG_HC_PID_DATA0; ++ qh->maxp = fh_otg_hcd_get_mps(&urb->pipe_info); ++ FH_CIRCLEQ_INIT(&qh->qtd_list); ++ FH_LIST_INIT(&qh->qh_list_entry); ++ qh->channel = NULL; ++ ++ /* FS/LS Enpoint on HS Hub ++ * NOT virtual root hub */ ++ dev_speed = hcd->fops->speed(hcd, urb->priv); ++ ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); ++ qh->do_split = 0; ++ ++ if (((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL)) && ++ (hub_addr != 0 && hub_addr != 1)) { ++ FH_DEBUGPL(DBG_HCD, ++ "QH init: EP %d: TT found at hub addr %d, for port %d\n", ++ fh_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, ++ hub_port); ++ qh->do_split = 1; ++ } ++ ++ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { ++ /* Compute scheduling parameters once and save them. */ ++ hprt0_data_t hprt; ++ ++ /** @todo Account for split transfers in the bus time. */ ++ int bytecount = ++ fh_hb_mult(qh->maxp) * fh_max_packet(qh->maxp); ++ ++ qh->usecs = ++ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), ++ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), ++ bytecount); ++ /* Start in a slightly future (micro)frame. */ ++ qh->sched_frame = fh_frame_num_inc(hcd->frame_number, ++ SCHEDULE_SLOP); ++ qh->interval = urb->interval; ++ ++#if 0 ++ /* Increase interrupt polling rate for debugging. */ ++ if (qh->ep_type == UE_INTERRUPT) { ++ qh->interval = 8; ++ } ++#endif ++ hprt.d32 = FH_READ_REG32(hcd->core_if->host_if->hprt0); ++ if ((hprt.b.prtspd == FH_HPRT0_PRTSPD_HIGH_SPEED) && ++ ((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL))) { ++ qh->interval *= 8; ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ ++ } ++ ++ FH_DEBUGPL(DBG_HCD, "FH OTG HCD QH Initialized\n"); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - qh = %p\n", qh); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - Device Address = %d\n", ++ fh_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - Endpoint %d, %s\n", ++ fh_otg_hcd_get_ep_num(&urb->pipe_info), ++ fh_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); ++ switch (dev_speed) { ++ case USB_SPEED_LOW: ++ qh->dev_speed = FH_OTG_EP_SPEED_LOW; ++ speed = "low"; ++ break; ++ case USB_SPEED_FULL: ++ qh->dev_speed = FH_OTG_EP_SPEED_FULL; ++ speed = "full"; ++ break; ++ case USB_SPEED_HIGH: ++ qh->dev_speed = FH_OTG_EP_SPEED_HIGH; ++ speed = "high"; ++ break; ++ default: ++ speed = "?"; ++ break; ++ } ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - Speed = %s\n", speed); ++ ++ switch (qh->ep_type) { ++ case UE_ISOCHRONOUS: ++ type = "isochronous"; ++ break; ++ case UE_INTERRUPT: ++ type = "interrupt"; ++ break; ++ case UE_CONTROL: ++ type = "control"; ++ break; ++ case UE_BULK: ++ type = "bulk"; ++ break; ++ default: ++ type = "?"; ++ break; ++ } ++ ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - Type = %s\n", type); ++ ++#ifdef DEBUG ++ if (qh->ep_type == UE_INTERRUPT) { ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - usecs = %d\n", ++ qh->usecs); ++ FH_DEBUGPL(DBG_HCDV, "FH OTG HCD QH - interval = %d\n", ++ qh->interval); ++ } ++#endif ++ ++} ++ ++/** ++ * This function allocates and initializes a QH. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * @return Returns pointer to the newly allocated QH, or NULL on error. */ ++fh_otg_qh_t *fh_otg_hcd_qh_create(fh_otg_hcd_t * hcd, ++ fh_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ fh_otg_qh_t *qh; ++ ++ /* Allocate memory */ ++ /** @todo add memflags argument */ ++ qh = fh_otg_hcd_qh_alloc(atomic_alloc); ++ if (qh == NULL) { ++ FH_ERROR("qh allocation failed"); ++ return NULL; ++ } ++ ++ qh_init(hcd, qh, urb); ++ ++ if (hcd->core_if->dma_desc_enable ++ && (fh_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { ++ fh_otg_hcd_qh_free(hcd, qh); ++ return NULL; ++ } ++ ++ return qh; ++} ++ ++/** ++ * Checks that a channel is available for a periodic transfer. ++ * ++ * @return 0 if successful, negative error code otherise. ++ */ ++static int periodic_channel_available(fh_otg_hcd_t * hcd) ++{ ++ /* ++ * Currently assuming that there is a dedicated host channnel for each ++ * periodic transaction plus at least one host channel for ++ * non-periodic transactions. ++ */ ++ int status; ++ int num_channels; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) ++ && (hcd->periodic_channels < num_channels - 1)) { ++ status = 0; ++ } else { ++ FH_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", ++ __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE ++ status = -FH_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that there is sufficient bandwidth for the specified QH in the ++ * periodic schedule. For simplicity, this calculation assumes that all the ++ * transfers in the periodic schedule may occur in the same (micro)frame. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh QH containing periodic bandwidth required. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_periodic_bandwidth(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ int status; ++ int16_t max_claimed_usecs; ++ ++ status = 0; ++ ++ if ((qh->dev_speed == FH_OTG_EP_SPEED_HIGH) || qh->do_split) { ++ /* ++ * High speed mode. ++ * Max periodic usecs is 80% x 125 usec = 100 usec. ++ */ ++ ++ max_claimed_usecs = 100 - qh->usecs; ++ } else { ++ /* ++ * Full speed mode. ++ * Max periodic usecs is 90% x 1000 usec = 900 usec. ++ */ ++ max_claimed_usecs = 900 - qh->usecs; ++ } ++ ++ if (hcd->periodic_usecs > max_claimed_usecs) { ++ FH_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE ++ status = -FH_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that the max transfer size allowed in a host channel is large enough ++ * to handle the maximum data transfer in a single (micro)frame for a periodic ++ * transfer. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh QH for a periodic endpoint. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_max_xfer_size(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ int status; ++ uint32_t max_xfer_size; ++ uint32_t max_channel_xfer_size; ++ ++ status = 0; ++ ++ max_xfer_size = fh_max_packet(qh->maxp) * fh_hb_mult(qh->maxp); ++ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; ++ ++ if (max_xfer_size > max_channel_xfer_size) { ++ FH_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n", ++ __func__, max_xfer_size, max_channel_xfer_size); //NOTICE ++ status = -FH_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Schedules an interrupt or isochronous transfer in the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh QH for the periodic transfer. The QH should already contain the ++ * scheduling information. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int schedule_periodic(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ int status = 0; ++ ++ status = periodic_channel_available(hcd); ++ if (status) { ++ FH_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ if (status) { ++ FH_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_max_xfer_size(hcd, qh); ++ if (status) { ++ FH_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ /* Don't rely on SOF and start in ready schedule */ ++ FH_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); ++ } ++ else { ++ /* Always start in the inactive schedule. */ ++ FH_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); ++ } ++ ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs += qh->usecs; ++ ++ return status; ++} ++ ++/** ++ * This function adds a QH to either the non periodic or periodic schedule if ++ * it is not already in the schedule. If the QH is already in the schedule, no ++ * action is taken. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int fh_otg_hcd_qh_add(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ int status = 0; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!FH_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH already in a schedule. */ ++ return status; ++ } ++ ++ /* Add the new QH to the appropriate schedule */ ++ if (fh_qh_is_non_per(qh)) { ++ /* Always start in the inactive schedule. */ ++ FH_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } else { ++ status = schedule_periodic(hcd, qh); ++ if ( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ FH_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ hcd->periodic_qh_count++; ++ } ++ ++ return status; ++} ++ ++/** ++ * Removes an interrupt or isochronous transfer from the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the FH OTG controller. ++ * @param qh QH for the periodic transfer. ++ */ ++static void deschedule_periodic(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ FH_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs -= qh->usecs; ++} ++ ++/** ++ * Removes a QH from either the non-periodic or periodic schedule. Memory is ++ * not freed. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh QH to remove from schedule. */ ++void fh_otg_hcd_qh_remove(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (FH_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH is not in a schedule. */ ++ return; ++ } ++ ++ if (fh_qh_is_non_per(qh)) { ++ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ FH_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ } else { ++ deschedule_periodic(hcd, qh); ++ hcd->periodic_qh_count--; ++ if( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ FH_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ } ++} ++ ++/** ++ * Deactivates a QH. For non-periodic QHs, removes the QH from the active ++ * non-periodic schedule. The QH is added to the inactive non-periodic ++ * schedule if any QTDs are still attached to the QH. ++ * ++ * For periodic QHs, the QH is removed from the periodic queued schedule. If ++ * there are any QTDs still attached to the QH, the QH is added to either the ++ * periodic inactive schedule or the periodic ready schedule and its next ++ * scheduled frame is calculated. The QH is placed in the ready schedule if ++ * the scheduled frame has been reached already. Otherwise it's placed in the ++ * inactive schedule. If there are no QTDs attached to the QH, the QH is ++ * completely removed from the periodic schedule. ++ */ ++void fh_otg_hcd_qh_deactivate(fh_otg_hcd_t * hcd, fh_otg_qh_t * qh, ++ int sched_next_periodic_split) ++{ ++ if (fh_qh_is_non_per(qh)) { ++ fh_otg_hcd_qh_remove(hcd, qh); ++ if (!FH_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule. */ ++ fh_otg_hcd_qh_add(hcd, qh); ++ } ++ } else { ++ uint16_t frame_number = fh_otg_hcd_get_frame_number(hcd); ++ ++ if (qh->do_split) { ++ /* Schedule the next continuing periodic split transfer */ ++ if (sched_next_periodic_split) { ++ ++ qh->sched_frame = frame_number; ++ if (fh_frame_num_le(frame_number, ++ fh_frame_num_inc ++ (qh->start_split_frame, ++ 1))) { ++ /* ++ * Allow one frame to elapse after start ++ * split microframe before scheduling ++ * complete split, but DONT if we are ++ * doing the next start split in the ++ * same frame for an ISOC out. ++ */ ++ if ((qh->ep_type != UE_ISOCHRONOUS) || ++ (qh->ep_is_in != 0)) { ++ qh->sched_frame = ++ fh_frame_num_inc(qh->sched_frame, 1); ++ } ++ } ++ } else { ++ qh->sched_frame = ++ fh_frame_num_inc(qh->start_split_frame, ++ qh->interval); ++ if (fh_frame_num_le ++ (qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ } else { ++ qh->sched_frame = ++ fh_frame_num_inc(qh->sched_frame, qh->interval); ++ if (fh_frame_num_le(qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ } ++ ++ if (FH_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ fh_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* ++ * Remove from periodic_sched_queued and move to ++ * appropriate queue. ++ */ ++ if (qh->sched_frame == frame_number) { ++ FH_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } else { ++ FH_LIST_MOVE_HEAD ++ (&hcd->periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } ++ } ++ } ++} ++ ++/** ++ * This function allocates and initializes a QTD. ++ * ++ * @param urb The URB to create a QTD from. Each URB-QTD pair will end up ++ * pointing to each other so each pair should have a unique correlation. ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return Returns pointer to the newly allocated QTD, or NULL on error. */ ++fh_otg_qtd_t *fh_otg_hcd_qtd_create(fh_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ fh_otg_qtd_t *qtd; ++ ++ qtd = fh_otg_hcd_qtd_alloc(atomic_alloc); ++ if (qtd == NULL) { ++ return NULL; ++ } ++ ++ fh_otg_hcd_qtd_init(qtd, urb); ++ return qtd; ++} ++ ++/** ++ * Initializes a QTD structure. ++ * ++ * @param qtd The QTD to initialize. ++ * @param urb The URB to use for initialization. */ ++void fh_otg_hcd_qtd_init(fh_otg_qtd_t * qtd, fh_otg_hcd_urb_t * urb) ++{ ++ fh_memset(qtd, 0, sizeof(fh_otg_qtd_t)); ++ qtd->urb = urb; ++ if (fh_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) { ++ /* ++ * The only time the QTD data toggle is used is on the data ++ * phase of control transfers. This phase always starts with ++ * DATA1. ++ */ ++ qtd->data_toggle = FH_OTG_HC_PID_DATA1; ++ qtd->control_phase = FH_OTG_CONTROL_SETUP; ++ } ++ ++ /* start split */ ++ qtd->complete_split = 0; ++ qtd->isoc_split_pos = FH_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ qtd->in_process = 0; ++ ++ /* Store the qtd ptr in the urb to reference what QTD. */ ++ urb->qtd = qtd; ++ return; ++} ++ ++/** ++ * This function adds a QTD to the QTD-list of a QH. It will find the correct ++ * QH to place the QTD into. If it does not find a QH, then it will create a ++ * new QH. If the QH to which the QTD is added is not currently scheduled, it ++ * is placed into the proper schedule based on its EP type. ++ * ++ * @param[in] qtd The QTD to add ++ * @param[in] hcd The FH HCD structure ++ * @param[out] qh out parameter to return queue head ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int fh_otg_hcd_qtd_add(fh_otg_qtd_t * qtd, ++ fh_otg_hcd_t * hcd, fh_otg_qh_t ** qh, int atomic_alloc) ++{ ++ int retval = 0; ++ fh_irqflags_t flags; ++ ++ fh_otg_hcd_urb_t *urb = qtd->urb; ++ ++ /* ++ * Get the QH which holds the QTD-list to insert to. Create QH if it ++ * doesn't exist. ++ */ ++ if (*qh == NULL) { ++ *qh = fh_otg_hcd_qh_create(hcd, urb, atomic_alloc); ++ if (*qh == NULL) { ++ retval = -1; ++ goto done; ++ } ++ } ++ FH_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ retval = fh_otg_hcd_qh_add(hcd, *qh); ++ if (retval == 0) { ++ FH_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, ++ qtd_list_entry); ++ } ++ FH_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++done: ++ ++ return retval; ++} ++ ++#endif /* FH_DEVICE_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_os_dep.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_os_dep.h +new file mode 100644 +index 00000000..cf5bf274 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_os_dep.h +@@ -0,0 +1,99 @@ ++#ifndef _FH_OS_DEP_H_ ++#define _FH_OS_DEP_H_ ++ ++/** ++ * @file ++ * ++ * This file contains OS dependent structures. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/errno.h> ++#include <linux/types.h> ++#include <linux/slab.h> ++#include <linux/list.h> ++#include <linux/interrupt.h> ++#include <linux/ctype.h> ++#include <linux/string.h> ++#include <linux/dma-mapping.h> ++#include <linux/jiffies.h> ++#include <linux/delay.h> ++#include <linux/timer.h> ++#include <linux/workqueue.h> ++#include <linux/stat.h> ++#include <linux/pci.h> ++ ++#include <linux/version.h> ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include <linux/irq.h> ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include <linux/usb/ch9.h> ++#else ++# include <linux/usb_ch9.h> ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include <linux/usb/gadget.h> ++#else ++# include <linux/usb_gadget.h> ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include <asm/irq.h> ++#endif ++ ++#ifdef PCI_INTERFACE ++# include <asm/io.h> ++#endif ++ ++#ifdef LM_INTERFACE ++# include <asm/unaligned.h> ++# include <asm/sizes.h> ++# include <asm/param.h> ++# include <asm/io.h> ++# include <asm/arch/lm.h> ++# include <asm/arch/irqs.h> ++# include <asm/arch/regs-irq.h> ++#endif ++ ++/** The OS page size */ ++#define FH_OS_PAGE_SIZE PAGE_SIZE ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++typedef struct os_dependent { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Register offset for Diagnostic API */ ++ uint32_t reg_offset; ++ ++ struct platform_device *pdev; ++ ++ /** Start address of a PCI region */ ++ resource_size_t rsrc_start; ++ ++ /** Length address of a PCI region */ ++ resource_size_t rsrc_len; ++ ++} os_dependent_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _FH_OS_DEP_H_ */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.c +new file mode 100644 +index 00000000..134e91c0 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.c +@@ -0,0 +1,2989 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_pcd.c $ ++ * $Revision: #105 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_HOST_ONLY ++ ++/** @file ++ * This file implements PCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * PCD Core provides Interface, defined in <code><fh_otg_pcd_if.h></code> ++ * header file, which can be used to implement OS specific PCD interface. ++ * ++ * An important function of the PCD is managing interrupts generated ++ * by the FH_otg controller. The implementation of the FH_otg device ++ * mode interrupt service routines is in fh_otg_pcd_intr.c. ++ * ++ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc). ++ * @todo Does it work when the request size is greater than DEPTSIZ ++ * transfer size ++ * ++ */ ++ ++#include "fh_otg_pcd.h" ++ ++#ifdef FH_UTE_CFI ++#include "fh_otg_cfi.h" ++ ++extern int init_cfi(cfiobject_t * cfiobj); ++#endif ++ ++/** ++ * Choose endpoint from ep arrays using usb_ep structure. ++ */ ++static fh_otg_pcd_ep_t *get_ep_from_handle(fh_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function completes a request. It call's the request call back. ++ */ ++void fh_otg_request_done(fh_otg_pcd_ep_t * ep, fh_otg_pcd_request_t * req, ++ int32_t status) ++{ ++ unsigned stopped = ep->stopped; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); ++ FH_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ ++ /* don't modify queue heads during completion callback */ ++ ep->stopped = 1; ++ /* spin_unlock/spin_lock now done in fops->complete() */ ++ ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, ++ req->actual); ++ ++ if (ep->pcd->request_pending > 0) ++ --ep->pcd->request_pending; ++ ++ ep->stopped = stopped; ++ FH_FREE(req); ++} ++ ++/** ++ * This function terminates all the requsts in the EP request queue. ++ */ ++void fh_otg_request_nuke(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_pcd_request_t *req; ++ ++ ep->stopped = 1; ++ ++ /* called with irqs blocked?? */ ++ while (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ fh_otg_request_done(ep, req, -FH_E_SHUTDOWN); ++ } ++} ++ ++void fh_otg_pcd_start(fh_otg_pcd_t * pcd, ++ const struct fh_otg_pcd_function_ops *fops) ++{ ++ pcd->fops = fops; ++} ++ ++/** ++ * PCD Callback function for initializing the PCD when switching to ++ * device mode. ++ * ++ * @param p void pointer to the <code>fh_otg_pcd_t</code> ++ */ ++static int32_t fh_otg_pcd_start_cb(void *p) ++{ ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) p; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ /* ++ * Initialized the Core for Device mode. ++ */ ++ if (fh_otg_is_device_mode(core_if)) { ++ fh_otg_core_dev_init(core_if); ++ /* Set core_if's lock pointer to the pcd->lock */ ++ core_if->lock = pcd->lock; ++ } ++ return 1; ++} ++ ++/** CFI-specific buffer allocation function for EP */ ++#ifdef FH_UTE_CFI ++uint8_t *cfiw_ep_alloc_buffer(fh_otg_pcd_t * pcd, void *pep, fh_dma_t * addr, ++ size_t buflen, int flags) ++{ ++ fh_otg_pcd_ep_t *ep; ++ ep = get_ep_from_handle(pcd, pep); ++ if (!ep) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ ++ return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, ++ flags); ++} ++#else ++uint8_t *cfiw_ep_alloc_buffer(fh_otg_pcd_t * pcd, void *pep, fh_dma_t * addr, ++ size_t buflen, int flags); ++#endif ++ ++/** ++ * PCD Callback function for notifying the PCD when resuming from ++ * suspend. ++ * ++ * @param p void pointer to the <code>fh_otg_pcd_t</code> ++ */ ++static int32_t fh_otg_pcd_resume_cb(void *p) ++{ ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) p; ++ ++ if (pcd->fops->resume) ++ pcd->fops->resume(pcd); ++ ++ /* Stop the SRP timeout timer. */ ++ if ((GET_CORE_IF(pcd)->core_params->phy_type != FH_PHY_TYPE_PARAM_FS) ++ || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { ++ if (GET_CORE_IF(pcd)->srp_timer_started) { ++ GET_CORE_IF(pcd)->srp_timer_started = 0; ++ FH_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); ++ } ++ } ++ return 1; ++} ++ ++/** ++ * PCD Callback function for notifying the PCD device is suspended. ++ * ++ * @param p void pointer to the <code>fh_otg_pcd_t</code> ++ */ ++static int32_t fh_otg_pcd_suspend_cb(void *p) ++{ ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) p; ++ ++ if (pcd->fops->suspend) { ++ FH_SPINUNLOCK(pcd->lock); ++ pcd->fops->suspend(pcd); ++ FH_SPINLOCK(pcd->lock); ++ } ++ ++ return 1; ++} ++ ++/** ++ * PCD Callback function for stopping the PCD when switching to Host ++ * mode. ++ * ++ * @param p void pointer to the <code>fh_otg_pcd_t</code> ++ */ ++static int32_t fh_otg_pcd_stop_cb(void *p) ++{ ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) p; ++ extern void fh_otg_pcd_stop(fh_otg_pcd_t * _pcd); ++ ++ fh_otg_pcd_stop(pcd); ++ return 1; ++} ++ ++/** ++ * PCD Callback structure for handling mode switching. ++ */ ++static fh_otg_cil_callbacks_t pcd_callbacks = { ++ .start = fh_otg_pcd_start_cb, ++ .stop = fh_otg_pcd_stop_cb, ++ .suspend = fh_otg_pcd_suspend_cb, ++ .resume_wakeup = fh_otg_pcd_resume_cb, ++ .p = 0, /* Set at registration */ ++}; ++ ++/** ++ * This function allocates a DMA Descriptor chain for the Endpoint ++ * buffer to be used for a transfer to/from the specified endpoint. ++ */ ++fh_otg_dev_dma_desc_t *fh_otg_ep_alloc_desc_chain(fh_dma_t * dma_desc_addr, ++ uint32_t count) ++{ ++ return FH_DMA_ALLOC_ATOMIC(count * sizeof(fh_otg_dev_dma_desc_t), ++ dma_desc_addr); ++} ++ ++struct fh_otg_dma_free { ++ fh_tasklet_t *tsklt; ++ uint32_t size; ++ void *virt_addr; ++ fh_dma_t dma_addr; ++}; ++ ++static void fh_otg_dma_free_func(void *data) ++{ ++ struct fh_otg_dma_free *pDmafreeMgr = ++ (struct fh_otg_dma_free *)data; ++ ++ FH_DMA_FREE(pDmafreeMgr->size, ++ pDmafreeMgr->virt_addr, ++ pDmafreeMgr->dma_addr); ++ FH_TASK_FREE(pDmafreeMgr->tsklt); ++ FH_FREE(pDmafreeMgr); ++} ++/** ++ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. ++ */ ++void fh_otg_ep_free_desc_chain(fh_otg_dev_dma_desc_t * desc_addr, ++ uint32_t dma_desc_addr, uint32_t count) ++{ ++ struct fh_otg_dma_free *pDmafreeMgr; ++ fh_tasklet_t *pDmafreeTsklt; ++ ++ pDmafreeMgr = FH_ALLOC(sizeof(struct fh_otg_dma_free)); ++ if (pDmafreeMgr == NULL) ++ goto alloc_err1; ++ ++ pDmafreeTsklt = FH_TASK_ALLOC("dmafree_tasklet", ++ fh_otg_dma_free_func, ++ pDmafreeMgr); ++ if (pDmafreeTsklt == NULL) ++ goto alloc_err2; ++ ++ pDmafreeMgr->tsklt = pDmafreeTsklt; ++ pDmafreeMgr->size = count * sizeof(fh_otg_dev_dma_desc_t); ++ pDmafreeMgr->virt_addr = desc_addr; ++ pDmafreeMgr->dma_addr = dma_desc_addr; ++ ++ FH_TASK_SCHEDULE(pDmafreeTsklt); ++ ++ return; ++ ++alloc_err2: ++ FH_FREE(pDmafreeMgr); ++alloc_err1: ++ WARN_ON(true); ++} ++ ++#ifdef FH_EN_ISOC ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param fh_ep The EP to start the transfer on. ++ * ++ */ ++void fh_otg_iso_ep_start_ddma_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * fh_ep) ++{ ++ ++ dsts_data_t dsts = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ int i, j; ++ uint32_t len; ++ ++ if (fh_ep->is_in) ++ fh_ep->desc_cnt = fh_ep->buf_proc_intrvl / fh_ep->bInterval; ++ else ++ fh_ep->desc_cnt = ++ fh_ep->buf_proc_intrvl * fh_ep->pkt_per_frm / ++ fh_ep->bInterval; ++ ++ /** Allocate descriptors for double buffering */ ++ fh_ep->iso_desc_addr = ++ fh_otg_ep_alloc_desc_chain(&fh_ep->iso_dma_desc_addr, ++ fh_ep->desc_cnt * 2); ++ if (fh_ep->desc_addr) { ++ FH_WARN("%s, can't allocate DMA descriptor chain\n", __func__); ++ return; ++ } ++ ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /** ISO OUT EP */ ++ if (fh_ep->is_in == 0) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ fh_otg_dev_dma_desc_t *dma_desc = fh_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ uint32_t data_per_desc; ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[fh_ep->num]; ++ int offset; ++ ++ addr = &core_if->dev_if->out_ep_regs[fh_ep->num]->doepctl; ++ dma_ad = (dma_addr_t) FH_READ_REG32(&(out_regs->doepdma)); ++ ++ /** Buffer 0 descriptors setup */ ++ dma_ad = fh_ep->dma_addr0; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ offset = 0; ++ for (i = 0; i < fh_ep->desc_cnt - fh_ep->pkt_per_frm; ++ i += fh_ep->pkt_per_frm) { ++ ++ for (j = 0; j < fh_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * fh_ep->maxpacket; ++ if (len > fh_ep->data_per_frame) ++ data_per_desc = ++ fh_ep->data_per_frame - ++ j * fh_ep->maxpacket; ++ else ++ data_per_desc = fh_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ ++ for (j = 0; j < fh_ep->pkt_per_frm - 1; ++j) { ++ uint32_t len = (j + 1) * fh_ep->maxpacket; ++ if (len > fh_ep->data_per_frame) ++ data_per_desc = ++ fh_ep->data_per_frame - ++ j * fh_ep->maxpacket; ++ else ++ data_per_desc = fh_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ len = (j + 1) * fh_ep->maxpacket; ++ if (len > fh_ep->data_per_frame) ++ data_per_desc = ++ fh_ep->data_per_frame - j * fh_ep->maxpacket; ++ else ++ data_per_desc = fh_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_out.ioc = 0; ++ dma_ad = fh_ep->dma_addr1; ++ ++ offset = 0; ++ for (i = 0; i < fh_ep->desc_cnt - fh_ep->pkt_per_frm; ++ i += fh_ep->pkt_per_frm) { ++ for (j = 0; j < fh_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * fh_ep->maxpacket; ++ if (len > fh_ep->data_per_frame) ++ data_per_desc = ++ fh_ep->data_per_frame - ++ j * fh_ep->maxpacket; ++ else ++ data_per_desc = fh_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ data_per_desc = ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ for (j = 0; j < fh_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep->data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = 1; ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep->data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ fh_ep->next_frame = 0; ++ ++ /** Write dma_ad into DOEPDMA register */ ++ FH_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) fh_ep->iso_dma_desc_addr); ++ ++ } ++ /** ISO IN EP */ ++ else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ fh_otg_dev_dma_desc_t *dma_desc = fh_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ fh_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[fh_ep->num]; ++ unsigned int frmnumber; ++ fifosize_data_t txfifosize, rxfifosize; ++ ++ txfifosize.d32 = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[fh_ep->num]-> ++ dtxfsts); ++ rxfifosize.d32 = ++ FH_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ ++ addr = &core_if->dev_if->in_ep_regs[fh_ep->num]->diepctl; ++ ++ dma_ad = fh_ep->dma_addr0; ++ ++ dsts.d32 = ++ FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = ++ (fh_ep->data_per_frame % fh_ep->maxpacket) ? 1 : 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = fh_ep->pkt_per_frm; ++ ++ frmnumber = fh_ep->next_frame; ++ ++ sts.b_iso_in.framenum = frmnumber; ++ sts.b_iso_in.txbytes = fh_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ /** Buffer 0 descriptors setup */ ++ for (i = 0; i < fh_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += fh_ep->data_per_frame; ++ sts.b_iso_in.framenum += fh_ep->bInterval; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++dma_desc; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_in.ioc = 0; ++ dma_ad = fh_ep->dma_addr1; ++ ++ for (i = 0; i < fh_ep->desc_cnt - fh_ep->pkt_per_frm; ++ i += fh_ep->pkt_per_frm) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += fh_ep->data_per_frame; ++ sts.b_iso_in.framenum += fh_ep->bInterval; ++ ++ sts.b_iso_in.ioc = 0; ++ } ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = 1; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ fh_ep->next_frame = sts.b_iso_in.framenum + fh_ep->bInterval; ++ ++ /** Write dma_ad into diepdma register */ ++ FH_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) fh_ep->iso_dma_desc_addr); ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.usbactep = 1; ++ depctl.b.cnak = 1; ++ ++ FH_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ depctl.d32 = FH_READ_REG32(addr); ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void fh_otg_iso_ep_start_buf_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ else ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ ++ if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) { ++ return; ++ } else { ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ ++ ep->xfer_len = ++ ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; ++ ep->pkt_cnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.mc = ep->pkt_per_frm; ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ FH_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ FH_WRITE_REG32(& ++ (core_if->dev_if->out_ep_regs[ep->num]-> ++ doepdma), (uint32_t) ep->dma_addr); ++ ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ FH_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++static void fh_otg_iso_ep_start_transfer(fh_otg_core_if_t * core_if, ++ fh_ep_t * ep) ++{ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ if (ep->is_in) { ++ ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; ++ } else { ++ ep->desc_cnt = ep->pkt_cnt; ++ } ++ fh_otg_iso_ep_start_ddma_transfer(core_if, ep); ++ } else { ++ if (core_if->pti_enh_enable) { ++ fh_otg_iso_ep_start_buf_transfer(core_if, ep); ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> ++ xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> ++ dma_addr0; ++ fh_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++ } ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ fh_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++} ++ ++/** ++ * This function stops transfer for an EP and ++ * resets the ep's variables. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void fh_otg_iso_ep_stop_transfer(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ /* disable the ep */ ++ depctl.d32 = FH_READ_REG32(addr); ++ ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ ++ FH_WRITE_REG32(addr, depctl.d32); ++ ++ if (core_if->dma_desc_enable && ++ ep->iso_desc_addr && ep->iso_dma_desc_addr) { ++ fh_otg_ep_free_desc_chain(ep->iso_desc_addr, ++ ep->iso_dma_desc_addr, ++ ep->desc_cnt * 2); ++ } ++ ++ /* reset varibales */ ++ ep->dma_addr0 = 0; ++ ep->dma_addr1 = 0; ++ ep->xfer_buff0 = 0; ++ ep->xfer_buff1 = 0; ++ ep->data_per_frame = 0; ++ ep->data_pattern_frame = 0; ++ ep->sync_frame = 0; ++ ep->buf_proc_intrvl = 0; ++ ep->bInterval = 0; ++ ep->proc_buf_num = 0; ++ ep->pkt_per_frm = 0; ++ ep->pkt_per_frm = 0; ++ ep->desc_cnt = 0; ++ ep->iso_desc_addr = 0; ++ ep->iso_dma_desc_addr = 0; ++} ++ ++int fh_otg_pcd_iso_ep_start(fh_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, fh_dma_t dma0, ++ fh_dma_t dma1, int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc) ++{ ++ fh_otg_pcd_ep_t *ep; ++ fh_irqflags_t flags = 0; ++ fh_ep_t *fh_ep; ++ int32_t frm_data; ++ dsts_data_t dsts; ++ fh_otg_core_if_t *core_if; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc || ep->fh_ep.num == 0) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ core_if = GET_CORE_IF(pcd); ++ fh_ep = &ep->fh_ep; ++ ++ if (ep->iso_req_handle) { ++ FH_WARN("ISO request in progress\n"); ++ } ++ ++ fh_ep->dma_addr0 = dma0; ++ fh_ep->dma_addr1 = dma1; ++ ++ fh_ep->xfer_buff0 = buf0; ++ fh_ep->xfer_buff1 = buf1; ++ ++ fh_ep->data_per_frame = data_per_frame; ++ ++ /** @todo - pattern data support is to be implemented in the future */ ++ fh_ep->data_pattern_frame = dp_frame; ++ fh_ep->sync_frame = sync_frame; ++ ++ fh_ep->buf_proc_intrvl = buf_proc_intrvl; ++ ++ fh_ep->bInterval = 1 << (ep->desc->bInterval - 1); ++ ++ fh_ep->proc_buf_num = 0; ++ ++ fh_ep->pkt_per_frm = 0; ++ frm_data = ep->fh_ep.data_per_frame; ++ while (frm_data > 0) { ++ fh_ep->pkt_per_frm++; ++ frm_data -= ep->fh_ep.maxpacket; ++ } ++ ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ if (start_frame == -1) { ++ fh_ep->next_frame = dsts.b.soffn + 1; ++ if (fh_ep->bInterval != 1) { ++ fh_ep->next_frame = ++ fh_ep->next_frame + (fh_ep->bInterval - 1 - ++ fh_ep->next_frame % ++ fh_ep->bInterval); ++ } ++ } else { ++ fh_ep->next_frame = start_frame; ++ } ++ ++ if (!core_if->pti_enh_enable) { ++ fh_ep->pkt_cnt = ++ fh_ep->buf_proc_intrvl * fh_ep->pkt_per_frm / ++ fh_ep->bInterval; ++ } else { ++ fh_ep->pkt_cnt = ++ (fh_ep->data_per_frame * ++ (fh_ep->buf_proc_intrvl / fh_ep->bInterval) ++ - 1 + fh_ep->maxpacket) / fh_ep->maxpacket; ++ } ++ ++ if (core_if->dma_desc_enable) { ++ fh_ep->desc_cnt = ++ fh_ep->buf_proc_intrvl * fh_ep->pkt_per_frm / ++ fh_ep->bInterval; ++ } ++ ++ if (atomic_alloc) { ++ fh_ep->pkt_info = ++ FH_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * fh_ep->pkt_cnt); ++ } else { ++ fh_ep->pkt_info = ++ FH_ALLOC(sizeof(iso_pkt_info_t) * fh_ep->pkt_cnt); ++ } ++ if (!fh_ep->pkt_info) { ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -FH_E_NO_MEMORY; ++ } ++ if (core_if->pti_enh_enable) { ++ fh_memset(fh_ep->pkt_info, 0, ++ sizeof(iso_pkt_info_t) * fh_ep->pkt_cnt); ++ } ++ ++ fh_ep->cur_pkt = 0; ++ ep->iso_req_handle = req_handle; ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ fh_otg_iso_ep_start_transfer(core_if, fh_ep); ++ return 0; ++} ++ ++int fh_otg_pcd_iso_ep_stop(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ fh_irqflags_t flags = 0; ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || !ep->desc || ep->fh_ep.num == 0) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ fh_ep = &ep->fh_ep; ++ ++ fh_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), fh_ep); ++ ++ FH_FREE(fh_ep->pkt_info); ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (ep->iso_req_handle != req_handle) { ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -FH_E_INVALID; ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ ep->iso_req_handle = 0; ++ return 0; ++} ++ ++/** ++ * This function is used for perodical data exchnage between PCD and gadget drivers. ++ * for Isochronous EPs ++ * ++ * - Every time a sync period completes this function is called to ++ * perform data exchange between PCD and gadget ++ */ ++void fh_otg_iso_buffer_done(fh_otg_pcd_t * pcd, fh_otg_pcd_ep_t * ep, ++ void *req_handle) ++{ ++ int i; ++ fh_ep_t *fh_ep; ++ ++ fh_ep = &ep->fh_ep; ++ ++ FH_SPINUNLOCK(ep->pcd->lock); ++ pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle, ++ fh_ep->proc_buf_num ^ 0x1); ++ FH_SPINLOCK(ep->pcd->lock); ++ ++ for (i = 0; i < fh_ep->pkt_cnt; ++i) { ++ fh_ep->pkt_info[i].status = 0; ++ fh_ep->pkt_info[i].offset = 0; ++ fh_ep->pkt_info[i].length = 0; ++ } ++} ++ ++int fh_otg_pcd_get_iso_packet_count(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle) ++{ ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep->desc || ep->fh_ep.num == 0) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ fh_ep = &ep->fh_ep; ++ ++ return fh_ep->pkt_cnt; ++} ++ ++void fh_otg_pcd_get_iso_packet_params(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, int *offset) ++{ ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ FH_WARN("bad ep\n"); ++ ++ fh_ep = &ep->fh_ep; ++ ++ *status = fh_ep->pkt_info[packet].status; ++ *actual = fh_ep->pkt_info[packet].length; ++ *offset = fh_ep->pkt_info[packet].offset; ++} ++ ++#endif /* FH_EN_ISOC */ ++ ++static void fh_otg_pcd_init_ep(fh_otg_pcd_t * pcd, fh_otg_pcd_ep_t * pcd_ep, ++ uint32_t is_in, uint32_t ep_num) ++{ ++ /* Init EP structure */ ++ pcd_ep->desc = 0; ++ pcd_ep->pcd = pcd; ++ pcd_ep->stopped = 1; ++ pcd_ep->queue_sof = 0; ++ ++ /* Init FH ep structure */ ++ pcd_ep->fh_ep.is_in = is_in; ++ pcd_ep->fh_ep.num = ep_num; ++ pcd_ep->fh_ep.active = 0; ++ pcd_ep->fh_ep.tx_fifo_num = 0; ++ /* Control until ep is actvated */ ++ pcd_ep->fh_ep.type = FH_OTG_EP_TYPE_CONTROL; ++ pcd_ep->fh_ep.maxpacket = MAX_PACKET_SIZE; ++ pcd_ep->fh_ep.dma_addr = 0; ++ pcd_ep->fh_ep.start_xfer_buff = 0; ++ pcd_ep->fh_ep.xfer_buff = 0; ++ pcd_ep->fh_ep.xfer_len = 0; ++ pcd_ep->fh_ep.xfer_count = 0; ++ pcd_ep->fh_ep.sent_zlp = 0; ++ pcd_ep->fh_ep.total_len = 0; ++ pcd_ep->fh_ep.desc_addr = 0; ++ pcd_ep->fh_ep.dma_desc_addr = 0; ++ FH_CIRCLEQ_INIT(&pcd_ep->queue); ++} ++ ++/** ++ * Initialize ep's ++ */ ++static void fh_otg_pcd_reinit(fh_otg_pcd_t * pcd) ++{ ++ int i; ++ uint32_t hwcfg1; ++ fh_otg_pcd_ep_t *ep; ++ int in_ep_cntr, out_ep_cntr; ++ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; ++ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &pcd->ep0; ++ fh_otg_pcd_init_ep(pcd, ep, 0, 0); ++ ++ in_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; ++ for (i = 1; in_ep_cntr < num_in_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ fh_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; ++ in_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ fh_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i); ++ ++ FH_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ out_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; ++ for (i = 1; out_ep_cntr < num_out_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ fh_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; ++ out_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ fh_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i); ++ FH_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ pcd->ep0state = EP0_DISCONNECT; ++ pcd->ep0.fh_ep.maxpacket = MAX_EP0_SIZE; ++ pcd->ep0.fh_ep.type = FH_OTG_EP_TYPE_CONTROL; ++} ++ ++/** ++ * This function is called when the SRP timer expires. The SRP should ++ * complete within 6 seconds. ++ */ ++static void srp_timeout(void *ptr) ++{ ++ gotgctl_data_t gotgctl; ++ fh_otg_core_if_t *core_if = (fh_otg_core_if_t *) ptr; ++ volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; ++ ++ gotgctl.d32 = FH_READ_REG32(addr); ++ ++ core_if->srp_timer_started = 0; ++ ++ if (core_if->adp_enable) { ++ if (gotgctl.b.bsesvld == 0) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ FH_PRINTF("SRP Timeout BSESSVLD = 0\n"); ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ fh_otg_adp_probe_start(core_if); ++ } else { ++ FH_PRINTF("SRP Timeout BSESSVLD = 1\n"); ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ ++ if ((core_if->core_params->phy_type == FH_PHY_TYPE_PARAM_FS) && ++ (core_if->core_params->i2c_enable)) { ++ FH_PRINTF("SRP Timeout\n"); ++ ++ if ((core_if->srp_success) && (gotgctl.b.bsesvld)) { ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32, 0); ++ ++ core_if->srp_success = 0; ++ } else { ++ __FH_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ FH_WRITE_REG32(addr, gotgctl.d32); ++ } ++ } else if (gotgctl.b.sesreq) { ++ FH_PRINTF("SRP Timeout\n"); ++ ++ __FH_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ FH_WRITE_REG32(addr, gotgctl.d32); ++ } else { ++ FH_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); ++ } ++} ++ ++/** ++ * Tasklet ++ * ++ */ ++extern void start_next_request(fh_otg_pcd_ep_t * ep); ++ ++static void start_xfer_tasklet_func(void *data) ++{ ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) data; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ int i; ++ depctl_data_t diepctl; ++ ++ FH_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); ++ ++ diepctl.d32 = FH_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0.queue_sof) { ++ pcd->ep0.queue_sof = 0; ++ start_next_request(&pcd->ep0); ++ // break; ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ depctl_data_t diepctl; ++ diepctl.d32 = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ ++ if (pcd->in_ep[i].queue_sof) { ++ pcd->in_ep[i].queue_sof = 0; ++ start_next_request(&pcd->in_ep[i]); ++ // break; ++ } ++ } ++ ++ return; ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++fh_otg_pcd_t *fh_otg_pcd_init(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_pcd_t *pcd = NULL; ++ fh_otg_dev_if_t *dev_if; ++ int i; ++ ++ /* ++ * Allocate PCD structure ++ */ ++ pcd = FH_ALLOC(sizeof(fh_otg_pcd_t)); ++ ++ if (pcd == NULL) { ++ return NULL; ++ } ++ ++ pcd->lock = FH_SPINLOCK_ALLOC(); ++ if (!pcd->lock) { ++ FH_ERROR("Could not allocate lock for pcd"); ++ FH_FREE(pcd); ++ return NULL; ++ } ++ /* Set core_if's lock pointer to hcd->lock */ ++ core_if->lock = pcd->lock; ++ pcd->core_if = core_if; ++ ++ dev_if = core_if->dev_if; ++ dev_if->isoc_ep = NULL; ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ FH_PRINTF("Dedicated Tx FIFOs mode\n"); ++ } else { ++ FH_PRINTF("Shared Tx FIFO mode\n"); ++ } ++ ++ /* ++ * Initialized the Core for Device mode here if there is nod ADP support. ++ * Otherwise it will be done later in fh_otg_adp_start routine. ++ */ ++ if (fh_otg_is_device_mode(core_if) /*&& !core_if->adp_enable */ ) { ++ fh_otg_core_dev_init(core_if); ++ } ++ ++ /* ++ * Register the PCD Callbacks. ++ */ ++ fh_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd); ++ ++ /* ++ * Initialize the DMA buffer for SETUP packets ++ */ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ pcd->setup_pkt = ++ FH_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ &pcd->setup_pkt_dma_handle); ++ if (pcd->setup_pkt == NULL) { ++ FH_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = ++ FH_DMA_ALLOC(sizeof(uint16_t), ++ &pcd->status_buf_dma_handle); ++ if (pcd->status_buf == NULL) { ++ FH_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, pcd->setup_pkt_dma_handle); ++ FH_FREE(pcd); ++ return NULL; ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dev_if->setup_desc_addr[0] = ++ fh_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[0], 1); ++ dev_if->setup_desc_addr[1] = ++ fh_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[1], 1); ++ dev_if->in_desc_addr = ++ fh_otg_ep_alloc_desc_chain ++ (&dev_if->dma_in_desc_addr, 1); ++ dev_if->out_desc_addr = ++ fh_otg_ep_alloc_desc_chain ++ (&dev_if->dma_out_desc_addr, 1); ++ pcd->data_terminated = 0; ++ ++ if (dev_if->setup_desc_addr[0] == 0 ++ || dev_if->setup_desc_addr[1] == 0 ++ || dev_if->in_desc_addr == 0 ++ || dev_if->out_desc_addr == 0) { ++ ++ if (dev_if->out_desc_addr) ++ fh_otg_ep_free_desc_chain ++ (dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, 1); ++ if (dev_if->in_desc_addr) ++ fh_otg_ep_free_desc_chain ++ (dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ if (dev_if->setup_desc_addr[1]) ++ fh_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr[1], 1); ++ if (dev_if->setup_desc_addr[0]) ++ fh_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr[0], 1); ++ ++ FH_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ FH_DMA_FREE(sizeof(*pcd->status_buf), ++ pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ ++ FH_FREE(pcd); ++ ++ return NULL; ++ } ++ } ++ } else { ++ pcd->setup_pkt = FH_ALLOC(sizeof(*pcd->setup_pkt) * 5); ++ if (pcd->setup_pkt == NULL) { ++ FH_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = FH_ALLOC(sizeof(uint16_t)); ++ if (pcd->status_buf == NULL) { ++ FH_FREE(pcd->setup_pkt); ++ FH_FREE(pcd); ++ return NULL; ++ } ++ } ++ ++ fh_otg_pcd_reinit(pcd); ++ ++ /* Allocate the cfi object for the PCD */ ++#ifdef FH_UTE_CFI ++ pcd->cfi = FH_ALLOC(sizeof(cfiobject_t)); ++ if (NULL == pcd->cfi) ++ goto fail; ++ if (init_cfi(pcd->cfi)) { ++ CFI_INFO("%s: Failed to init the CFI object\n", __func__); ++ goto fail; ++ } ++#endif ++ ++ /* Initialize tasklets */ ++ pcd->start_xfer_tasklet = FH_TASK_ALLOC("xfer_tasklet", ++ start_xfer_tasklet_func, pcd); ++ pcd->test_mode_tasklet = FH_TASK_ALLOC("test_mode_tasklet", ++ do_test_mode, pcd); ++ ++ /* Initialize SRP timer */ ++ core_if->srp_timer = FH_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); ++ ++ if (core_if->core_params->dev_out_nak) { ++ /** ++ * Initialize xfer timeout timer. Implemented for ++ * 2.93a feature "Device DDMA OUT NAK Enhancement" ++ */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ pcd->core_if->ep_xfer_timer[i] = ++ FH_TIMER_ALLOC("ep timer", ep_xfer_timeout, ++ &pcd->core_if->ep_xfer_info[i]); ++ } ++ } ++ ++ return pcd; ++#ifdef FH_UTE_CFI ++fail: ++#endif ++ if (pcd->setup_pkt) ++ FH_FREE(pcd->setup_pkt); ++ if (pcd->status_buf) ++ FH_FREE(pcd->status_buf); ++#ifdef FH_UTE_CFI ++ if (pcd->cfi) ++ FH_FREE(pcd->cfi); ++#endif ++ if (pcd) ++ FH_FREE(pcd); ++ return NULL; ++ ++} ++ ++/** ++ * Remove PCD specific data ++ */ ++void fh_otg_pcd_remove(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ int i; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ FH_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); ++ pcd->core_if->ep_xfer_info[i].state = 0; ++ } ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ FH_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ FH_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ fh_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr ++ [0], 1); ++ fh_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr ++ [1], 1); ++ fh_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ fh_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, ++ 1); ++ } ++ } else { ++ FH_FREE(pcd->setup_pkt); ++ FH_FREE(pcd->status_buf); ++ } ++ FH_SPINLOCK_FREE(pcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ pcd->core_if->lock = NULL; ++ ++ FH_TASK_FREE(pcd->start_xfer_tasklet); ++ FH_TASK_FREE(pcd->test_mode_tasklet); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ if (pcd->core_if->ep_xfer_timer[i]) { ++ FH_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); ++ } ++ } ++ } ++ ++/* Release the CFI object's dynamic memory */ ++#ifdef FH_UTE_CFI ++ if (pcd->cfi->ops.release) { ++ pcd->cfi->ops.release(pcd->cfi); ++ } ++#endif ++ ++ FH_FREE(pcd); ++} ++ ++/** ++ * Returns whether registered pcd is dual speed or not ++ */ ++uint32_t fh_otg_pcd_is_dualspeed(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ if ((core_if->core_params->speed == FH_SPEED_PARAM_FULL) || ++ ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls))) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/** ++ * Returns whether registered pcd is OTG capable or not ++ */ ++uint32_t fh_otg_pcd_is_otg(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ uint32_t retval = 0; ++ ++ usbcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->gusbcfg); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) ++ if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) ++ return 0; ++ else ++ return 1; ++# else ++ if (!usbcfg.b.srpcap) ++ return 0; ++ else ++ retval |= 1; ++ ++ if (usbcfg.b.hnpcap) ++ retval |= 2; ++ ++ if (core_if->adp_enable) ++ retval |= 4; ++#endif ++ ++ return retval; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_tx_fifo(fh_otg_core_if_t * core_if, int size) ++{ ++ uint32_t val, TxMsk = 1; ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { ++ val = (FH_READ_REG32(&core_if->core_global_regs->dtxfsiz[i]) >> 16) * 4; ++ if (((TxMsk & core_if->tx_msk) == 0) && (val >= size)) { ++ core_if->tx_msk |= TxMsk; ++ return i + 1; ++ } ++ TxMsk <<= 1; ++ } ++ FH_ERROR("No suitable TxFIFO\n"); ++ return 0; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_perio_tx_fifo(fh_otg_core_if_t * core_if, int size) ++{ ++ uint32_t val, PerTxMsk = 1; ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { ++ val = (FH_READ_REG32(&core_if->core_global_regs->dtxfsiz[i]) >> 16) * 4; ++ if (((PerTxMsk & core_if->p_tx_msk) == 0) && (val >= size)) { ++ core_if->p_tx_msk |= PerTxMsk; ++ return i + 1; ++ } ++ PerTxMsk <<= 1; ++ } ++ FH_ERROR("No suitable Periodic TxFIFO\n"); ++ return 0; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_perio_tx_fifo(fh_otg_core_if_t * core_if, ++ uint32_t fifo_num) ++{ ++ core_if->p_tx_msk = ++ (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_tx_fifo(fh_otg_core_if_t * core_if, uint32_t fifo_num) ++{ ++ core_if->tx_msk = ++ (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; ++} ++ ++/** ++ * This function is being called from gadget ++ * to enable PCD endpoint. ++ */ ++int fh_otg_pcd_ep_enable(fh_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *usb_ep) ++{ ++ int num, dir, fifo_size, nat; ++ fh_otg_pcd_ep_t *ep = NULL; ++ const usb_endpoint_descriptor_t *desc; ++ fh_irqflags_t flags; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ int retval = 0; ++ int i, epcount; ++ ++ desc = (const usb_endpoint_descriptor_t *)ep_desc; ++ ++ if (!desc) { ++ pcd->ep0.priv = usb_ep; ++ ep = &pcd->ep0; ++ retval = -FH_E_INVALID; ++ goto out; ++ } ++ ++ num = UE_GET_ADDR(desc->bEndpointAddress); ++ dir = UE_GET_DIR(desc->bEndpointAddress); ++ ++ if (!desc->wMaxPacketSize) { ++ FH_WARN("bad maxpacketsize\n"); ++ retval = -FH_E_INVALID; ++ goto out; ++ } ++ ++ if (dir == UE_DIR_IN) { ++ epcount = pcd->core_if->dev_if->num_in_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->in_ep[i].fh_ep.num) { ++ ep = &pcd->in_ep[i]; ++ break; ++ } ++ } ++ } else { ++ epcount = pcd->core_if->dev_if->num_out_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->out_ep[i].fh_ep.num) { ++ ep = &pcd->out_ep[i]; ++ break; ++ } ++ } ++ } ++ ++ if (!ep) { ++ FH_WARN("bad address\n"); ++ retval = -FH_E_INVALID; ++ goto out; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ ep->desc = desc; ++ ep->priv = usb_ep; ++ ++ /* ++ * Activate the EP ++ */ ++ ep->stopped = 0; ++ ++ ep->fh_ep.is_in = (dir == UE_DIR_IN); ++ ep->fh_ep.maxpacket = UGETW(desc->wMaxPacketSize) & 0x7ff; ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ ep->fh_ep.type = desc->bmAttributes & UE_XFERTYPE; ++ ++ if (ep->fh_ep.is_in) { ++ if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ ep->fh_ep.tx_fifo_num = 0; ++ ++ if (ep->fh_ep.type == UE_ISOCHRONOUS) { ++ /* ++ * if ISOC EP then assign a Periodic Tx FIFO. ++ */ ++ fifo_size = ep->fh_ep.maxpacket * (nat + 1); ++ ep->fh_ep.tx_fifo_num = ++ assign_perio_tx_fifo(GET_CORE_IF(pcd), fifo_size); ++ } ++ } else { ++ /* ++ * if Dedicated FIFOs mode is on then assign a Tx FIFO. ++ */ ++ fifo_size = ep->fh_ep.maxpacket; ++ ep->fh_ep.tx_fifo_num = ++ assign_tx_fifo(GET_CORE_IF(pcd), fifo_size); ++ } ++ ++ /* Calculating EP info controller base address */ ++ if (ep->fh_ep.tx_fifo_num ++ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ gdfifocfg.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ dptxfsiz.d32 = ++ (FH_READ_REG32 ++ (&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->fh_ep.tx_fifo_num - 1]) >> 16); ++ gdfifocfg.b.epinfobase = ++ gdfifocfgbase.d32 + dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ /* Set initial data PID. */ ++ if (ep->fh_ep.type == UE_BULK) { ++ ep->fh_ep.data_pid_start = 0; ++ } ++ ++ /* Alloc DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++#ifndef FH_UTE_PER_IO ++ if (ep->fh_ep.type != UE_ISOCHRONOUS) { ++#endif ++ ep->fh_ep.desc_addr = ++ fh_otg_ep_alloc_desc_chain(&ep-> ++ fh_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ if (!ep->fh_ep.desc_addr) { ++ FH_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -FH_E_SHUTDOWN; ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++#ifndef FH_UTE_PER_IO ++ } else { ++ ep->fh_ep.desc_addr = ++ fh_otg_ep_alloc_desc_chain(&ep-> ++ fh_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ ep->fh_ep.desc_addr1 = ++ fh_otg_ep_alloc_desc_chain(&ep-> ++ fh_ep.dma_desc_addr1, ++ MAX_DMA_DESC_CNT/2); ++ if (!ep->fh_ep.desc_addr || !ep->fh_ep.desc_addr1) { ++ FH_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -FH_E_SHUTDOWN; ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++ /* Set initial data PID. */ ++ if (ep->fh_ep.type == UE_ISOCHRONOUS) { ++ ep->fh_ep.iso_desc_first = 0; ++ ep->fh_ep.iso_desc_second = 0; ++ ep->fh_ep.iso_transfer_started = 0; ++ } ++ } ++#endif ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", ++ (ep->fh_ep.is_in ? "IN" : "OUT"), ++ ep->fh_ep.type, ep->fh_ep.maxpacket, ep->desc); ++#ifdef FH_UTE_PER_IO ++ ep->fh_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); ++#endif ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ ep->fh_ep.bInterval = 1 << (ep->desc->bInterval - 1); ++ ep->fh_ep.frame_num = 0xFFFFFFFF; ++ } ++ ++ fh_otg_ep_activate(GET_CORE_IF(pcd), &ep->fh_ep); ++ ++#ifdef FH_UTE_CFI ++ if (pcd->cfi->ops.ep_enable) { ++ pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep); ++ } ++#endif ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out: ++ return retval; ++} ++ ++/** ++ * This function is being called from gadget ++ * to disable PCD endpoint. ++ */ ++int fh_otg_pcd_ep_disable(fh_otg_pcd_t * pcd, void *ep_handle) ++{ ++ fh_otg_pcd_ep_t *ep; ++ fh_irqflags_t flags; ++ fh_otg_dev_dma_desc_t *desc_addr; ++ fh_dma_t dma_desc_addr; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc) { ++ FH_DEBUGPL(DBG_PCD, "bad ep address\n"); ++ return -FH_E_INVALID; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ fh_otg_request_nuke(ep); ++ ++ fh_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->fh_ep); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ FH_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->fh_ep.num]); ++ pcd->core_if->ep_xfer_info[ep->fh_ep.num].state = 0; ++ } ++ ep->desc = NULL; ++ ep->stopped = 1; ++ ++ gdfifocfg.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ ++ if (ep->fh_ep.is_in) { ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Flush the Tx FIFO */ ++ fh_otg_flush_tx_fifo(GET_CORE_IF(pcd), ++ ep->fh_ep.tx_fifo_num); ++ } ++ release_perio_tx_fifo(GET_CORE_IF(pcd), ep->fh_ep.tx_fifo_num); ++ release_tx_fifo(GET_CORE_IF(pcd), ep->fh_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Decreasing EPinfo Base Addr */ ++ dptxfsiz.d32 = ++ (FH_READ_REG32 ++ (&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->fh_ep.tx_fifo_num-1]) >> 16); ++ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ ++ /* Free DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->fh_ep.type != UE_ISOCHRONOUS) { ++ desc_addr = ep->fh_ep.desc_addr; ++ dma_desc_addr = ep->fh_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ fh_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ ++ } else { ++ desc_addr = ep->fh_ep.desc_addr; ++ dma_desc_addr = ep->fh_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ fh_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ desc_addr = ep->fh_ep.desc_addr1; ++ dma_desc_addr = ep->fh_ep.dma_desc_addr1; ++ fh_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT/2); ++ } ++ goto out_unlocked; ++ } ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out_unlocked: ++ FH_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->fh_ep.num, ++ ep->fh_ep.is_in ? "IN" : "OUT"); ++ return 0; ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain for ISOC transfers. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++void fh_otg_pcd_start_iso_ddma(fh_otg_core_if_t * core_if, fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_dev_dma_desc_t *dma_desc; ++ fh_otg_pcd_request_t *req = NULL; ++ fh_ep_t *fhep = NULL; ++ uint32_t frame_num = 0; ++ int i = 0; ++ int j; ++ int sync_request = 4; ++ uint16_t nat; ++ depctl_data_t depctl; ++ ++ fhep = &ep->fh_ep; ++ dma_desc = fhep->desc_addr; ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ FH_DEBUGPL(DBG_PCD, "nat=%u binterval =%02x\n",nat, fhep->bInterval); ++ FH_DEBUGPL(DBG_PCD, "frame_num = %d\n", fhep->frame_num); ++ ++ /* Complete first three IN EP requests for the synchronization */ ++ if (fhep->is_in) { ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ for (j = 0; j < sync_request; j++) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ FH_PRINTF("ISOC 0x%p, req = NULL!\n", ep); ++ return; ++ } else { ++ /* Complete first request */ ++ req->actual = 0; ++ fh_otg_request_done(ep, req, 0); ++ } ++ } ++ } else { ++ FH_PRINTF("ISOC ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ frame_num = fhep->frame_num + (sync_request -1)*fhep->bInterval; ++ ++ FH_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + fhep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % fhep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 0; ++ ++ if (req == FH_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_in.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ FH_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_in.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[fhep->num]->diepdma, fhep->dma_desc_addr); ++ FH_DEBUGPL(DBG_PCD, "%d ISOC IN descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->in_ep_regs[fhep->num]->diepctl, 0, depctl.d32); ++ } else { ++ FH_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ i = i+1; ++ frame_num = (frame_num + fhep->bInterval) & 0x3FFF; ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % fhep->maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 0; ++ ++ if (req == FH_CIRCLEQ_LAST(&ep->queue)) { ++ dma_desc->status.b_iso_out.l = 1; ++ } ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ FH_DEBUGPL(DBG_PCD, "ISO_DESC #%d %p status = %08x\n", i, dma_desc, dma_desc->status.d32); ++ if (i == MAX_DMA_DESC_CNT/2 - 1) { ++ dma_desc->status.b_iso_out.l = 1; ++ break; ++ } ++ dma_desc++; ++ } ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[fhep->num]->doepdma, fhep->dma_desc_addr); ++ FH_DEBUGPL(DBG_PCD, "%d ISOC OUT descs were programmed\n", i-1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->out_ep_regs[fhep->num]->doepctl, 0, depctl.d32); ++ } ++ fhep->iso_desc_first = i; //vahrama - pay attention previous one was i-1 ++ fhep->iso_transfer_started = 1; ++ fhep->frame_num = frame_num; ++ fhep->use_add_buf = 1; ++} ++/** ++ * Program next ISO request to the DMA chain ++ * ++ */ ++static void program_next_iso_request_ddma (fh_otg_pcd_ep_t * ep, fh_otg_pcd_request_t * req) ++{ ++ fh_otg_dev_dma_desc_t *dma_desc; ++ fh_dma_t dma_desc_addr; ++ uint32_t frame_num = 0; ++ uint32_t nat; ++ uint32_t index; ++ ++ FH_DEBUGPL(DBG_PCD, "%s", __FUNCTION__); ++ ++ if (ep->fh_ep.use_add_buf) { ++ index = ep->fh_ep.iso_desc_second + 1; ++ } else { ++ index = ep->fh_ep.iso_desc_first + 1; ++ } ++ ++ if (index > MAX_DMA_DESC_CNT/2) { ++ FH_PRINTF("There are no free descs in the chain!\n"); ++ return; ++ } ++ ++ if (ep->fh_ep.use_add_buf) { ++ dma_desc = &ep->fh_ep.desc_addr1[ep->fh_ep.iso_desc_second]; ++ dma_desc_addr = ep->fh_ep.dma_desc_addr1; ++ ep->fh_ep.iso_desc_second += 1; ++ } else { ++ dma_desc = &ep->fh_ep.desc_addr[ep->fh_ep.iso_desc_first]; ++ dma_desc_addr = ep->fh_ep.dma_desc_addr; ++ ep->fh_ep.iso_desc_first += 1; ++ } ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ frame_num = (ep->fh_ep.frame_num + ep->fh_ep.bInterval) & 0x3FFF; ++ if (ep->fh_ep.is_in) { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_in.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_in.txbytes = req->length; ++ dma_desc->status.b_iso_in.framenum = frame_num; ++ dma_desc->status.b_iso_in.txsts = 0; ++ dma_desc->status.b_iso_in.sp = (req->length % ep->fh_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_in.ioc = 1; ++ dma_desc->status.b_iso_in.pid = nat + 1; ++ dma_desc->status.b_iso_in.l = 1; ++ ++ dma_desc->status.b_iso_in.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_in.l = 0; ++ } ++ } else { ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b_iso_out.bs = BS_HOST_BUSY; ++ dma_desc->buf = req->dma; ++ dma_desc->status.b_iso_out.rxbytes = req->length; ++ dma_desc->status.b_iso_out.rxsts = 0; ++ dma_desc->status.b_iso_out.sp = (req->length % ep->fh_ep.maxpacket) ? 1 : 0; ++ dma_desc->status.b_iso_out.ioc = 1; ++ dma_desc->status.b_iso_out.pid = nat + 1; ++ dma_desc->status.b_iso_out.l = 1; ++ ++ dma_desc->status.b_iso_out.bs = BS_HOST_READY; ++ ++ /* Clear L bit on the previous desc of the chain */ ++ if (index > 1) { ++ dma_desc--; ++ dma_desc->status.b_iso_out.l = 0; ++ } ++ } ++ ep->fh_ep.frame_num = frame_num; ++ ++} ++ ++/******************************************************************************/ ++#ifdef FH_UTE_PER_IO ++ ++/** ++ * Free the request and its extended parts ++ * ++ */ ++void fh_pcd_xiso_ereq_free(fh_otg_pcd_ep_t * ep, fh_otg_pcd_request_t * req) ++{ ++ FH_FREE(req->ext_req.per_io_frame_descs); ++ FH_FREE(req); ++} ++ ++/** ++ * Start the next request in the endpoint's queue. ++ * ++ */ ++int fh_otg_pcd_xiso_start_next_request(fh_otg_pcd_t * pcd, ++ fh_otg_pcd_ep_t * ep) ++{ ++ int i; ++ fh_otg_pcd_request_t *req = NULL; ++ fh_ep_t *fhep = NULL; ++ struct fh_iso_xreq_port *ereq = NULL; ++ struct fh_iso_pkt_desc_port *ddesc_iso; ++ uint16_t nat; ++ depctl_data_t diepctl; ++ ++ fhep = &ep->fh_ep; ++ ++ if (fhep->xiso_active_xfers > 0) { ++#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers ++ FH_WARN("There are currently active transfers for EP%d \ ++ (active=%d; queued=%d)", fhep->num, fhep->xiso_active_xfers, ++ fhep->xiso_queued_xfers); ++#endif ++ return 0; ++ } ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ ereq = &req->ext_req; ++ ep->stopped = 0; ++ ++ /* Get the frame number */ ++ fhep->xiso_frame_num = ++ fh_otg_get_frame_number(GET_CORE_IF(pcd)); ++ FH_DEBUG("FRM_NUM=%d", fhep->xiso_frame_num); ++ ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (fhep->is_in) { ++ /* Setup DMA Descriptor chain for IN Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ if (i > 0) ++ fhep->xiso_frame_num = ++ (fhep->xiso_bInterval + ++ fhep->xiso_frame_num) & 0x3FFF; ++ fhep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ fhep->desc_addr[i].status.b_iso_in.txbytes = ++ ddesc_iso[i].length; ++ fhep->desc_addr[i].status.b_iso_in.framenum = ++ fhep->xiso_frame_num; ++ fhep->desc_addr[i].status.b_iso_in.bs = ++ BS_HOST_READY; ++ fhep->desc_addr[i].status.b_iso_in.txsts = 0; ++ fhep->desc_addr[i].status.b_iso_in.sp = ++ (ddesc_iso[i].length % ++ fhep->maxpacket) ? 1 : 0; ++ fhep->desc_addr[i].status.b_iso_in.ioc = 0; ++ fhep->desc_addr[i].status.b_iso_in.pid = nat + 1; ++ fhep->desc_addr[i].status.b_iso_in.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ fhep->desc_addr[i].status.b_iso_in.ioc = 1; ++ fhep->desc_addr[i].status.b_iso_in.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ fhep->xiso_active_xfers++; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[fhep->num]->diepdma, ++ fhep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[fhep->num]->diepctl, 0, ++ diepctl.d32); ++ } else { ++ /* Setup DMA Descriptor chain for OUT Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ fhep->xiso_frame_num = (fhep->xiso_bInterval + ++ fhep->xiso_frame_num) & 0x3FFF; ++ fhep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ fhep->desc_addr[i].status.b_iso_out.rxbytes = ++ ddesc_iso[i].length; ++ fhep->desc_addr[i].status.b_iso_out.framenum = ++ fhep->xiso_frame_num; ++ fhep->desc_addr[i].status.b_iso_out.bs = ++ BS_HOST_READY; ++ fhep->desc_addr[i].status.b_iso_out.rxsts = 0; ++ fhep->desc_addr[i].status.b_iso_out.sp = ++ (ddesc_iso[i].length % ++ fhep->maxpacket) ? 1 : 0; ++ fhep->desc_addr[i].status.b_iso_out.ioc = 0; ++ fhep->desc_addr[i].status.b_iso_out.pid = nat + 1; ++ fhep->desc_addr[i].status.b_iso_out.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ fhep->desc_addr[i].status.b_iso_out.ioc = 1; ++ fhep->desc_addr[i].status.b_iso_out.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ fhep->xiso_active_xfers++; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[fhep->num]-> ++ doepdma, fhep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[fhep->num]-> ++ doepctl, 0, diepctl.d32); ++ } ++ ++ } else { ++ ep->stopped = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * - Remove the request from the queue ++ */ ++void complete_xiso_ep(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_pcd_request_t *req = NULL; ++ struct fh_iso_xreq_port *ereq = NULL; ++ struct fh_iso_pkt_desc_port *ddesc_iso = NULL; ++ fh_ep_t *fhep = NULL; ++ int i; ++ ++ //FH_DEBUG(); ++ fhep = &ep->fh_ep; ++ ++ /* Get the first pending request from the queue */ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ FH_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ fhep->xiso_active_xfers--; ++ fhep->xiso_queued_xfers--; ++ /* Remove this request from the queue */ ++ FH_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ } else { ++ FH_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ ep->stopped = 1; ++ ereq = &req->ext_req; ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (fhep->xiso_active_xfers < 0) { ++ FH_WARN("EP#%d (xiso_active_xfers=%d)", fhep->num, ++ fhep->xiso_active_xfers); ++ } ++ ++ /* Fill the Isoc descs of portable extended req from dma descriptors */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ if (fhep->is_in) { /* IN endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ fhep->desc_addr[i].status.b_iso_in.txbytes; ++ ddesc_iso[i].status = ++ fhep->desc_addr[i].status.b_iso_in.txsts; ++ } else { /* OUT endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ fhep->desc_addr[i].status.b_iso_out.rxbytes; ++ ddesc_iso[i].status = ++ fhep->desc_addr[i].status.b_iso_out.rxsts; ++ } ++ } ++ ++ FH_SPINUNLOCK(ep->pcd->lock); ++ ++ /* Call the completion function in the non-portable logic */ ++ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, ++ &req->ext_req); ++ ++ FH_SPINLOCK(ep->pcd->lock); ++ ++ /* Free the request - specific freeing needed for extended request object */ ++ fh_pcd_xiso_ereq_free(ep, req); ++ ++ /* Start the next request */ ++ fh_otg_pcd_xiso_start_next_request(ep->pcd, ep); ++ ++ return; ++} ++ ++/** ++ * Create and initialize the Isoc pkt descriptors of the extended request. ++ * ++ */ ++static int fh_otg_pcd_xiso_create_pkt_descs(fh_otg_pcd_request_t * req, ++ void *ereq_nonport, ++ int atomic_alloc) ++{ ++ struct fh_iso_xreq_port *ereq = NULL; ++ struct fh_iso_xreq_port *req_mapped = NULL; ++ struct fh_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ ++ uint32_t pkt_count; ++ int i; ++ ++ ereq = &req->ext_req; ++ req_mapped = (struct fh_iso_xreq_port *)ereq_nonport; ++ pkt_count = req_mapped->pio_pkt_count; ++ ++ /* Create the isoc descs */ ++ if (atomic_alloc) { ++ ipds = FH_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); ++ } else { ++ ipds = FH_ALLOC(sizeof(*ipds) * pkt_count); ++ } ++ ++ if (!ipds) { ++ FH_ERROR("Failed to allocate isoc descriptors"); ++ return -FH_E_NO_MEMORY; ++ } ++ ++ /* Initialize the extended request fields */ ++ ereq->per_io_frame_descs = ipds; ++ ereq->error_count = 0; ++ ereq->pio_alloc_pkt_count = pkt_count; ++ ereq->pio_pkt_count = pkt_count; ++ ereq->tr_sub_flags = req_mapped->tr_sub_flags; ++ ++ /* Init the Isoc descriptors */ ++ for (i = 0; i < pkt_count; i++) { ++ ipds[i].length = req_mapped->per_io_frame_descs[i].length; ++ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; ++ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ ++ ipds[i].actual_length = ++ req_mapped->per_io_frame_descs[i].actual_length; ++ } ++ ++ return 0; ++} ++ ++static void prn_ext_request(struct fh_iso_xreq_port *ereq) ++{ ++ struct fh_iso_pkt_desc_port *xfd = NULL; ++ int i; ++ ++ FH_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); ++ FH_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); ++ FH_DEBUG("error_count=%d", ereq->error_count); ++ FH_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); ++ FH_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); ++ FH_DEBUG("res=%d", ereq->res); ++ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ xfd = &ereq->per_io_frame_descs[0]; ++ FH_DEBUG("FD #%d", i); ++ ++ FH_DEBUG("xfd->actual_length=%d", xfd->actual_length); ++ FH_DEBUG("xfd->length=%d", xfd->length); ++ FH_DEBUG("xfd->offset=%d", xfd->offset); ++ FH_DEBUG("xfd->status=%d", xfd->status); ++ } ++} ++ ++/** ++ * ++ */ ++int fh_otg_pcd_xiso_ep_queue(fh_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, fh_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc, ++ void *ereq_nonport) ++{ ++ fh_otg_pcd_request_t *req = NULL; ++ fh_otg_pcd_ep_t *ep; ++ fh_irqflags_t flags; ++ int res; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ ++ /* We support this extension only for DDMA mode */ ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) ++ if (!GET_CORE_IF(pcd)->dma_desc_enable) ++ return -FH_E_INVALID; ++ ++ /* Create a fh_otg_pcd_request_t object */ ++ if (atomic_alloc) { ++ req = FH_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = FH_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -FH_E_NO_MEMORY; ++ } ++ ++ /* Create the Isoc descs for this request which shall be the exact match ++ * of the structure sent to us from the non-portable logic */ ++ res = ++ fh_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); ++ if (res) { ++ FH_WARN("Failed to init the Isoc descriptors"); ++ FH_FREE(req); ++ return res; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ FH_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ ++ //FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ep->fh_ep.dma_addr = dma_buf; ++ ep->fh_ep.start_xfer_buff = buf; ++ ep->fh_ep.xfer_buff = buf; ++ ep->fh_ep.xfer_len = 0; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = buflen; ++ ++ /* Add this request to the tail */ ++ FH_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ ep->fh_ep.xiso_queued_xfers++; ++ ++//FH_DEBUG("CP_0"); ++//FH_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); ++//prn_ext_request((struct fh_iso_xreq_port *) ereq_nonport); ++//prn_ext_request(&req->ext_req); ++ ++ //FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ /* If the req->status == ASAP then check if there is any active transfer ++ * for this endpoint. If no active transfers, then get the first entry ++ * from the queue and start that transfer ++ */ ++ if (req->ext_req.tr_sub_flags == FH_EREQ_TF_ASAP) { ++ res = fh_otg_pcd_xiso_start_next_request(pcd, ep); ++ if (res) { ++ FH_WARN("Failed to start the next Isoc transfer"); ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ FH_FREE(req); ++ return res; ++ } ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return 0; ++} ++ ++#endif ++/* END ifdef FH_UTE_PER_IO ***************************************************/ ++int fh_otg_pcd_ep_queue(fh_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, fh_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc) ++{ ++ fh_irqflags_t flags; ++ fh_otg_pcd_request_t *req; ++ fh_otg_pcd_ep_t *ep; ++ uint32_t max_transfer; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->fh_ep.num != 0)) { ++ FH_WARN("bad ep\n"); ++ return -FH_E_INVALID; ++ } ++ ++ if (atomic_alloc) { ++ req = FH_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = FH_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -FH_E_NO_MEMORY; ++ } ++ FH_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ if (!GET_CORE_IF(pcd)->core_params->opt) { ++ if (ep->fh_ep.num != 0) { ++ FH_ERROR("queue req %p, len %d buf %p\n", ++ req_handle, buflen, buf); ++ } ++ } ++ ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ req->dw_align_buf = NULL; ++ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable ++ && !GET_CORE_IF(pcd)->dma_desc_enable) ++ req->dw_align_buf = FH_DMA_ALLOC(buflen, ++ &req->dw_align_buf_dma); ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++#if 0 ++ /* ++ * After adding request to the queue for IN ISOC wait for In Token Received ++ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token ++ * Received when EP is disabled interrupt to obtain starting microframe ++ * (odd/even) start transfer ++ */ ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ if (req != 0) { ++ depctl_data_t depctl = {.d32 = ++ FH_READ_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->fh_ep.num]-> ++ diepctl) }; ++ ++pcd->request_pending; ++ ++ FH_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->fh_ep.is_in) { ++ depctl.b.cnak = 1; ++ FH_WRITE_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->fh_ep.num]-> ++ diepctl, depctl.d32); ++ } ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->fh_ep.iso_transfer_started) { ++ /* ++ * Add next request to the descriptor chain ++ * currently not in use by HW ++ */ ++ program_next_iso_request_ddma(ep, req); ++ } else if (!ep->fh_ep.is_in) ++ /* For OUT start first request immediately after queue */ ++ fh_otg_pcd_start_iso_ddma(GET_CORE_IF(pcd), ep); ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return 0; ++ } ++#endif ++ /* ++ * For EP0 IN without premature status, zlp is required? ++ */ ++ if (ep->fh_ep.num == 0 && ep->fh_ep.is_in) { ++ FH_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->fh_ep.num); ++ //_req->zero = 1; ++ } ++ ++ /* Start the transfer */ ++ if (FH_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) { ++ /* EP0 Transfer? */ ++ if (ep->fh_ep.num == 0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ FH_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_DATA_PHASE\n", ++ __func__); ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ FH_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_OUT_DATA_PHASE\n", ++ __func__); ++ if (pcd->request_config) { ++ /* Complete STATUS PHASE */ ++ ep->fh_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ FH_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_STATUS_PHASE\n", ++ __func__); ++ break; ++ ++ default: ++ FH_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", ++ pcd->ep0state); ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -FH_E_SHUTDOWN; ++ } ++ ++ ep->fh_ep.dma_addr = dma_buf; ++ ep->fh_ep.start_xfer_buff = buf; ++ ep->fh_ep.xfer_buff = buf; ++ ep->fh_ep.xfer_len = buflen; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = ep->fh_ep.xfer_len; ++ ++ if (zero) { ++ if ((ep->fh_ep.xfer_len % ++ ep->fh_ep.maxpacket == 0) ++ && (ep->fh_ep.xfer_len != 0)) { ++ ep->fh_ep.sent_zlp = 1; ++ } ++ ++ } ++ ++ fh_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep->fh_ep); ++ } // non-ep0 endpoints ++ else { ++#ifdef FH_UTE_CFI ++ if (ep->fh_ep.buff_mode != BM_STANDARD) { ++ /* store the request length */ ++ ep->fh_ep.cfi_req_len = buflen; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ++ ep, req); ++ } else { ++#endif ++ max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params-> ++ max_transfer_size; ++ ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ if (ep->fh_ep.is_in) ++ fh_memcpy(req->dw_align_buf, ++ buf, buflen); ++ ep->fh_ep.dma_addr = ++ req->dw_align_buf_dma; ++ ep->fh_ep.start_xfer_buff = ++ req->dw_align_buf; ++ ep->fh_ep.xfer_buff = ++ req->dw_align_buf; ++ } else { ++ ep->fh_ep.dma_addr = dma_buf; ++ ep->fh_ep.start_xfer_buff = buf; ++ ep->fh_ep.xfer_buff = buf; ++ } ++ ep->fh_ep.xfer_len = 0; ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = buflen; ++ ++ ep->fh_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = ++ DDMA_MAX_TRANSFER_SIZE - ++ (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->fh_ep.is_in) { ++ if (ep->fh_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->fh_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->fh_ep.maxxfer > ++ out_max_xfer) { ++ ep->fh_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->fh_ep.maxxfer < ep->fh_ep.total_len) { ++ ep->fh_ep.maxxfer -= ++ (ep->fh_ep.maxxfer % ++ ep->fh_ep.maxpacket); ++ } ++ ++ if (zero) { ++ if ((ep->fh_ep.total_len % ++ ep->fh_ep.maxpacket == 0) ++ && (ep->fh_ep.total_len != 0)) { ++ ep->fh_ep.sent_zlp = 1; ++ } ++ } ++#ifdef FH_UTE_CFI ++ } ++#endif ++ fh_otg_ep_start_transfer(GET_CORE_IF(pcd), ++ &ep->fh_ep); ++ } ++ } ++ ++ if (req != 0) { ++ ++pcd->request_pending; ++ FH_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->fh_ep.is_in && ep->stopped ++ && !(GET_CORE_IF(pcd)->dma_enable)) { ++ /** @todo NGS Create a function for this. */ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ if (GET_CORE_IF(pcd)->multiproc_int_enable) { ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs->diepeachintmsk ++ [ep->fh_ep.num], 0, ++ diepmsk.d32); ++ } else { ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs-> ++ diepmsk, 0, diepmsk.d32); ++ } ++ ++ } ++ } ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return 0; ++} ++ ++int fh_otg_pcd_ep_dequeue(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ fh_irqflags_t flags; ++ fh_otg_pcd_request_t *req; ++ fh_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->fh_ep.num != 0)) { ++ FH_WARN("bad argument\n"); ++ return -FH_E_INVALID; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* make sure it's actually queued on this endpoint */ ++ FH_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ if (req->priv == (void *)req_handle) { ++ break; ++ } ++ } ++ ++ if (req->priv != (void *)req_handle) { ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -FH_E_INVALID; ++ } ++ ++ if (!FH_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { ++ fh_otg_request_done(ep, req, -FH_E_RESTART); ++ } else { ++ req = NULL; ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return req ? 0 : -FH_E_SHUTDOWN; ++ ++} ++ ++int fh_otg_pcd_ep_halt(fh_otg_pcd_t * pcd, void *ep_handle, int value) ++{ ++ fh_otg_pcd_ep_t *ep; ++ fh_irqflags_t flags; ++ int retval = 0; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || (!ep->desc && ep != &pcd->ep0) || ++ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { ++ FH_WARN("%s, bad ep\n", __func__); ++ return -FH_E_INVALID; ++ } ++ ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ FH_WARN("%d %s XFer In process\n", ep->fh_ep.num, ++ ep->fh_ep.is_in ? "IN" : "OUT"); ++ retval = -FH_E_AGAIN; ++ } else if (value == 0) { ++ ep->fh_ep.stall_clear_flag = 0; ++ fh_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->fh_ep); ++ } else if (value == 1) { ++ stall: ++ if (ep->fh_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { ++ dtxfsts_data_t txstatus; ++ fifosize_data_t txfifosize; ++ ++ txfifosize.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->fh_ep. ++ tx_fifo_num]); ++ txstatus.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->in_ep_regs[ep->fh_ep.num]-> ++ dtxfsts); ++ ++ if (txstatus.b.txfspcavail < txfifosize.b.depth) { ++ FH_WARN("%s() Data In Tx Fifo\n", __func__); ++ retval = -FH_E_AGAIN; ++ } else { ++ if (ep->fh_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ fh_otg_ep_set_stall(GET_CORE_IF(pcd), ++ &ep->fh_ep); ++ } ++ } else { ++ if (ep->fh_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ fh_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->fh_ep); ++ } ++ } else if (value == 2) { ++ ep->fh_ep.stall_clear_flag = 0; ++ } else if (value == 3) { ++ ep->fh_ep.stall_clear_flag = 1; ++ goto stall; ++ } ++ ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return retval; ++} ++ ++/** ++ * This function initiates remote wakeup of the host from suspend state. ++ */ ++void fh_otg_pcd_rem_wkup_from_suspend(fh_otg_pcd_t * pcd, int set) ++{ ++ dctl_data_t dctl = { 0 }; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dsts_data_t dsts; ++ ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ if (!dsts.b.suspsts) { ++ FH_WARN("Remote wakeup while is not in suspend state\n"); ++ } ++ /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ ++ if (pcd->remote_wakeup_enable) { ++ if (set) { ++ ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn; ++ ++ fh_otg_adp_probe_stop(core_if); ++ ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ FH_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ fh_otg_core_init(core_if); ++ fh_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ fh_otg_initiate_srp(core_if); ++ } ++ ++ dctl.b.rmtwkupsig = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ FH_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ ++ fh_mdelay(2); ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ FH_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); ++ } ++ } else { ++ FH_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); ++ } ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++/** ++ * This function initiates remote wakeup of the host from L1 sleep state. ++ */ ++void fh_otg_pcd_rem_wkup_from_sleep(fh_otg_pcd_t * pcd, int set) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ /* Check if we are in L1 state */ ++ if (!lpmcfg.b.prt_sleep_sts) { ++ FH_DEBUGPL(DBG_PCD, "Device is not in sleep state\n"); ++ return; ++ } ++ ++ /* Check if host allows remote wakeup */ ++ if (!lpmcfg.b.rem_wkup_en) { ++ FH_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n"); ++ return; ++ } ++ ++ /* Check if Resume OK */ ++ if (!lpmcfg.b.sleep_state_resumeok) { ++ FH_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n"); ++ return; ++ } ++ ++ lpmcfg.d32 = FH_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,0); ++ ++ FH_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ if (set) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.rmtwkupsig = 1; ++ /* Set RmtWkUpSig bit to start remote wakup signaling. ++ * Hardware will automatically clear this bit. ++ */ ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ FH_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ } ++ ++} ++#endif ++ ++/** ++ * Performs remote wakeup. ++ */ ++void fh_otg_pcd_remote_wakeup(fh_otg_pcd_t * pcd, int set) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_irqflags_t flags; ++ if (fh_otg_is_device_mode(core_if)) { ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ if (core_if->lx_state == FH_OTG_L1) { ++ fh_otg_pcd_rem_wkup_from_sleep(pcd, set); ++ } else { ++#endif ++ fh_otg_pcd_rem_wkup_from_suspend(pcd, set); ++#ifdef CONFIG_USB_FH_OTG_LPM ++ } ++#endif ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return; ++} ++ ++void fh_otg_pcd_disconnect_us(fh_otg_pcd_t * pcd, int no_of_usecs) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = { 0 }; ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ FH_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ fh_udelay(no_of_usecs); ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); ++ ++ } else{ ++ FH_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ return; ++ ++} ++ ++void fh_otg_pcd_disconnect_soft(fh_otg_pcd_t *pcd, int ctrl_flag) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = {0}; ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ if (ctrl_flag) ++ FH_MODIFY_REG32( ++ &core_if->dev_if->dev_global_regs->dctl, ++ 0, ++ dctl.d32); ++ else ++ FH_MODIFY_REG32( ++ &core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32, ++ 0); ++ } else { ++ FH_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ ++ return; ++} ++ ++int fh_otg_pcd_wakeup(fh_otg_pcd_t * pcd) ++{ ++ dsts_data_t dsts; ++ gotgctl_data_t gotgctl; ++ ++ /* ++ * This function starts the Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++ ++ /* Check if valid session */ ++ gotgctl.d32 = ++ FH_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); ++ if (gotgctl.b.bsesvld) { ++ /* Check if suspend state */ ++ dsts.d32 = ++ FH_READ_REG32(& ++ (GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts)); ++ if (dsts.b.suspsts) { ++ fh_otg_pcd_remote_wakeup(pcd, 1); ++ } ++ } else { ++ fh_otg_pcd_initiate_srp(pcd); ++ } ++ ++ return 0; ++ ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param pcd the pcd structure. ++ */ ++void fh_otg_pcd_initiate_srp(fh_otg_pcd_t * pcd) ++{ ++ fh_irqflags_t flags; ++ FH_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ fh_otg_initiate_srp(GET_CORE_IF(pcd)); ++ FH_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++} ++ ++int fh_otg_pcd_get_frame_number(fh_otg_pcd_t * pcd) ++{ ++ return fh_otg_get_frame_number(GET_CORE_IF(pcd)); ++} ++ ++int fh_otg_pcd_is_lpm_enabled(fh_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->lpm_enable; ++} ++ ++int fh_otg_pcd_is_besl_enabled(fh_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->besl_enable; ++} ++ ++int fh_otg_pcd_get_param_baseline_besl(fh_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->baseline_besl; ++} ++ ++int fh_otg_pcd_get_param_deep_besl(fh_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->deep_besl; ++} ++ ++uint32_t get_b_hnp_enable(fh_otg_pcd_t * pcd) ++{ ++ return pcd->b_hnp_enable; ++} ++ ++uint32_t get_a_hnp_support(fh_otg_pcd_t * pcd) ++{ ++ return pcd->a_hnp_support; ++} ++ ++uint32_t get_a_alt_hnp_support(fh_otg_pcd_t * pcd) ++{ ++ return pcd->a_alt_hnp_support; ++} ++ ++int fh_otg_pcd_get_rmwkup_enable(fh_otg_pcd_t * pcd) ++{ ++ return pcd->remote_wakeup_enable; ++} ++ ++#endif /* FH_HOST_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.h +new file mode 100644 +index 00000000..1d2a66bd +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd.h +@@ -0,0 +1,268 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_pcd.h $ ++ * $Revision: #49 $ ++ * $Date: 2013/05/16 $ ++ * $Change: 2231774 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_HOST_ONLY ++#if !defined(__FH_PCD_H__) ++#define __FH_PCD_H__ ++ ++#include "fh_otg_os_dep.h" ++#include "../fh_common_port/usb.h" ++#include "fh_otg_cil.h" ++#include "fh_otg_pcd_if.h" ++struct cfiobject; ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Perpherial Contoller Driver (PCD). ++ * ++ * The Peripheral Controller Driver (PCD) for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. For ++ * the Mass Storage Function driver the File-backed USB Storage Gadget ++ * (FBS) driver will be used. The FBS driver supports the ++ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only ++ * transports. ++ * ++ */ ++ ++/** Invalid DMA Address */ ++#define FH_DMA_ADDR_INVALID (~(fh_dma_t)0) ++ ++/** Max Transfer size for any EP */ ++#define DDMA_MAX_TRANSFER_SIZE 65535 ++ ++/** ++ * Get the pointer to the core_if from the pcd pointer. ++ */ ++#define GET_CORE_IF( _pcd ) (_pcd->core_if) ++ ++/** ++ * States of EP0. ++ */ ++typedef enum ep0_state { ++ EP0_DISCONNECT, /* no host */ ++ EP0_IDLE, ++ EP0_IN_DATA_PHASE, ++ EP0_OUT_DATA_PHASE, ++ EP0_IN_STATUS_PHASE, ++ EP0_OUT_STATUS_PHASE, ++ EP0_STALL, ++} ep0state_e; ++ ++/** Fordward declaration.*/ ++struct fh_otg_pcd; ++ ++/** FH_otg iso request structure. ++ * ++ */ ++typedef struct usb_iso_request fh_otg_pcd_iso_request_t; ++ ++#ifdef FH_UTE_PER_IO ++ ++/** ++ * This shall be the exact analogy of the same type structure defined in the ++ * usb_gadget.h. Each descriptor contains ++ */ ++struct fh_iso_pkt_desc_port { ++ uint32_t offset; ++ uint32_t length; /* expected length */ ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct fh_iso_xreq_port { ++ /** transfer/submission flag */ ++ uint32_t tr_sub_flags; ++ /** Start the request ASAP */ ++#define FH_EREQ_TF_ASAP 0x00000002 ++ /** Just enqueue the request w/o initiating a transfer */ ++#define FH_EREQ_TF_ENQUEUE 0x00000004 ++ ++ /** ++ * count of ISO packets attached to this request - shall ++ * not exceed the pio_alloc_pkt_count ++ */ ++ uint32_t pio_pkt_count; ++ /** count of ISO packets allocated for this request */ ++ uint32_t pio_alloc_pkt_count; ++ /** number of ISO packet errors */ ++ uint32_t error_count; ++ /** reserved for future extension */ ++ uint32_t res; ++ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ ++ struct fh_iso_pkt_desc_port *per_io_frame_descs; ++}; ++#endif ++/** FH_otg request structure. ++ * This structure is a list of requests. ++ */ ++typedef struct fh_otg_pcd_request { ++ void *priv; ++ void *buf; ++ fh_dma_t dma; ++ uint32_t length; ++ uint32_t actual; ++ unsigned sent_zlp:1; ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ **/ ++ uint8_t *dw_align_buf; ++ fh_dma_t dw_align_buf_dma; ++ ++ FH_CIRCLEQ_ENTRY(fh_otg_pcd_request) queue_entry; ++#ifdef FH_UTE_PER_IO ++ struct fh_iso_xreq_port ext_req; ++ //void *priv_ereq_nport; /* */ ++#endif ++} fh_otg_pcd_request_t; ++ ++FH_CIRCLEQ_HEAD(req_list, fh_otg_pcd_request); ++ ++/** PCD EP structure. ++ * This structure describes an EP, there is an array of EPs in the PCD ++ * structure. ++ */ ++typedef struct fh_otg_pcd_ep { ++ /** USB EP Descriptor */ ++ const usb_endpoint_descriptor_t *desc; ++ ++ /** queue of fh_otg_pcd_requests. */ ++ struct req_list queue; ++ unsigned stopped:1; ++ unsigned disabling:1; ++ unsigned dma:1; ++ unsigned queue_sof:1; ++ ++#ifdef FH_EN_ISOC ++ /** ISOC req handle passed */ ++ void *iso_req_handle; ++#endif //_EN_ISOC_ ++ ++ /** FH_otg ep data. */ ++ fh_ep_t fh_ep; ++ ++ /** Pointer to PCD */ ++ struct fh_otg_pcd *pcd; ++ ++ void *priv; ++} fh_otg_pcd_ep_t; ++ ++/** FH_otg PCD Structure. ++ * This structure encapsulates the data for the fh_otg PCD. ++ */ ++struct fh_otg_pcd { ++ const struct fh_otg_pcd_function_ops *fops; ++ /** The FH otg device pointer */ ++ struct fh_otg_device *otg_dev; ++ /** Core Interface */ ++ fh_otg_core_if_t *core_if; ++ /** State of EP0 */ ++ ep0state_e ep0state; ++ /** EP0 Request is pending */ ++ unsigned ep0_pending:1; ++ /** Indicates when SET CONFIGURATION Request is in process */ ++ unsigned request_config:1; ++ /** The state of the Remote Wakeup Enable. */ ++ unsigned remote_wakeup_enable:1; ++ /** The state of the B-Device HNP Enable. */ ++ unsigned b_hnp_enable:1; ++ /** The state of A-Device HNP Support. */ ++ unsigned a_hnp_support:1; ++ /** The state of the A-Device Alt HNP support. */ ++ unsigned a_alt_hnp_support:1; ++ /** Count of pending Requests */ ++ unsigned request_pending; ++ ++ /** SETUP packet for EP0 ++ * This structure is allocated as a DMA buffer on PCD initialization ++ * with enough space for up to 3 setup packets. ++ */ ++ union { ++ usb_device_request_t req; ++ uint32_t d32[2]; ++ } *setup_pkt; ++ ++ fh_dma_t setup_pkt_dma_handle; ++ ++ /* Additional buffer and flag for CTRL_WR premature case */ ++ uint8_t *backup_buf; ++ unsigned data_terminated; ++ ++ /** 2-byte dma buffer used to return status from GET_STATUS */ ++ uint16_t *status_buf; ++ fh_dma_t status_buf_dma_handle; ++ ++ /** EP0 */ ++ fh_otg_pcd_ep_t ep0; ++ ++ /** Array of IN EPs. */ ++ fh_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1]; ++ /** Array of OUT EPs. */ ++ fh_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1]; ++ /** number of valid EPs in the above array. */ ++// unsigned num_eps : 4; ++ fh_spinlock_t *lock; ++ ++ /** Tasklet to defer starting of TEST mode transmissions until ++ * Status Phase has been completed. ++ */ ++ fh_tasklet_t *test_mode_tasklet; ++ ++ /** Tasklet to delay starting of xfer in DMA mode */ ++ fh_tasklet_t *start_xfer_tasklet; ++ ++ /** The test mode to enter when the tasklet is executed. */ ++ unsigned test_mode; ++ /** The cfi_api structure that implements most of the CFI API ++ * and OTG specific core configuration functionality ++ */ ++#ifdef FH_UTE_CFI ++ struct cfiobject *cfi; ++#endif ++ ++}; ++ ++//FIXME this functions should be static, and this prototypes should be removed ++extern void fh_otg_request_nuke(fh_otg_pcd_ep_t * ep); ++extern void fh_otg_request_done(fh_otg_pcd_ep_t * ep, ++ fh_otg_pcd_request_t * req, int32_t status); ++ ++void fh_otg_iso_buffer_done(fh_otg_pcd_t * pcd, fh_otg_pcd_ep_t * ep, ++ void *req_handle); ++extern void fh_otg_pcd_start_iso_ddma(fh_otg_core_if_t * core_if, ++ fh_otg_pcd_ep_t * ep); ++ ++extern void do_test_mode(void *data); ++#endif ++#endif /* FH_HOST_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_if.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_if.h +new file mode 100644 +index 00000000..2bfa526f +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_if.h +@@ -0,0 +1,368 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_pcd_if.h $ ++ * $Revision: #13 $ ++ * $Date: 2012/12/12 $ ++ * $Change: 2125019 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_HOST_ONLY ++ ++#if !defined(__FH_PCD_IF_H__) ++#define __FH_PCD_IF_H__ ++ ++//#include "fh_os.h" ++#include "fh_otg_core_if.h" ++ ++/** @file ++ * This file defines FH_OTG PCD Core API. ++ */ ++ ++struct fh_otg_pcd; ++typedef struct fh_otg_pcd fh_otg_pcd_t; ++ ++/** Maxpacket size for EP0 */ ++#define MAX_EP0_SIZE 64 ++/** Maxpacket size for any EP */ ++#define MAX_PACKET_SIZE 1024 ++ ++/** @name Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function will be called whenever a previously queued request has ++ * completed. The status value will be set to -FH_E_SHUTDOWN to indicated a ++ * failed or aborted transfer, or -FH_E_RESTART to indicate the device was reset, ++ * or -FH_E_TIMEOUT to indicate it timed out, or -FH_E_INVALID to indicate invalid ++ * parameters. */ ++typedef int (*fh_completion_cb_t) (fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ uint32_t actual); ++/** ++ * This function will be called whenever a previousle queued ISOC request has ++ * completed. Count of ISOC packets could be read using fh_otg_pcd_get_iso_packet_count ++ * function. ++ * The status of each ISOC packet could be read using fh_otg_pcd_get_iso_packet_* ++ * functions. ++ */ ++typedef int (*fh_isoc_completion_cb_t) (fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num); ++/** This function should handle any SETUP request that cannot be handled by the ++ * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any ++ * class-specific requests, etc. The function must non-blocking. ++ * ++ * Returns 0 on success. ++ * Returns -FH_E_NOT_SUPPORTED if the request is not supported. ++ * Returns -FH_E_INVALID if the setup request had invalid parameters or bytes. ++ * Returns -FH_E_SHUTDOWN on any other error. */ ++typedef int (*fh_setup_cb_t) (fh_otg_pcd_t * pcd, uint8_t * bytes); ++/** This is called whenever the device has been disconnected. The function ++ * driver should take appropriate action to clean up all pending requests in the ++ * PCD Core, remove all endpoints (except ep0), and initialize back to reset ++ * state. */ ++typedef int (*fh_disconnect_cb_t) (fh_otg_pcd_t * pcd); ++/** This function is called when device has been connected. */ ++typedef int (*fh_connect_cb_t) (fh_otg_pcd_t * pcd, int speed); ++/** This function is called when device has been suspended */ ++typedef int (*fh_suspend_cb_t) (fh_otg_pcd_t * pcd); ++/** This function is called when device has received LPM tokens, i.e. ++ * device has been sent to sleep state. */ ++typedef int (*fh_sleep_cb_t) (fh_otg_pcd_t * pcd); ++/** This function is called when device has been resumed ++ * from suspend(L2) or L1 sleep state. */ ++typedef int (*fh_resume_cb_t) (fh_otg_pcd_t * pcd); ++/** This function is called whenever hnp params has been changed. ++ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions ++ * to get hnp parameters. */ ++typedef int (*fh_hnp_params_changed_cb_t) (fh_otg_pcd_t * pcd); ++/** This function is called whenever USB RESET is detected. */ ++typedef int (*fh_reset_cb_t) (fh_otg_pcd_t * pcd); ++ ++typedef int (*cfi_setup_cb_t) (fh_otg_pcd_t * pcd, void *ctrl_req_bytes); ++ ++/** ++ * ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param ereq_port Pointer to the extended request structure created in the ++ * portable part. ++ */ ++typedef int (*xiso_completion_cb_t) (fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ void *ereq_port); ++/** Function Driver Ops Data Structure */ ++struct fh_otg_pcd_function_ops { ++ fh_connect_cb_t connect; ++ fh_disconnect_cb_t disconnect; ++ fh_setup_cb_t setup; ++ fh_completion_cb_t complete; ++ fh_isoc_completion_cb_t isoc_complete; ++ fh_suspend_cb_t suspend; ++ fh_sleep_cb_t sleep; ++ fh_resume_cb_t resume; ++ fh_reset_cb_t reset; ++ fh_hnp_params_changed_cb_t hnp_changed; ++ cfi_setup_cb_t cfi_setup; ++#ifdef FH_UTE_PER_IO ++ xiso_completion_cb_t xisoc_complete; ++#endif ++}; ++/** @} */ ++ ++/** @name Function Driver Functions */ ++/** @{ */ ++ ++/** Call this function to get pointer on fh_otg_pcd_t, ++ * this pointer will be used for all PCD API functions. ++ * ++ * @param core_if The FH_OTG Core ++ */ ++extern fh_otg_pcd_t *fh_otg_pcd_init(fh_otg_core_if_t * core_if); ++ ++/** Frees PCD allocated by fh_otg_pcd_init ++ * ++ * @param pcd The PCD ++ */ ++extern void fh_otg_pcd_remove(fh_otg_pcd_t * pcd); ++ ++/** Call this to bind the function driver to the PCD Core. ++ * ++ * @param pcd Pointer on fh_otg_pcd_t returned by fh_otg_pcd_init function. ++ * @param fops The Function Driver Ops data structure containing pointers to all callbacks. ++ */ ++extern void fh_otg_pcd_start(fh_otg_pcd_t * pcd, ++ const struct fh_otg_pcd_function_ops *fops); ++ ++/** Enables an endpoint for use. This function enables an endpoint in ++ * the PCD. The endpoint is described by the ep_desc which has the ++ * same format as a USB ep descriptor. The ep_handle parameter is used to refer ++ * to the endpoint from other API functions and in callbacks. Normally this ++ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the ++ * core for that interface. ++ * ++ * Returns -FH_E_INVALID if invalid parameters were passed. ++ * Returns -FH_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. ++ * ++ * @param pcd The PCD ++ * @param ep_desc Endpoint descriptor ++ * @param ep_handle Handle on endpoint, that will be used to identify endpoint. ++ */ ++extern int fh_otg_pcd_ep_enable(fh_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *ep_handle); ++ ++/** Disable the endpoint referenced by ep_handle. ++ * ++ * Returns -FH_E_INVALID if invalid parameters were passed. ++ * Returns -FH_E_SHUTDOWN if any other error occurred. ++ * Returns 0 on success. */ ++extern int fh_otg_pcd_ep_disable(fh_otg_pcd_t * pcd, void *ep_handle); ++ ++/** Queue a data transfer request on the endpoint referenced by ep_handle. ++ * After the transfer is completes, the complete callback will be called with ++ * the request status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf The buffer for the data ++ * @param dma_buf The DMA buffer for the data ++ * @param buflen The length of the data transfer ++ * @param zero Specifies whether to send zero length last packet. ++ * @param req_handle Set this handle to any value to use to reference this ++ * request in the ep_dequeue function or from the complete callback ++ * @param atomic_alloc If driver need to perform atomic allocations ++ * for internal data structures. ++ * ++ * Returns -FH_E_INVALID if invalid parameters were passed. ++ * Returns -FH_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int fh_otg_pcd_ep_queue(fh_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, fh_dma_t dma_buf, ++ uint32_t buflen, int zero, void *req_handle, ++ int atomic_alloc); ++#ifdef FH_UTE_PER_IO ++/** ++ * ++ * @param ereq_nonport Pointer to the extended request part of the ++ * usb_request structure defined in usb_gadget.h file. ++ */ ++extern int fh_otg_pcd_xiso_ep_queue(fh_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, fh_dma_t dma_buf, ++ uint32_t buflen, int zero, ++ void *req_handle, int atomic_alloc, ++ void *ereq_nonport); ++ ++#endif ++ ++/** De-queue the specified data transfer that has not yet completed. ++ * ++ * Returns -FH_E_INVALID if invalid parameters were passed. ++ * Returns -FH_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int fh_otg_pcd_ep_dequeue(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Halt (STALL) an endpoint or clear it. ++ * ++ * Returns -FH_E_INVALID if invalid parameters were passed. ++ * Returns -FH_E_SHUTDOWN if any other error ocurred. ++ * Returns -FH_E_AGAIN if the STALL cannot be sent and must be tried again later ++ * Returns 0 on success. */ ++extern int fh_otg_pcd_ep_halt(fh_otg_pcd_t * pcd, void *ep_handle, int value); ++ ++/** This function should be called on every hardware interrupt */ ++extern int32_t fh_otg_pcd_handle_intr(fh_otg_pcd_t * pcd); ++ ++/** This function returns current frame number */ ++extern int fh_otg_pcd_get_frame_number(fh_otg_pcd_t * pcd); ++ ++/** ++ * Start isochronous transfers on the endpoint referenced by ep_handle. ++ * For isochronous transfers duble buffering is used. ++ * After processing each of buffers comlete callback will be called with ++ * status for each transaction. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf0 The virtual address of first data buffer ++ * @param buf1 The virtual address of second data buffer ++ * @param dma0 The DMA address of first data buffer ++ * @param dma1 The DMA address of second data buffer ++ * @param sync_frame Data pattern frame number ++ * @param dp_frame Data size for pattern frame ++ * @param data_per_frame Data size for regular frame ++ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP. ++ * @param buf_proc_intrvl Interval of ISOC Buffer processing ++ * @param req_handle Handle of ISOC request ++ * @param atomic_alloc Specefies whether to perform atomic allocation for ++ * internal data structures. ++ * ++ * Returns -FH_E_NO_MEMORY if there is no enough memory. ++ * Returns -FH_E_INVALID if incorrect arguments are passed to the function. ++ * Returns -DW_E_SHUTDOWN for any other error. ++ * Returns 0 on success ++ */ ++//extern int fh_otg_pcd_iso_ep_start(fh_otg_pcd_t * pcd, void *ep_handle, ++// uint8_t * buf0, uint8_t * buf1, ++// fh_dma_t dma0, fh_dma_t dma1, ++// int sync_frame, int dp_frame, ++// int data_per_frame, int start_frame, ++// int buf_proc_intrvl, void *req_handle, ++// int atomic_alloc); ++ ++/** Stop ISOC transfers on endpoint referenced by ep_handle. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param req_handle Handle of ISOC request ++ * ++ * Returns -FH_E_INVALID if incorrect arguments are passed to the function ++ * Returns 0 on success ++ */ ++int fh_otg_pcd_iso_ep_stop(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Get ISOC packet status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle Isochronoush request handle ++ * @param packet Number of packet ++ * @param status Out parameter for returning status ++ * @param actual Out parameter for returning actual length ++ * @param offset Out parameter for returning offset ++ * ++ */ ++extern void fh_otg_pcd_get_iso_packet_params(fh_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, ++ int *offset); ++ ++/** Get ISOC packet count. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle ++ */ ++extern int fh_otg_pcd_get_iso_packet_count(fh_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle); ++ ++/** This function starts the SRP Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++extern int fh_otg_pcd_wakeup(fh_otg_pcd_t * pcd); ++ ++/** This function returns 1 if LPM support is enabled, and 0 otherwise. */ ++extern int fh_otg_pcd_is_lpm_enabled(fh_otg_pcd_t * pcd); ++ ++/** This function returns 1 if LPM Errata support is enabled, and 0 otherwise. */ ++extern int fh_otg_pcd_is_besl_enabled(fh_otg_pcd_t * pcd); ++ ++/** This function returns baseline_besl module parametr. */ ++extern int fh_otg_pcd_get_param_baseline_besl(fh_otg_pcd_t * pcd); ++ ++/** This function returns deep_besl module parametr. */ ++extern int fh_otg_pcd_get_param_deep_besl(fh_otg_pcd_t * pcd); ++ ++/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */ ++extern int fh_otg_pcd_get_rmwkup_enable(fh_otg_pcd_t * pcd); ++ ++/** Initiate SRP */ ++extern void fh_otg_pcd_initiate_srp(fh_otg_pcd_t * pcd); ++ ++/** Starts remote wakeup signaling. */ ++extern void fh_otg_pcd_remote_wakeup(fh_otg_pcd_t * pcd, int set); ++ ++/** Starts micorsecond soft disconnect. */ ++extern void fh_otg_pcd_disconnect_us(fh_otg_pcd_t * pcd, int no_of_usecs); ++/** soft ctrl disconnect. */ ++extern void fh_otg_pcd_disconnect_soft(fh_otg_pcd_t *pcd, int ctrl_flag); ++/** This function returns whether device is dualspeed.*/ ++extern uint32_t fh_otg_pcd_is_dualspeed(fh_otg_pcd_t * pcd); ++ ++/** This function returns whether device is otg. */ ++extern uint32_t fh_otg_pcd_is_otg(fh_otg_pcd_t * pcd); ++ ++/** These functions allow to get hnp parameters */ ++extern uint32_t get_b_hnp_enable(fh_otg_pcd_t * pcd); ++extern uint32_t get_a_hnp_support(fh_otg_pcd_t * pcd); ++extern uint32_t get_a_alt_hnp_support(fh_otg_pcd_t * pcd); ++ ++/** CFI specific Interface functions */ ++/** Allocate a cfi buffer */ ++//extern uint8_t *cfiw_ep_alloc_buffer(fh_otg_pcd_t * pcd, void *pep, ++// fh_dma_t * addr, size_t buflen, ++// int flags); ++ ++/******************************************************************************/ ++ ++/** @} */ ++ ++#endif /* __FH_PCD_IF_H__ */ ++ ++#endif /* FH_HOST_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_intr.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_intr.c +new file mode 100644 +index 00000000..9b51a3cd +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_intr.c +@@ -0,0 +1,5430 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_pcd_intr.c $ ++ * $Revision: #126 $ ++ * $Date: 2014/08/25 $ ++ * $Change: 2595073 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_HOST_ONLY ++ ++#include "fh_otg_pcd.h" ++ ++#ifdef FH_UTE_CFI ++#include "fh_otg_cfi.h" ++#endif ++ ++#ifdef FH_UTE_PER_IO ++extern void complete_xiso_ep(fh_otg_pcd_ep_t * ep); ++#endif ++//#define PRINT_CFI_DMA_DESCS ++ ++#define DEBUG_EP0 ++ ++/** ++ * This function updates OTG. ++ */ ++static void fh_otg_pcd_update_otg(fh_otg_pcd_t * pcd, const unsigned reset) ++{ ++ ++ if (reset) { ++ pcd->b_hnp_enable = 0; ++ pcd->a_hnp_support = 0; ++ pcd->a_alt_hnp_support = 0; ++ } ++ ++ if (pcd->fops->hnp_changed) { ++ pcd->fops->hnp_changed(pcd); ++ } ++} ++ ++/** @file ++ * This file contains the implementation of the PCD Interrupt handlers. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * All interrupt registers are processed from LSB to MSB. ++ */ ++ ++/** ++ * This function prints the ep0 state for debug purposes. ++ */ ++static inline void print_ep0_state(fh_otg_pcd_t * pcd) ++{ ++#ifdef DEBUG ++ char str[40]; ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ fh_strcpy(str, "EP0_DISCONNECT"); ++ break; ++ case EP0_IDLE: ++ fh_strcpy(str, "EP0_IDLE"); ++ break; ++ case EP0_IN_DATA_PHASE: ++ fh_strcpy(str, "EP0_IN_DATA_PHASE"); ++ break; ++ case EP0_OUT_DATA_PHASE: ++ fh_strcpy(str, "EP0_OUT_DATA_PHASE"); ++ break; ++ case EP0_IN_STATUS_PHASE: ++ fh_strcpy(str, "EP0_IN_STATUS_PHASE"); ++ break; ++ case EP0_OUT_STATUS_PHASE: ++ fh_strcpy(str, "EP0_OUT_STATUS_PHASE"); ++ break; ++ case EP0_STALL: ++ fh_strcpy(str, "EP0_STALL"); ++ break; ++ default: ++ fh_strcpy(str, "EP0_INVALID"); ++ } ++ ++ FH_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); ++#endif ++} ++ ++/** ++ * This function calculate the size of the payload in the memory ++ * for out endpoints and prints size for debug purposes(used in ++ * 2.93a DevOutNak feature). ++ */ ++static inline void print_memory_payload(fh_otg_pcd_t * pcd, fh_ep_t * ep) ++{ ++#ifdef DEBUG ++ deptsiz_data_t deptsiz_init = {.d32 = 0 }; ++ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; ++ int pack_num; ++ unsigned payload; ++ ++ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; ++ deptsiz_updt.d32 = ++ FH_READ_REG32(&pcd->core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ /* Payload will be */ ++ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; ++ /* Packet count is decremented every time a packet ++ * is written to the RxFIFO not in to the external memory ++ * So, if payload == 0, then it means no packet was sent to ext memory*/ ++ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); ++ FH_DEBUGPL(DBG_PCDV, ++ "Payload for EP%d-%s\n", ++ ep->num, (ep->is_in ? "IN" : "OUT")); ++ FH_DEBUGPL(DBG_PCDV, ++ "Number of transfered bytes = 0x%08x\n", payload); ++ FH_DEBUGPL(DBG_PCDV, ++ "Number of transfered packets = %d\n", pack_num); ++#endif ++} ++ ++ ++#ifdef FH_UTE_CFI ++static inline void print_desc(struct fh_otg_dma_desc *ddesc, ++ const uint8_t * epname, int descnum) ++{ ++ CFI_INFO ++ ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n", ++ epname, descnum, ddesc->buf, ddesc->status.b.bytes, ++ ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts, ++ ddesc->status.b.bs); ++} ++#endif ++ ++/** ++ * This function returns pointer to in ep struct with number ep_num ++ */ ++static inline fh_otg_pcd_ep_t *get_in_ep(fh_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_in_eps; ++i) { ++ if (pcd->in_ep[i].fh_ep.num == ep_num) ++ return &pcd->in_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This function returns pointer to out ep struct with number ep_num ++ */ ++static inline fh_otg_pcd_ep_t *get_out_ep(fh_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_out_eps; ++i) { ++ if (pcd->out_ep[i].fh_ep.num == ep_num) ++ return &pcd->out_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This functions gets a pointer to an EP from the wIndex address ++ * value of the control request. ++ */ ++fh_otg_pcd_ep_t *get_ep_by_addr(fh_otg_pcd_t * pcd, u16 wIndex) ++{ ++ fh_otg_pcd_ep_t *ep; ++ uint32_t ep_num = UE_GET_ADDR(wIndex); ++ ++ if (ep_num == 0) { ++ ep = &pcd->ep0; ++ } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */ ++ ep = &pcd->in_ep[ep_num - 1]; ++ } else { ++ ep = &pcd->out_ep[ep_num - 1]; ++ } ++ ++ return ep; ++} ++ ++/** ++ * This function checks the EP request queue, if the queue is not ++ * empty the next request is started. ++ */ ++void start_next_request(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_pcd_request_t *req = 0; ++ uint32_t max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; ++ ++#ifdef FH_UTE_CFI ++ struct fh_otg_pcd *pcd; ++ pcd = ep->pcd; ++#endif ++ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ ++#ifdef FH_UTE_CFI ++ if (ep->fh_ep.buff_mode != BM_STANDARD) { ++ ep->fh_ep.cfi_req_len = req->length; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); ++ } else { ++#endif ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ ep->fh_ep.dma_addr = req->dw_align_buf_dma; ++ ep->fh_ep.start_xfer_buff = req->dw_align_buf; ++ ep->fh_ep.xfer_buff = req->dw_align_buf; ++ } else { ++ ep->fh_ep.dma_addr = req->dma; ++ ep->fh_ep.start_xfer_buff = req->buf; ++ ep->fh_ep.xfer_buff = req->buf; ++ } ++ ep->fh_ep.sent_zlp = 0; ++ ep->fh_ep.total_len = req->length; ++ ep->fh_ep.xfer_len = 0; ++ ep->fh_ep.xfer_count = 0; ++ ++ ep->fh_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE ++ - (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->fh_ep.is_in) { ++ if (ep->fh_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->fh_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->fh_ep.maxxfer > out_max_xfer) { ++ ep->fh_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->fh_ep.maxxfer < ep->fh_ep.total_len) { ++ ep->fh_ep.maxxfer -= ++ (ep->fh_ep.maxxfer % ep->fh_ep.maxpacket); ++ } ++ if (req->sent_zlp) { ++ if ((ep->fh_ep.total_len % ++ ep->fh_ep.maxpacket == 0) ++ && (ep->fh_ep.total_len != 0)) { ++ ep->fh_ep.sent_zlp = 1; ++ } ++ ++ } ++#ifdef FH_UTE_CFI ++ } ++#endif ++ fh_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->fh_ep); ++ } else if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ intr_mask.b.nak = 1; ++ ++ if (GET_CORE_IF(ep->pcd)->multiproc_int_enable) { ++ FH_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->fh_ep.num], intr_mask.d32, 0); ++ } else { ++ FH_MODIFY_REG32(&GET_CORE_IF(ep->pcd)->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ FH_PRINTF("There are no more ISOC requests \n"); ++ ep->fh_ep.frame_num = 0xFFFFFFFF; ++ } ++} ++ ++/** ++ * This function handles the SOF Interrupts. At this time the SOF ++ * Interrupt is disabled. ++ */ ++int32_t fh_otg_pcd_handle_sof_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ gintsts_data_t gintsts; ++ ++ FH_DEBUGPL(DBG_PCD, "SOF\n"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Rx Status Queue Level Interrupt, which ++ * indicates that there is a least one packet in the Rx FIFO. The ++ * packets are moved from the FIFO to memory, where they will be ++ * processed when the Endpoint Interrupt Register indicates Transfer ++ * Complete or SETUP Phase Done. ++ * ++ * Repeat the following until the Rx Status Queue is empty: ++ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet ++ * info ++ * -# If Receive FIFO is empty then skip to step Clear the interrupt ++ * and exit ++ * -# If SETUP Packet call fh_otg_read_setup_packet to copy the ++ * SETUP data to the buffer ++ * -# If OUT Data Packet call fh_otg_read_packet to copy the data ++ * to the destination buffer ++ */ ++int32_t fh_otg_pcd_handle_rx_status_q_level_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t gintmask = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ fh_otg_pcd_ep_t *ep; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" }; ++#endif ++ ++ //FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); ++ /* Disable the Rx Status Queue Level interrupt */ ++ gintmask.b.rxstsqlvl = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0); ++ ++ /* Get the Status from the top of the FIFO */ ++ status.d32 = FH_READ_REG32(&global_regs->grxstsp); ++ ++ FH_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " ++ "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, ++ dpid_str[status.b.dpid], ++ status.b.pktsts, status.b.fn, status.b.fn); ++ /* Get pointer to EP structure */ ++ ep = get_out_ep(pcd, status.b.epnum); ++ ++ switch (status.b.pktsts) { ++ case FH_DSTS_GOUT_NAK: ++ FH_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ break; ++ case FH_STS_DATA_UPDT: ++ FH_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); ++ if (status.b.bcnt && ep->fh_ep.xfer_buff) { ++ /** @todo NGS Check for buffer overflow? */ ++ fh_otg_read_packet(core_if, ++ ep->fh_ep.xfer_buff, ++ status.b.bcnt); ++ ep->fh_ep.xfer_count += status.b.bcnt; ++ ep->fh_ep.xfer_buff += status.b.bcnt; ++ } ++ break; ++ case FH_STS_XFER_COMP: ++ FH_DEBUGPL(DBG_PCDV, "OUT Complete\n"); ++ break; ++ case FH_DSTS_SETUP_COMP: ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "Setup Complete\n"); ++#endif ++ break; ++ case FH_DSTS_SETUP_UPDT: ++ fh_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, ++ "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", ++ pcd->setup_pkt->req.bmRequestType, ++ pcd->setup_pkt->req.bRequest, ++ UGETW(pcd->setup_pkt->req.wValue), ++ UGETW(pcd->setup_pkt->req.wIndex), ++ UGETW(pcd->setup_pkt->req.wLength)); ++#endif ++ ep->fh_ep.xfer_count += status.b.bcnt; ++ break; ++ default: ++ FH_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", ++ status.b.pktsts); ++ break; ++ } ++ ++ /* Enable the Rx Status Queue Level interrupt */ ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32); ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ //FH_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); ++ return 1; ++} ++ ++/** ++ * This function examines the Device IN Token Learning Queue to ++ * determine the EP number of the last IN token received. This ++ * implementation is for the Mass Storage device where there are only ++ * 2 IN EPs (Control-IN and BULK-IN). ++ * ++ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there ++ * are 8 EP Numbers in each of the other possible DTKNQ Registers. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * ++ */ ++static inline int get_ep_of_last_in_token(fh_otg_core_if_t * core_if) ++{ ++ fh_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ int ndx = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ int epnum = 0; ++ ++ //FH_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = FH_READ_REG32(addr); ++ FH_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ /* Get the EP numbers */ ++ in_tkn_epnums[0] = dtknqr1.b.epnums0_5; ++ ndx = dtknqr1.b.intknwptr - 1; ++ ++ //FH_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); ++ if (ndx == -1) { ++ /** @todo Find a simpler way to calculate the max ++ * queue position.*/ ++ int cnt = TOKEN_Q_DEPTH; ++ if (TOKEN_Q_DEPTH <= 6) { ++ cnt = TOKEN_Q_DEPTH - 1; ++ } else if (TOKEN_Q_DEPTH <= 14) { ++ cnt = TOKEN_Q_DEPTH - 7; ++ } else if (TOKEN_Q_DEPTH <= 22) { ++ cnt = TOKEN_Q_DEPTH - 15; ++ } else { ++ cnt = TOKEN_Q_DEPTH - 23; ++ } ++ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF; ++ } else { ++ if (ndx <= 5) { ++ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 13) { ++ ndx -= 6; ++ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 21) { ++ ndx -= 14; ++ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 29) { ++ ndx -= 22; ++ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; ++ } ++ } ++ //FH_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); ++ return epnum; ++} ++ ++/** ++ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. ++ * The active request is checked for the next packet to be loaded into ++ * the non-periodic Tx FIFO. ++ */ ++int32_t fh_otg_pcd_handle_np_tx_fifo_empty_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ fh_otg_dev_in_ep_regs_t *ep_regs; ++ gnptxsts_data_t txstatus = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ int epnum = 0; ++ fh_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ /* Get the epnum from the IN Token Learning Queue. */ ++ epnum = get_ep_of_last_in_token(core_if); ++ ep = get_in_ep(pcd, epnum); ++ ++ FH_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->fh_ep.xfer_len - ep->fh_ep.xfer_count; ++ if (len > ep->fh_ep.maxpacket) { ++ len = ep->fh_ep.maxpacket; ++ } ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ FH_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); ++ ++ while (txstatus.b.nptxqspcavail > 0 && ++ txstatus.b.nptxfspcavail > dwords && ++ ep->fh_ep.xfer_count < ep->fh_ep.xfer_len) { ++ /* Write the FIFO */ ++ fh_otg_ep_write_packet(core_if, &ep->fh_ep, 0); ++ len = ep->fh_ep.xfer_len - ep->fh_ep.xfer_count; ++ ++ if (len > ep->fh_ep.maxpacket) { ++ len = ep->fh_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = FH_READ_REG32(&global_regs->gnptxsts); ++ FH_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", ++ FH_READ_REG32(&global_regs->gnptxsts)); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.nptxfempty = 1; ++ FH_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when dedicated Tx FIFO Empty interrupt occurs. ++ * The active request is checked for the next packet to be loaded into ++ * apropriate Tx FIFO. ++ */ ++static int32_t write_empty_tx_fifo(fh_otg_pcd_t * pcd, uint32_t epnum) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ fh_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ fh_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ FH_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->fh_ep.xfer_len - ep->fh_ep.xfer_count; ++ ++ if (len > ep->fh_ep.maxpacket) { ++ len = ep->fh_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail >= dwords && ++ ep->fh_ep.xfer_count < ep->fh_ep.xfer_len && ++ ep->fh_ep.xfer_len != 0) { ++ /* Write the FIFO */ ++ fh_otg_ep_write_packet(core_if, &ep->fh_ep, 0); ++ ++ len = ep->fh_ep.xfer_len - ep->fh_ep.xfer_count; ++ if (len > ep->fh_ep.maxpacket) { ++ len = ep->fh_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ FH_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when the Device is disconnected. It stops ++ * any active requests and informs the Gadget driver of the ++ * disconnect. ++ */ ++void fh_otg_pcd_stop(fh_otg_pcd_t * pcd) ++{ ++ int i, num_in_eps, num_out_eps; ++ fh_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_SPINLOCK(pcd->lock); ++ ++ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s() \n", __func__); ++ /* don't disconnect drivers more than once */ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ FH_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); ++ FH_SPINUNLOCK(pcd->lock); ++ return; ++ } ++ pcd->ep0state = EP0_DISCONNECT; ++ ++ /* Reset the OTG state. */ ++ fh_otg_pcd_update_otg(pcd, 1); ++ ++ /* Disable the NP Tx Fifo Empty Interrupt. */ ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Flush the FIFOs */ ++ /**@todo NGS Flush Periodic FIFOs */ ++ fh_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); ++ fh_otg_flush_rx_fifo(GET_CORE_IF(pcd)); ++ ++ /* prevent new request submissions, kill any outstanding requests */ ++ ep = &pcd->ep0; ++ fh_otg_request_nuke(ep); ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_in_eps; i++) { ++ fh_otg_pcd_ep_t *ep = &pcd->in_ep[i]; ++ fh_otg_request_nuke(ep); ++ } ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_out_eps; i++) { ++ fh_otg_pcd_ep_t *ep = &pcd->out_ep[i]; ++ fh_otg_request_nuke(ep); ++ } ++ ++ /* report disconnect; the driver is already quiesced */ ++ if (pcd->fops->disconnect) { ++ FH_SPINUNLOCK(pcd->lock); ++ pcd->fops->disconnect(pcd); ++ FH_SPINLOCK(pcd->lock); ++ } ++ FH_SPINUNLOCK(pcd->lock); ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t fh_otg_pcd_handle_i2c_intr(fh_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); ++ intr_mask.b.i2cintr = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.i2cintr = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t fh_otg_pcd_handle_early_suspend_intr(fh_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++#if defined(VERBOSE) ++ FH_PRINTF("Early Suspend Detected\n"); ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.erlysuspend = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function configures EPO to receive SETUP packets. ++ * ++ * @todo NGS: Update the comments from the HW FS. ++ * ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param pcd Programming view of the PCD. ++ */ ++static inline void ep0_out_start(fh_otg_core_if_t * core_if, ++ fh_otg_pcd_t * pcd) ++{ ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, ++ FH_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++#endif ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ doepctl.d32 = FH_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ if (doepctl.b.epena) { ++ return; ++ } ++ } ++ ++ doeptsize0.b.supcnt = 3; ++ doeptsize0.b.pktcnt = 1; ++ doeptsize0.b.xfersize = 8 * 3; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ ++ /** @todo dma needs to handle multiple setup packets (up to 3) */ ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ pcd->setup_pkt_dma_handle); ++ } else { ++ dev_if->setup_desc_index = ++ (dev_if->setup_desc_index + 1) & 1; ++ dma_desc = ++ dev_if->setup_desc_addr[dev_if->setup_desc_index]; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.sr = 0; ++ dma_desc->status.b.mtrf = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = pcd->ep0.fh_ep.maxpacket; ++ dma_desc->buf = pcd->setup_pkt_dma_handle; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ dev_if->dma_setup_desc_addr ++ [dev_if->setup_desc_index]); ++ } ++ ++ } else { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ } ++ ++ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ ++ doepctl.d32 = 0; ++ doepctl.b.epena = 1; ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.cnak = 1; ++ FH_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } else { ++ FH_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); ++ } ++ ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ FH_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ FH_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ FH_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++} ++ ++/** ++ * This interrupt occurs when a USB Reset is detected. When the USB ++ * Reset Interrupt occurs the device state is set to DEFAULT and the ++ * EP0 state is set to IDLE. ++ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) ++ * -# Unmask the following interrupt bits ++ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) ++ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) ++ * - DOEPMSK.SETUP = 1 ++ * - DOEPMSK.XferCompl = 1 ++ * - DIEPMSK.XferCompl = 1 ++ * - DIEPMSK.TimeOut = 1 ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * At this point, all the required initialization, except for enabling ++ * the control 0 OUT endpoint is done, for receiving SETUP packets. ++ */ ++int32_t fh_otg_pcd_handle_usb_reset_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ int i = 0; ++ gintsts_data_t gintsts; ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = FH_READ_REG32(core_if->pcgcctl); ++ if (power.b.stoppclk) { ++ power.d32 = 0; ++ power.b.stoppclk = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.pwrclmp = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.rstpdwnmodule = 1; ++ FH_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ } ++ ++ core_if->lx_state = FH_OTG_L0; ++ core_if->otg_sts = 0; ++ ++ FH_PRINTF("USB RESET\n"); ++#ifdef FH_EN_ISOC ++ for (i = 1; i < 16; ++i) { ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ ep = get_in_ep(pcd, i); ++ if (ep != 0) { ++ fh_ep = &ep->fh_ep; ++ fh_ep->next_frame = 0xffffffff; ++ } ++ } ++#endif /* FH_EN_ISOC */ ++ ++ /* reset the HNP settings */ ++ fh_otg_pcd_update_otg(pcd, 1); ++ ++ /* Clear the Remote Wakeup Signalling */ ++ dctl.b.rmtwkupsig = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ ++ /* Set NAK for all OUT EPs */ ++ doepctl.b.snak = 1; ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ } ++ ++ /* Flush the NP Tx FIFO */ ++ fh_otg_flush_tx_fifo(core_if, 0x10); ++ /* Flush the Learning Queue */ ++ resetctl.b.intknqflsh = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i <= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0], ++ doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ ++/* if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ diepmsk.b.nak = 1; ++ } ++*/ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0], ++ diepmsk.d32); ++ } else { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++ ++ FH_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); ++ } ++ ++ /* Reset Device Address */ ++ dcfg.d32 = FH_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.devaddr = 0; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* setup EP0 to receive SETUP packets */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) ++ ep0_out_start(core_if, pcd); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbreset = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Get the device speed from the device status register and convert it ++ * to USB speed constant. ++ * ++ * @param core_if Programming view of FH_otg controller. ++ */ ++static int get_device_speed(fh_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ int speed = 0; ++ dsts.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ switch (dsts.b.enumspd) { ++ case FH_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ speed = USB_SPEED_HIGH; ++ break; ++ case FH_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case FH_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ speed = USB_SPEED_FULL; ++ break; ++ ++ case FH_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ speed = USB_SPEED_LOW; ++ break; ++ } ++ ++ return speed; ++} ++ ++/** ++ * Read the device status register and set the device speed in the ++ * data structure. ++ * Set up EP0 to receive SETUP packets by calling fh_ep0_activate. ++ */ ++int32_t fh_otg_pcd_handle_enum_done_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ gintsts_data_t gintsts; ++ gusbcfg_data_t gusbcfg; ++ fh_otg_core_global_regs_t *global_regs = ++ GET_CORE_IF(pcd)->core_global_regs; ++ uint8_t utmi16b, utmi8b; ++ int speed; ++ dcfg_data_t dcfg; ++ ++ FH_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); ++ ++ /* WA for the case when SW gets SPEED ENUM without first USB RESET case ++ * due to USB RESET issued by the host earlier. Anyways USB Reset routine ++ * needs to be called to at least program EP 0 OUT - vahrama ++ */ ++ dcfg.d32 = FH_READ_REG32(&pcd->core_if->dev_if->dev_global_regs->dcfg); ++ if (pcd->core_if->otg_ver && dcfg.b.devaddr) ++ fh_otg_pcd_handle_usb_reset_intr(pcd); ++ ++ ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { ++ utmi16b = 6; //vahrama old value was 6; ++ utmi8b = 9; ++ } else { ++ utmi16b = 4; ++ utmi8b = 8; ++ } ++ fh_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->fh_ep); ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++ ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ pcd->ep0state = EP0_IDLE; ++ } else if (pcd->ep0state == EP0_STALL) { ++ pcd->ep0state = EP0_IDLE; ++ } ++ ++ pcd->ep0state = EP0_IDLE; ++ ++ ep0->stopped = 0; ++ ++ speed = get_device_speed(GET_CORE_IF(pcd)); ++ pcd->fops->connect(pcd, speed); ++ ++ /* Set USB turnaround time based on device speed and PHY interface. */ ++ gusbcfg.d32 = FH_READ_REG32(&global_regs->gusbcfg); ++ if (speed == USB_SPEED_HIGH) { ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ FH_HWCFG2_HS_PHY_TYPE_ULPI) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ FH_HWCFG2_HS_PHY_TYPE_UTMI) { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else if (GET_CORE_IF(pcd)->hwcfg4. ++ b.utmi_phy_data_width == 1) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 8) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ FH_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { ++ /* UTMI+ OR ULPI interface */ ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } else { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 16) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } ++ } ++ } ++ } else { ++ /* Full or low speed */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ FH_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.enumdone = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the ISO OUT Packet was dropped due to ++ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs ++ * read all the data from the Rx FIFO. ++ */ ++int32_t fh_otg_pcd_handle_isoc_out_packet_dropped_intr(fh_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ FH_WARN("INTERRUPT Handler not implemented for %s\n", ++ "ISOC Out Dropped"); ++ ++ intr_mask.b.isooutdrop = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.isooutdrop = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates the end of the portion of the micro-frame ++ * for periodic transactions. If there is a periodic transaction for ++ * the next frame, load the packets into the EP periodic Tx FIFO. ++ */ ++int32_t fh_otg_pcd_handle_end_periodic_frame_intr(fh_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); ++ ++ intr_mask.b.eopframe = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.eopframe = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that EP of the packet on the top of the ++ * non-periodic Tx FIFO does not match EP of the IN Token received. ++ * ++ * The "Device IN Token Queue" Registers are read to determine the ++ * order the IN Tokens have been received. The non-periodic Tx FIFO ++ * is flushed, so it can be reloaded in the order seen in the IN Token ++ * Queue. ++ */ ++int32_t fh_otg_pcd_handle_ep_mismatch_intr(fh_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 1; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (!gintsts.b.ginnakeff) { ++ /* Disable EP Mismatch interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.epmismatch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.ginnakeff = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ /* Set the global non-periodic IN NAK handshake */ ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgnpinnak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } else { ++ FH_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); ++ } ++ /* Disabling of all EP's will be done in fh_otg_pcd_handle_in_nak_effective() ++ * handler after Global IN NAK Effective interrupt will be asserted */ ++ } ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.epmismatch = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt is valid only in DMA mode. This interrupt indicates that the ++ * core has stopped fetching data for IN endpoints due to the unavailability of ++ * TxFIFO space or Request Queue space. This interrupt is used by the ++ * application for an endpoint mismatch algorithm. ++ * ++ * @param pcd The PCD ++ */ ++int32_t fh_otg_pcd_handle_ep_fetsusp_intr(fh_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk_data; ++ dctl_data_t dctl; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Mask GINTSTS.FETSUSP interrupt */ ++ gintmsk_data.d32 = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gintmsk_data.b.fetsusp = 0; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.fetsusp = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This funcion stalls EP0. ++ */ ++static inline void ep0_do_stall(fh_otg_pcd_t * pcd, const int err_val) ++{ ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ usb_device_request_t *ctrl = &pcd->setup_pkt->req; ++ FH_WARN("req %02x.%02x protocol STALL; err %d\n", ++ ctrl->bmRequestType, ctrl->bRequest, err_val); ++ ++ ep0->fh_ep.is_in = 1; ++ fh_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->fh_ep); ++ ep0->fh_ep.is_in = 0; ++ fh_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->fh_ep); ++ pcd->ep0.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This functions delegates the setup command to the gadget driver. ++ */ ++static inline void do_gadget_setup(fh_otg_pcd_t * pcd, ++ usb_device_request_t * ctrl) ++{ ++ int ret = 0; ++ FH_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->setup(pcd, (uint8_t *) ctrl); ++ FH_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ } ++ ++ /** @todo This is a g_file_storage gadget driver specific ++ * workaround: a DELAYED_STATUS result from the fsg_setup ++ * routine will result in the gadget queueing a EP0 IN status ++ * phase for a two-stage control transfer. Exactly the same as ++ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class ++ * specific request. Need a generic way to know when the gadget ++ * driver will queue the status phase. Can we assume when we ++ * call the gadget driver setup() function that it will always ++ * queue and require the following flag? Need to look into ++ * this. ++ */ ++ ++ if (ret == 256 + 999) { ++ pcd->request_config = 1; ++ } ++} ++ ++#ifdef FH_UTE_CFI ++/** ++ * This functions delegates the CFI setup commands to the gadget driver. ++ * This function will return a negative value to indicate a failure. ++ */ ++static inline int cfi_gadget_setup(fh_otg_pcd_t * pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int ret = 0; ++ ++ if (pcd->fops && pcd->fops->cfi_setup) { ++ FH_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->cfi_setup(pcd, ctrl_req); ++ FH_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function starts the Zero-Length Packet for the IN status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_in_status_phase(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ if (pcd->ep0state == EP0_STALL) { ++ return; ++ } ++ ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ ++ /* Prepare for more SETUP Packets */ ++ FH_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); ++ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_desc_enable) ++ && (ep0->fh_ep.xfer_count < ep0->fh_ep.total_len)) { ++ FH_DEBUGPL(DBG_PCDV, ++ "Data terminated wait next packet in out_desc_addr\n"); ++ pcd->backup_buf = phys_to_virt(ep0->fh_ep.dma_addr); ++ pcd->data_terminated = 1; ++ } ++ ep0->fh_ep.xfer_len = 0; ++ ep0->fh_ep.xfer_count = 0; ++ ep0->fh_ep.is_in = 1; ++ ep0->fh_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ fh_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->fh_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ //ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This function starts the Zero-Length Packet for the OUT status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_out_status_phase(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ doepint_data_t doepint; ++ doepint.d32 = FH_READ_REG32(&pcd->core_if->dev_if->out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_STALL) { ++ FH_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); ++ return; ++ } ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ ++ FH_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); ++ ep0->fh_ep.xfer_len = 0; ++ ep0->fh_ep.xfer_count = 0; ++ ep0->fh_ep.is_in = 0; ++ ep0->fh_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ /* If there is xfercomplete on EP0 OUT do not start OUT Status stage. ++ * xfercomplete means that ZLP was already received as EP0 OUT is enabled ++ * during IN Data stage ++ */ ++ if ((doepint.b.xfercompl == 1) && (pcd->core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_enable == 1) && (pcd->core_if->dma_desc_enable == 0)) { ++ FH_DEBUGPL(DBG_PCD, "Status stage already completed\n"); ++ return; ++ } ++ ++ fh_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->fh_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ if (GET_CORE_IF(pcd)->dma_enable == 0) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++} ++ ++/** ++ * Clear the EP halt (STALL) and if pending requests start the ++ * transfer. ++ */ ++static inline void pcd_clear_halt(fh_otg_pcd_t * pcd, fh_otg_pcd_ep_t * ep) ++{ ++ if (ep->fh_ep.stall_clear_flag) { ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++ return; ++ } ++ ++ fh_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->fh_ep); ++ ++ /* Reactive the EP */ ++ fh_otg_ep_activate(GET_CORE_IF(pcd), &ep->fh_ep); ++ if (ep->stopped) { ++ ep->stopped = 0; ++ /* If there is a request in the EP queue start it */ ++ ++ /** @todo FIXME: this causes an EP mismatch in DMA mode. ++ * epmismatch not yet implemented. */ ++ ++ /* ++ * Above fixme is solved by implmenting a tasklet to call the ++ * start_next_request(), outside of interrupt context at some ++ * time after the current time, after a clear-halt setup packet. ++ * Still need to implement ep mismatch in the future if a gadget ++ * ever uses more than one endpoint at once ++ */ ++ ep->queue_sof = 1; ++ FH_TASK_SCHEDULE(pcd->start_xfer_tasklet); ++ } ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++} ++ ++/** ++ * This function is called when the SET_FEATURE TEST_MODE Setup packet ++ * is sent from the host. The Device Control register is written with ++ * the Test Mode bits set to the specified Test Mode. This is done as ++ * a tasklet so that the "Status" phase of the control transfer ++ * completes before transmitting the TEST packets. ++ * ++ * @todo This has not been tested since the tasklet struct was put ++ * into the PCD struct! ++ * ++ */ ++void do_test_mode(void *data) ++{ ++ dctl_data_t dctl; ++ fh_otg_pcd_t *pcd = (fh_otg_pcd_t *) data; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int test_mode = pcd->test_mode; ++ ++// FH_WARN("%s() has not been tested since being rewritten!\n", __func__); ++ ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ switch (test_mode) { ++ case 1: // TEST_J ++ dctl.b.tstctl = 1; ++ break; ++ ++ case 2: // TEST_K ++ dctl.b.tstctl = 2; ++ break; ++ ++ case 3: // TEST_SE0_NAK ++ dctl.b.tstctl = 3; ++ break; ++ ++ case 4: // TEST_PACKET ++ dctl.b.tstctl = 4; ++ break; ++ ++ case 5: // TEST_FORCE_ENABLE ++ dctl.b.tstctl = 5; ++ break; ++ case 7: ++ fh_otg_set_hnpreq(core_if, 1); ++ } ++ FH_PRINTF("test mode = %d\n",test_mode); ++ core_if->test_mode = test_mode; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++ ++/** ++ * This function process the GET_STATUS Setup Commands. ++ */ ++static inline void do_get_status(fh_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ fh_otg_pcd_ep_t *ep; ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ uint16_t *status = pcd->status_buf; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, ++ "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ if (UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ ++ FH_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); ++ FH_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); ++ FH_PRINTF("OTG CAP - %d, %d\n", ++ core_if->core_params->otg_cap, ++ FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ if (core_if->otg_ver == 1 ++ && core_if->core_params->otg_cap == ++ FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ uint8_t *otgsts = (uint8_t *) pcd->status_buf; ++ *otgsts = (core_if->otg_sts & 0x1); ++ pcd->ep0_pending = 1; ++ ep0->fh_ep.start_xfer_buff = ++ (uint8_t *) otgsts; ++ ep0->fh_ep.xfer_buff = (uint8_t *) otgsts; ++ ep0->fh_ep.dma_addr = ++ pcd->status_buf_dma_handle; ++ ep0->fh_ep.xfer_len = 1; ++ ep0->fh_ep.xfer_count = 0; ++ ep0->fh_ep.total_len = ep0->fh_ep.xfer_len; ++ fh_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep0->fh_ep); ++ return; ++ } else { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ } else { ++ *status = 0x1; /* Self powered */ ++ *status |= pcd->remote_wakeup_enable << 1; ++ break; ++ } ++ case UT_INTERFACE: ++ *status = 0; ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0 || UGETW(ctrl.wLength) > 2) { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ /** @todo check for EP stall */ ++ *status = ep->stopped; ++ break; ++ } ++ pcd->ep0_pending = 1; ++ ep0->fh_ep.start_xfer_buff = (uint8_t *) status; ++ ep0->fh_ep.xfer_buff = (uint8_t *) status; ++ ep0->fh_ep.dma_addr = pcd->status_buf_dma_handle; ++ ep0->fh_ep.xfer_len = 2; ++ ep0->fh_ep.xfer_count = 0; ++ ep0->fh_ep.total_len = ep0->fh_ep.xfer_len; ++ fh_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->fh_ep); ++} ++ ++/** ++ * This function process the SET_FEATURE Setup Commands. ++ */ ++static inline void do_set_feature(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ fh_otg_pcd_ep_t *ep = 0; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ FH_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 1; ++ break; ++ ++ case UF_TEST_MODE: ++ /* Setup the Test Mode tasklet to do the Test ++ * Packet generation after the SETUP Status ++ * phase has completed. */ ++ ++ /** @todo This has not been tested since the ++ * tasklet struct was put into the PCD ++ * struct! */ ++ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; ++ FH_TASK_SCHEDULE(pcd->test_mode_tasklet); ++ break; ++ ++ case UF_DEVICE_B_HNP_ENABLE: ++ FH_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); ++ ++ /* dev may initiate HNP */ ++ if (otg_cap_param == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ gotgctl.b.devhnpen = 1; ++ if (core_if->otg_ver) { ++ FH_MODIFY_REG32(&global_regs->gotgctl, 0, gotgctl.d32); ++ /* Ensure that USB Suspend interrupt is unmasked */ ++ gintmsk.b.usbsuspend = 1; ++ FH_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ else { ++ pcd->b_hnp_enable = 1; ++ fh_otg_pcd_update_otg(pcd, 0); ++ FH_DEBUGPL(DBG_PCD, "Request B HNP\n"); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.hnpreq = 1; ++ FH_WRITE_REG32(&global_regs->gotgctl, gotgctl.d32); ++ } ++ } else { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_HNP_SUPPORT: ++ /* RH port supports HNP */ ++ FH_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); ++ if (otg_cap_param == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_hnp_support = 1; ++ fh_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_ALT_HNP_SUPPORT: ++ /* other RH port does */ ++ FH_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); ++ if (otg_cap_param == FH_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_alt_hnp_support = 1; ++ fh_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_INTERFACE: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UT_ENDPOINT: ++ if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) { ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ ep->stopped = 1; ++ fh_otg_ep_set_stall(core_if, &ep->fh_ep); ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ } ++} ++ ++/** ++ * This function process the CLEAR_FEATURE Setup Commands. ++ */ ++static inline void do_clear_feature(fh_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ fh_otg_pcd_ep_t *ep = 0; ++ ++ FH_DEBUGPL(DBG_PCD, ++ "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 0; ++ break; ++ ++ case UF_TEST_MODE: ++ /** @todo Add CLEAR_FEATURE for TEST modes. */ ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -FH_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd_clear_halt(pcd, ep); ++ ++ break; ++ } ++} ++ ++/** ++ * This function process the SET_ADDRESS Setup Commands. ++ */ ++static inline void do_set_address(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ ++ if (ctrl.bmRequestType == UT_DEVICE) { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ ++#ifdef DEBUG_EP0 ++// FH_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); ++#endif ++ dcfg.b.devaddr = UGETW(ctrl.wValue); ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); ++ do_setup_in_status_phase(pcd); ++ } ++} ++ ++/** ++ * This function processes SETUP commands. In Linux, the USB Command ++ * processing is done in two places - the first being the PCD and the ++ * second in the Gadget Driver (for example, the File-Backed Storage ++ * Gadget Driver). ++ * ++ * <table> ++ * <tr><td>Command </td><td>Driver </td><td>Description</td></tr> ++ * ++ * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as ++ * defined in chapter 9 of the USB 2.0 Specification chapter 9 ++ * </td></tr> ++ * ++ * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint ++ * requests are the ENDPOINT_HALT feature is procesed, all others the ++ * interface requests are ignored.</td></tr> ++ * ++ * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint ++ * requests are processed by the PCD. Interface requests are passed ++ * to the Gadget Driver.</td></tr> ++ * ++ * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg, ++ * with device address received </td></tr> ++ * ++ * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the ++ * requested descriptor</td></tr> ++ * ++ * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional - ++ * not implemented by any of the existing Gadget Drivers.</td></tr> ++ * ++ * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable ++ * all EPs and enable EPs for new configuration.</td></tr> ++ * ++ * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return ++ * the current configuration</td></tr> ++ * ++ * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all ++ * EPs and enable EPs for new configuration.</td></tr> ++ * ++ * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the ++ * current interface.</td></tr> ++ * ++ * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug ++ * message.</td></tr> ++ * </table> ++ * ++ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are ++ * processed by pcd_setup. Calling the Function Driver's setup function from ++ * pcd_setup processes the gadget SETUP commands. ++ */ ++static inline void pcd_setup(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ ++#ifdef FH_UTE_CFI ++ int retval = 0; ++ struct cfi_usb_ctrlrequest cfi_req; ++#endif ++ ++ doeptsize0.d32 = FH_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); ++ ++ /** In BDMA more then 1 setup packet is not supported till 3.00a */ ++ if (core_if->dma_enable && core_if->dma_desc_enable == 0 ++ && (doeptsize0.b.supcnt < 2) ++ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ FH_ERROR ++ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); ++ } ++ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { ++ if (doeptsize0.b.supcnt == 3 && ep0->fh_ep.stp_rollover == 0) { ++ FH_ERROR(" !!! Setup packet count was not updated by the core\n"); ++ return; ++ } ++ ctrl = ++ (pcd->setup_pkt + ++ (3 - doeptsize0.b.supcnt - 1 + ++ ep0->fh_ep.stp_rollover))->req; ++ } ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ /* Clean up the request queue */ ++ fh_otg_request_nuke(ep0); ++ ep0->stopped = 0; ++ ++ if (ctrl.bmRequestType & UE_DIR_IN) { ++ ep0->fh_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ } else { ++ ep0->fh_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_DATA_PHASE; ++ } ++ ++ if (UGETW(ctrl.wLength) == 0) { ++ ep0->fh_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ ++ if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) { ++ ++#ifdef FH_UTE_CFI ++ FH_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); ++ ++ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ++ ctrl.bRequestType, ctrl.bRequest); ++ if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { ++ if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { ++ retval = cfi_setup(pcd, &cfi_req); ++ if (retval < 0) { ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return; ++ } ++ ++ /* if need gadget setup then call it and check the retval */ ++ if (pcd->cfi->need_gadget_att) { ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd-> ++ cfi->ctrl_req); ++ if (retval < 0) { ++ pcd->ep0_pending = 0; ++ return; ++ } ++ } ++ ++ if (pcd->cfi->need_status_in_complete) { ++ do_setup_in_status_phase(pcd); ++ } ++ return; ++ } ++ } ++#endif ++ ++ /* handle non-standard (class/vendor) requests in the gadget driver */ ++ do_gadget_setup(pcd, &ctrl); ++ return; ++ } ++ ++ /** @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl.bRequest) { ++ case UR_GET_STATUS: ++ do_get_status(pcd); ++ break; ++ ++ case UR_CLEAR_FEATURE: ++ do_clear_feature(pcd); ++ break; ++ ++ case UR_SET_FEATURE: ++ do_set_feature(pcd); ++ break; ++ ++ case UR_SET_ADDRESS: ++ do_set_address(pcd); ++ break; ++ ++ case UR_SET_INTERFACE: ++ case UR_SET_CONFIG: ++// _pcd->request_config = 1; /* Configuration changed */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UR_SYNCH_FRAME: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ default: ++ /* Call the Gadget Driver's setup functions */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ } ++} ++ ++/** ++ * This function completes the ep0 control transfer. ++ */ ++static int32_t ep0_complete_request(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ fh_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->fh_ep.num]; ++#ifdef DEBUG_EP0 ++ fh_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->fh_ep.num]; ++#endif ++ deptsiz0_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts = {.d32 = 0 }; ++ fh_otg_pcd_request_t *req; ++ int is_last = 0; ++ fh_otg_pcd_t *pcd = ep->pcd; ++ ++#ifdef FH_UTE_CFI ++ struct cfi_usb_ctrlrequest *ctrlreq; ++ int retval = -FH_E_NOT_SUPPORTED; ++#endif ++ ++ if (pcd->ep0_pending && FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ if (ep->fh_ep.is_in) { ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); ++#endif ++ do_setup_out_status_phase(pcd); ++ } else { ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); ++#endif ++ ++#ifdef FH_UTE_CFI ++ ctrlreq = &pcd->cfi->ctrl_req; ++ ++ if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) { ++ if (ctrlreq->bRequest > 0xB0 ++ && ctrlreq->bRequest < 0xBF) { ++ ++ /* Return if the PCD failed to handle the request */ ++ if ((retval = ++ pcd->cfi->ops. ++ ctrl_write_complete(pcd->cfi, ++ pcd)) < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the PCD(%d)\n", ++ retval); ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ ++ /* If the gadget needs to be notified on the request */ ++ if (pcd->cfi->need_gadget_att == 1) { ++ //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req); ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd->cfi-> ++ ctrl_req); ++ ++ /* Return from the function if the gadget failed to process ++ * the request properly - this should never happen !!! ++ */ ++ if (retval < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the gadget(%d)\n", ++ retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ } ++ ++ CFI_INFO("%s: RETVAL=%d\n", __func__, ++ retval); ++ /* If we hit here then the PCD and the gadget has properly ++ * handled the request - so send the ZLP IN to the host. ++ */ ++ /* @todo: MAS - decide whether we need to start the setup ++ * stage based on the need_setup value of the cfi object ++ */ ++ do_setup_in_status_phase(pcd); ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ } ++#endif ++ ++ do_setup_in_status_phase(pcd); ++ } ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ ++ if (FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ return 0; ++ } ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ is_last = 1; ++ } else if (ep->fh_ep.is_in) { ++ deptsiz.d32 = FH_READ_REG32(&in_ep_regs->dieptsiz); ++ if (core_if->dma_desc_enable != 0) ++ desc_sts = dev_if->in_desc_addr->status; ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n", ++ ep->fh_ep.num, ep->fh_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ ++ if (((core_if->dma_desc_enable == 0) ++ && (deptsiz.b.xfersize == 0)) ++ || ((core_if->dma_desc_enable != 0) ++ && (desc_sts.b.bytes == 0))) { ++ req->actual = ep->fh_ep.xfer_count; ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ do_setup_out_status_phase(pcd); ++ } ++ } else { ++ /* ep0-OUT */ ++#ifdef DEBUG_EP0 ++ deptsiz.d32 = FH_READ_REG32(&out_ep_regs->doeptsiz); ++ FH_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", ++ ep->fh_ep.num, ep->fh_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ req->actual = ep->fh_ep.xfer_count; ++ ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ /* For older cores do setup in status phase in Slave/BDMA modes, ++ * starting from 3.00 do that only in slave, and for DMA modes ++ * just re-enable ep 0 OUT here*/ ++ if (core_if->dma_enable == 0 ++ || (core_if->dma_desc_enable == 0 ++ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { ++ do_setup_in_status_phase(pcd); ++ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ FH_DEBUGPL(DBG_PCDV, ++ "Enable out ep before in status phase\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ fh_otg_request_done(ep, req, 0); ++ ep->fh_ep.start_xfer_buff = 0; ++ ep->fh_ep.xfer_buff = 0; ++ ep->fh_ep.xfer_len = 0; ++ return 1; ++ } ++ return 0; ++} ++ ++#ifdef FH_UTE_CFI ++/** ++ * This function calculates traverses all the CFI DMA descriptors and ++ * and accumulates the bytes that are left to be transfered. ++ * ++ * @return The total bytes left to transfered, or a negative value as failure ++ */ ++static inline int cfi_calc_desc_residue(fh_otg_pcd_ep_t * ep) ++{ ++ int32_t ret = 0; ++ int i; ++ struct fh_otg_dma_desc *ddesc = NULL; ++ struct cfi_ep *cfiep; ++ ++ /* See if the pcd_ep has its respective cfi_ep mapped */ ++ cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep); ++ if (!cfiep) { ++ CFI_INFO("%s: Failed to find ep\n", __func__); ++ return -1; ++ } ++ ++ ddesc = ep->fh_ep.descs; ++ ++ for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) { ++ ++#if defined(PRINT_CFI_DMA_DESCS) ++ print_desc(ddesc, ep->ep.name, i); ++#endif ++ ret += ddesc->status.b.bytes; ++ ddesc++; ++ } ++ ++ if (ret) ++ CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__, ++ ret); ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function completes the request for the EP. If there are ++ * additional requests for the EP in the queue they will be started. ++ */ ++static void complete_ep(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ fh_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->fh_ep.num]; ++ deptsiz_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts; ++ fh_otg_pcd_request_t *req = 0; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ uint32_t byte_count = 0; ++ int is_last = 0; ++ int i; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->fh_ep.num, ++ (ep->fh_ep.is_in ? "IN" : "OUT")); ++ ++ /* Get any pending requests */ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ FH_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ FH_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); ++ ++ if (ep->fh_ep.is_in) { ++ deptsiz.d32 = FH_READ_REG32(&in_ep_regs->dieptsiz); ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (deptsiz.b.xfersize == 0 ++ && deptsiz.b.pktcnt == 0) { ++ byte_count = ++ ep->fh_ep.xfer_len - ++ ep->fh_ep.xfer_count; ++ ++ ep->fh_ep.xfer_buff += byte_count; ++ ep->fh_ep.dma_addr += byte_count; ++ ep->fh_ep.xfer_count += byte_count; ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->fh_ep.num, ++ (ep->fh_ep. ++ is_in ? "IN" : "OUT"), ++ ep->fh_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ if (ep->fh_ep.xfer_len < ++ ep->fh_ep.total_len) { ++ fh_otg_ep_start_transfer ++ (core_if, &ep->fh_ep); ++ } else if (ep->fh_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->fh_ep.sent_zlp = 0; ++ fh_otg_ep_start_zl_transfer ++ (core_if, &ep->fh_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ if (ep->fh_ep.type == ++ FH_OTG_EP_TYPE_ISOC) { ++ req->actual = 0; ++ fh_otg_request_done(ep, req, 0); ++ ++ ep->fh_ep.start_xfer_buff = 0; ++ ep->fh_ep.xfer_buff = 0; ++ ep->fh_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } else ++ FH_WARN ++ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", ++ ep->fh_ep.num, ++ (ep->fh_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ } ++ } else { ++ dma_desc = ep->fh_ep.desc_addr; ++ byte_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ++#ifdef FH_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->fh_ep.buff_mode); ++ if (ep->fh_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ ++ byte_count = residue; ++ } else { ++#endif ++ for (i = 0; i < ep->fh_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ if (ep->fh_ep.type == ++ FH_OTG_EP_TYPE_ISOC) { ++ byte_count += ++ desc_sts.b_iso_in.txbytes; ++ } else { ++ byte_count += ++ desc_sts.b.bytes; ++ } ++ dma_desc++; ++ } ++#ifdef FH_UTE_CFI ++ } ++#endif ++ if (byte_count == 0) { ++ ep->fh_ep.xfer_count = ++ ep->fh_ep.total_len; ++ is_last = 1; ++ } else { ++ FH_WARN("Incomplete transfer\n"); ++ } ++ } ++ } else { ++ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { ++ FH_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->fh_ep.num, ++ ep->fh_ep.is_in ? "IN" : "OUT", ++ ep->fh_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->fh_ep.xfer_len < ep->fh_ep.total_len) { ++ fh_otg_ep_start_transfer(core_if, ++ &ep->fh_ep); ++ } else if (ep->fh_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->fh_ep.sent_zlp = 0; ++ fh_otg_ep_start_zl_transfer(core_if, ++ &ep->fh_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ FH_WARN ++ ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n", ++ ep->fh_ep.num, ++ (ep->fh_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ } ++ } else { ++ fh_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->fh_ep.num]; ++ desc_sts.d32 = 0; ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dma_desc = ep->fh_ep.desc_addr; ++ byte_count = 0; ++ ep->fh_ep.sent_zlp = 0; ++ ++#ifdef FH_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->fh_ep.buff_mode); ++ if (ep->fh_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ byte_count = residue; ++ } else { ++#endif ++ ++ for (i = 0; i < ep->fh_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ if (ep->fh_ep.type == ++ FH_OTG_EP_TYPE_ISOC) { ++ byte_count += ++ desc_sts.b_iso_out.rxbytes; ++ } else { ++ byte_count += ++ desc_sts.b.bytes; ++ } ++ dma_desc++; ++ } ++ ++#ifdef FH_UTE_CFI ++ } ++#endif ++ /* Checking for interrupt Out transfers with not ++ * dword aligned mps sizes ++ */ ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_INTR && ++ (ep->fh_ep.maxpacket % 4)) { ++ ep->fh_ep.xfer_count = ++ ep->fh_ep.total_len - byte_count; ++ if ((ep->fh_ep.xfer_len % ++ ep->fh_ep.maxpacket) ++ && (ep->fh_ep.xfer_len / ++ ep->fh_ep.maxpacket < ++ MAX_DMA_DESC_CNT)) ++ ep->fh_ep.xfer_len -= ++ (ep->fh_ep.desc_cnt - ++ 1) * ep->fh_ep.maxpacket + ++ ep->fh_ep.xfer_len % ++ ep->fh_ep.maxpacket; ++ else ++ ep->fh_ep.xfer_len -= ++ ep->fh_ep.desc_cnt * ++ ep->fh_ep.maxpacket; ++ if (ep->fh_ep.xfer_len > 0) { ++ fh_otg_ep_start_transfer ++ (core_if, &ep->fh_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ ep->fh_ep.xfer_count = ++ ep->fh_ep.total_len - byte_count + ++ ((4 - ++ (ep->fh_ep. ++ total_len & 0x3)) & 0x3); ++ is_last = 1; ++ } ++ } else { ++ deptsiz.d32 = 0; ++ deptsiz.d32 = ++ FH_READ_REG32(&out_ep_regs->doeptsiz); ++ ++ byte_count = (ep->fh_ep.xfer_len - ++ ep->fh_ep.xfer_count - ++ deptsiz.b.xfersize); ++ ep->fh_ep.xfer_buff += byte_count; ++ ep->fh_ep.dma_addr += byte_count; ++ ep->fh_ep.xfer_count += byte_count; ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->fh_ep.xfer_len < ep->fh_ep.total_len) { ++ fh_otg_ep_start_transfer(core_if, ++ &ep->fh_ep); ++ } else if (ep->fh_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->fh_ep.sent_zlp = 0; ++ fh_otg_ep_start_zl_transfer(core_if, ++ &ep->fh_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ } else { ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->fh_ep.xfer_len < ep->fh_ep.total_len) { ++ fh_otg_ep_start_transfer(core_if, &ep->fh_ep); ++ } else if (ep->fh_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->fh_ep.sent_zlp = 0; ++ fh_otg_ep_start_zl_transfer(core_if, ++ &ep->fh_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n", ++ &out_ep_regs->doeptsiz, ep->fh_ep.num, ++ ep->fh_ep.is_in ? "IN" : "OUT", ++ ep->fh_ep.xfer_len, ep->fh_ep.xfer_count, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++#ifdef FH_UTE_CFI ++ if (ep->fh_ep.buff_mode != BM_STANDARD) { ++ req->actual = ep->fh_ep.cfi_req_len - byte_count; ++ } else { ++#endif ++ req->actual = ep->fh_ep.xfer_count; ++#ifdef FH_UTE_CFI ++ } ++#endif ++ if (req->dw_align_buf) { ++ if (!ep->fh_ep.is_in) { ++ fh_memcpy(req->buf, req->dw_align_buf, req->length); ++ } ++ FH_DMA_FREE(req->length, req->dw_align_buf, ++ req->dw_align_buf_dma); ++ } ++ ++ fh_otg_request_done(ep, req, 0); ++ ++ ep->fh_ep.start_xfer_buff = 0; ++ ep->fh_ep.xfer_buff = 0; ++ ep->fh_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } ++} ++/** ++ * This function completes the request for the ISO EP in DDMA. If it is last ++ * descriptor and ep was disabled, then program already prepared(during ep_queue) ++ * descriptor chain if there are more requests to process ++ */ ++static void complete_ddma_iso_ep(fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dev_dma_desc_sts_t desc_sts; ++ fh_otg_pcd_request_t *req = 0; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ fh_dma_t dma_desc_addr; ++ fh_ep_t *fh_ep; ++ uint32_t depdma; ++ uint32_t index; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->fh_ep.num, ++ (ep->fh_ep.is_in ? "IN" : "OUT")); ++ fh_ep = &ep->fh_ep; ++ if (fh_ep->use_add_buf) { ++ dma_desc_addr = fh_ep->dma_desc_addr; ++ dma_desc = fh_ep->desc_addr; ++ } else { ++ dma_desc_addr = fh_ep->dma_desc_addr1; ++ dma_desc = fh_ep->desc_addr1; ++ } ++ /* Get any pending requests */ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ FH_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ FH_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ if (fh_ep->is_in) { ++ depdma = FH_READ_REG32(&core_if->dev_if->in_ep_regs[fh_ep->num]->diepdma); ++ index = (depdma - dma_desc_addr)/sizeof(fh_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ req->actual = req->length - desc_sts.b_iso_in.txbytes; ++ } else { ++ depdma = FH_READ_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doepdma); ++ index = (depdma - dma_desc_addr)/sizeof(fh_otg_dev_dma_desc_t) - 1; ++ desc_sts = dma_desc[index].status; ++ if (req->length%4) ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes + (4 - req->length%4); ++ else ++ req->actual = req->length - desc_sts.b_iso_out.rxbytes; ++ } ++ ++ /* Complete the request */ ++ fh_otg_request_done(ep, req, 0); ++} ++ ++#ifdef FH_EN_ISOC ++ ++/** ++ * This function BNA interrupt for Isochronous EPs ++ * ++ */ ++static void fh_otg_pcd_handle_iso_bna(fh_otg_pcd_ep_t * ep) ++{ ++ fh_ep_t *fh_ep = &ep->fh_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ fh_otg_pcd_t *pcd = ep->pcd; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ int i; ++ ++ dma_desc = ++ fh_ep->iso_desc_addr + fh_ep->desc_cnt * (fh_ep->proc_buf_num); ++ ++ if (fh_ep->is_in) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < fh_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_in.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < fh_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_out.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } ++ ++ if (fh_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[fh_ep-> ++ num]->doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[fh_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ FH_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++} ++ ++/** ++ * This function sets latest iso packet information(non-PTI mode) ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void set_current_pkt_info(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ dma_addr_t dma_addr; ++ uint32_t offset; ++ ++ if (ep->proc_buf_num) ++ dma_addr = ep->dma_addr1; ++ else ++ dma_addr = ep->dma_addr0; ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[ep->num]->dieptsiz); ++ offset = ep->data_per_frame; ++ } else { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ offset = ++ ep->data_per_frame + ++ (0x4 & (0x4 - (ep->data_per_frame & 0x3))); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = 0; ++ } else { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = -FH_E_NO_DATA; ++ } ++ ep->cur_pkt_addr += offset; ++ ep->cur_pkt_dma_addr += offset; ++ ep->cur_pkt++; ++} ++ ++/** ++ * This function sets latest iso packet information(DDMA mode) ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param fh_ep The EP to start the transfer on. ++ * ++ */ ++static void set_ddma_iso_pkts_info(fh_otg_core_if_t * core_if, ++ fh_ep_t * fh_ep) ++{ ++ fh_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ iso_pkt_info_t *iso_packet; ++ uint32_t data_per_desc; ++ uint32_t offset; ++ int i, j; ++ ++ iso_packet = fh_ep->pkt_info; ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (fh_ep->is_in == 0) { ++ dma_desc = ++ fh_ep->iso_desc_addr + ++ fh_ep->desc_cnt * fh_ep->proc_buf_num; ++ offset = 0; ++ ++ for (i = 0; i < fh_ep->desc_cnt - fh_ep->pkt_per_frm; ++ i += fh_ep->pkt_per_frm) { ++ for (j = 0; j < fh_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep-> ++ data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -FH_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes + (4 - ++ fh_ep->data_per_frame ++ % 4); ++ } ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ iso_packet++; ++ } ++ } ++ ++ for (j = 0; j < fh_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep->data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -FH_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ iso_packet->length = ++ fh_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ iso_packet++; ++ dma_desc++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -FH_E_NO_DATA; ++ } ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ fh_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ fh_ep->data_per_frame - sts.b_iso_out.rxbytes + ++ (4 - fh_ep->data_per_frame % 4); ++ } ++ ++ iso_packet->offset = offset; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ fh_ep->iso_desc_addr + ++ fh_ep->desc_cnt * fh_ep->proc_buf_num; ++ ++ for (i = 0; i < fh_ep->desc_cnt - 1; i++) { ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso packet descriptor */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + ++ (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -FH_E_NO_DATA; ++ ++ } ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ fh_ep->data_per_frame - sts.b_iso_in.txbytes; ++ ++ dma_desc++; ++ iso_packet++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ while (sts.b_iso_in.bs == BS_DMA_BUSY) { ++ sts.d32 = dma_desc->status.d32; ++ } ++ ++ /* Write status in iso packet descriptor ??? do be done with ERROR codes */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -FH_E_NO_DATA; ++ } ++ ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ fh_ep->data_per_frame - sts.b_iso_in.txbytes; ++ } ++} ++ ++/** ++ * This function reinitialize DMA Descriptors for Isochronous transfer ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param fh_ep The EP to start the transfer on. ++ * ++ */ ++static void reinit_ddma_iso_xfer(fh_otg_core_if_t * core_if, fh_ep_t * fh_ep) ++{ ++ int i, j; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ dma_addr_t dma_ad; ++ volatile uint32_t *addr; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ uint32_t data_per_desc; ++ ++ if (fh_ep->is_in == 0) { ++ addr = &core_if->dev_if->out_ep_regs[fh_ep->num]->doepctl; ++ } else { ++ addr = &core_if->dev_if->in_ep_regs[fh_ep->num]->diepctl; ++ } ++ ++ if (fh_ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = fh_ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = fh_ep->dma_addr1; ++ } ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (fh_ep->is_in == 0) { ++ dma_desc = ++ fh_ep->iso_desc_addr + ++ fh_ep->desc_cnt * fh_ep->proc_buf_num; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ for (i = 0; i < fh_ep->desc_cnt - fh_ep->pkt_per_frm; ++ i += fh_ep->pkt_per_frm) { ++ for (j = 0; j < fh_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep-> ++ data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_ad += data_per_desc; ++ dma_desc++; ++ } ++ } ++ ++ for (j = 0; j < fh_ep->pkt_per_frm - 1; ++j) { ++ ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep->data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = fh_ep->proc_buf_num; ++ ++ data_per_desc = ++ ((j + 1) * fh_ep->maxpacket > ++ fh_ep->data_per_frame) ? fh_ep->data_per_frame - ++ j * fh_ep->maxpacket : fh_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ fh_ep->iso_desc_addr + ++ fh_ep->desc_cnt * fh_ep->proc_buf_num; ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = fh_ep->pkt_per_frm; ++ sts.b_iso_in.framenum = fh_ep->next_frame; ++ sts.b_iso_in.txbytes = fh_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ for (i = 0; i < fh_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ sts.b_iso_in.framenum += fh_ep->bInterval; ++ dma_ad += fh_ep->data_per_frame; ++ dma_desc++; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = fh_ep->proc_buf_num; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ fh_ep->next_frame = ++ sts.b_iso_in.framenum + fh_ep->bInterval * 1; ++ } ++ fh_ep->proc_buf_num = (fh_ep->proc_buf_num ^ 1) & 0x1; ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * in case Iso out packet was dropped ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param fh_ep The EP for wihich transfer complete was asserted ++ * ++ */ ++static uint32_t handle_iso_out_pkt_dropped(fh_otg_core_if_t * core_if, ++ fh_ep_t * fh_ep) ++{ ++ uint32_t dma_addr; ++ uint32_t drp_pkt; ++ uint32_t drp_pkt_cnt; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ int i; ++ ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[fh_ep->num]->doeptsiz); ++ ++ drp_pkt = fh_ep->pkt_cnt - deptsiz.b.pktcnt; ++ drp_pkt_cnt = fh_ep->pkt_per_frm - (drp_pkt % fh_ep->pkt_per_frm); ++ ++ /* Setting dropped packets status */ ++ for (i = 0; i < drp_pkt_cnt; ++i) { ++ fh_ep->pkt_info[drp_pkt].status = -FH_E_NO_DATA; ++ drp_pkt++; ++ deptsiz.b.pktcnt--; ++ } ++ ++ if (deptsiz.b.pktcnt > 0) { ++ deptsiz.b.xfersize = ++ fh_ep->xfer_len - (fh_ep->pkt_cnt - ++ deptsiz.b.pktcnt) * fh_ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 0; ++ } ++ ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doeptsiz, ++ deptsiz.d32); ++ ++ if (deptsiz.b.pktcnt > 0) { ++ if (fh_ep->proc_buf_num) { ++ dma_addr = ++ fh_ep->dma_addr1 + fh_ep->xfer_len - ++ deptsiz.b.xfersize; ++ } else { ++ dma_addr = ++ fh_ep->dma_addr0 + fh_ep->xfer_len - ++ deptsiz.b.xfersize;; ++ } ++ ++ FH_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[fh_ep->num]->doepdma, dma_addr); ++ ++ /** Re-enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ FH_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[fh_ep->num]->doepctl, depctl.d32, ++ depctl.d32); ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function sets iso packets information(PTI mode) ++ * ++ * @param core_if Programming view of FH_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++static uint32_t set_iso_pkts_info(fh_otg_core_if_t * core_if, fh_ep_t * ep) ++{ ++ int i, j; ++ dma_addr_t dma_ad; ++ iso_pkt_info_t *packet_info = ep->pkt_info; ++ uint32_t offset; ++ uint32_t frame_data; ++ deptsiz_data_t deptsiz; ++ ++ if (ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = ep->dma_addr1; ++ } ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz); ++ } else { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ offset = 0; ++ for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) { ++ frame_data = ep->data_per_frame; ++ for (j = 0; j < ep->pkt_per_frm; ++j) { ++ ++ /* Packet status - is not set as initially ++ * it is set to 0 and if packet was sent ++ successfully, status field will remain 0*/ ++ ++ /* Bytes has been transfered */ ++ packet_info->length = ++ (ep->maxpacket < ++ frame_data) ? ep->maxpacket : frame_data; ++ ++ /* Received packet offset */ ++ packet_info->offset = offset; ++ offset += packet_info->length; ++ frame_data -= packet_info->length; ++ ++ packet_info++; ++ } ++ } ++ return 1; ++ } else { ++ /* This is a workaround for in case of Transfer Complete with ++ * PktDrpSts interrupts merging - in this case Transfer complete ++ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts ++ * set and with DOEPTSIZ register non zero. Investigations showed, ++ * that this happens when Out packet is dropped, but because of ++ * interrupts merging during first interrupt handling PktDrpSts ++ * bit is cleared and for next merged interrupts it is not reset. ++ * In this case SW hadles the interrupt as if PktDrpSts bit is set. ++ */ ++ if (ep->is_in) { ++ return 1; ++ } else { ++ return handle_iso_out_pkt_dropped(core_if, ep); ++ } ++ } ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * ++ * @param pcd The PCD ++ * @param ep The EP for which transfer complete was asserted ++ * ++ */ ++static void complete_iso_ep(fh_otg_pcd_t * pcd, fh_otg_pcd_ep_t * ep) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ fh_ep_t *fh_ep = &ep->fh_ep; ++ uint8_t is_last = 0; ++ ++ if (ep->fh_ep.next_frame == 0xffffffff) { ++ FH_WARN("Next frame is not set!\n"); ++ return; ++ } ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ set_ddma_iso_pkts_info(core_if, fh_ep); ++ reinit_ddma_iso_xfer(core_if, fh_ep); ++ is_last = 1; ++ } else { ++ if (core_if->pti_enh_enable) { ++ if (set_iso_pkts_info(core_if, fh_ep)) { ++ fh_ep->proc_buf_num = ++ (fh_ep->proc_buf_num ^ 1) & 0x1; ++ fh_otg_iso_ep_start_buf_transfer ++ (core_if, fh_ep); ++ is_last = 1; ++ } ++ } else { ++ set_current_pkt_info(core_if, fh_ep); ++ if (fh_ep->cur_pkt >= fh_ep->pkt_cnt) { ++ is_last = 1; ++ fh_ep->cur_pkt = 0; ++ fh_ep->proc_buf_num = ++ (fh_ep->proc_buf_num ^ 1) & 0x1; ++ if (fh_ep->proc_buf_num) { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff1; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr1; ++ } else { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff0; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr0; ++ } ++ ++ } ++ fh_otg_iso_ep_start_frm_transfer(core_if, ++ fh_ep); ++ } ++ } ++ } else { ++ set_current_pkt_info(core_if, fh_ep); ++ if (fh_ep->cur_pkt >= fh_ep->pkt_cnt) { ++ is_last = 1; ++ fh_ep->cur_pkt = 0; ++ fh_ep->proc_buf_num = (fh_ep->proc_buf_num ^ 1) & 0x1; ++ if (fh_ep->proc_buf_num) { ++ fh_ep->cur_pkt_addr = fh_ep->xfer_buff1; ++ fh_ep->cur_pkt_dma_addr = fh_ep->dma_addr1; ++ } else { ++ fh_ep->cur_pkt_addr = fh_ep->xfer_buff0; ++ fh_ep->cur_pkt_dma_addr = fh_ep->dma_addr0; ++ } ++ ++ } ++ fh_otg_iso_ep_start_frm_transfer(core_if, fh_ep); ++ } ++ if (is_last) ++ fh_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); ++} ++#endif /* FH_EN_ISOC */ ++ ++/** ++ * This function handle BNA interrupt for Non Isochronous EPs ++ * ++ */ ++static void fh_otg_pcd_handle_noniso_bna(fh_otg_pcd_ep_t * ep) ++{ ++ fh_ep_t *fh_ep = &ep->fh_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ fh_otg_pcd_t *pcd = ep->pcd; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ fh_otg_core_if_t *core_if = ep->pcd->core_if; ++ int i, start; ++ ++ if (!fh_ep->desc_cnt) ++ FH_WARN("Ep%d %s Descriptor count = %d \n", fh_ep->num, ++ (fh_ep->is_in ? "IN" : "OUT"), fh_ep->desc_cnt); ++ ++ if (core_if->core_params->cont_on_bna && !fh_ep->is_in ++ && fh_ep->type != FH_OTG_EP_TYPE_CONTROL) { ++ uint32_t doepdma; ++ fh_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[fh_ep->num]; ++ doepdma = FH_READ_REG32(&(out_regs->doepdma)); ++ start = (doepdma - fh_ep->dma_desc_addr)/sizeof(fh_otg_dev_dma_desc_t); ++ dma_desc = &(fh_ep->desc_addr[start]); ++ } else { ++ start = 0; ++ dma_desc = fh_ep->desc_addr; ++ } ++ ++ ++ for (i = start; i < fh_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ ++ if (fh_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[fh_ep->num]-> ++ doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[fh_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_MODIFY_REG32(addr, 0, depctl.d32); ++} ++ ++/** ++ * This function handles EP0 Control transfers. ++ * ++ * The state of the control transfers are tracked in ++ * <code>ep0state</code>. ++ */ ++static void handle_ep0(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ dev_dma_desc_sts_t desc_sts; ++ deptsiz0_data_t deptsiz; ++ uint32_t byte_count; ++ ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ print_ep0_state(pcd); ++#endif ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ break; ++ ++ case EP0_IDLE: ++ pcd->request_config = 0; ++ ++ pcd_setup(pcd); ++ break; ++ ++ case EP0_IN_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", ++ ep0->fh_ep.num, (ep0->fh_ep.is_in ? "IN" : "OUT"), ++ ep0->fh_ep.type, ep0->fh_ep.maxpacket); ++#endif ++ ++ if (core_if->dma_enable != 0) { ++ /* ++ * For EP0 we can only program 1 packet at a time so we ++ * need to do the make calculations after each complete. ++ * Call write_packet to make the calculations, as in ++ * slave mode, and use those values to determine if we ++ * can complete. ++ */ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[0]-> ++ dieptsiz); ++ byte_count = ++ ep0->fh_ep.xfer_len - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->in_desc_addr->status; ++ byte_count = ++ ep0->fh_ep.xfer_len - desc_sts.b.bytes; ++ } ++ ep0->fh_ep.xfer_count += byte_count; ++ ep0->fh_ep.xfer_buff += byte_count; ++ ep0->fh_ep.dma_addr += byte_count; ++ } ++ if (ep0->fh_ep.xfer_count < ep0->fh_ep.total_len) { ++ fh_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->fh_ep); ++ FH_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->fh_ep.sent_zlp) { ++ fh_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->fh_ep); ++ ep0->fh_ep.sent_zlp = 0; ++ FH_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ FH_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ case EP0_OUT_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", ++ ep0->fh_ep.num, (ep0->fh_ep.is_in ? "IN" : "OUT"), ++ ep0->fh_ep.type, ep0->fh_ep.maxpacket); ++#endif ++ if (core_if->dma_enable != 0) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if-> ++ dev_if->out_ep_regs[0]-> ++ doeptsiz); ++ byte_count = ++ ep0->fh_ep.maxpacket - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->out_desc_addr->status; ++ byte_count = ++ ep0->fh_ep.maxpacket - desc_sts.b.bytes; ++ } ++ ep0->fh_ep.xfer_count += byte_count; ++ ep0->fh_ep.xfer_buff += byte_count; ++ ep0->fh_ep.dma_addr += byte_count; ++ } ++ if (ep0->fh_ep.xfer_count < ep0->fh_ep.total_len) { ++ fh_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->fh_ep); ++ FH_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->fh_ep.sent_zlp) { ++ fh_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->fh_ep); ++ ep0->fh_ep.sent_zlp = 0; ++ FH_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ FH_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ case EP0_OUT_STATUS_PHASE: ++ FH_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); ++ ep0_complete_request(ep0); ++ pcd->ep0state = EP0_IDLE; ++ ep0->stopped = 1; ++ ep0->fh_ep.is_in = 0; /* OUT for next SETUP */ ++ ++ /* Prepare for more SETUP Packets */ ++ if (core_if->dma_enable) { ++ ep0_out_start(core_if, pcd); ++ } ++ break; ++ ++ case EP0_STALL: ++ FH_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); ++ break; ++ } ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++} ++ ++/** ++ * Restart transfer ++ */ ++static void restart_transfer(fh_otg_pcd_t * pcd, const uint32_t epnum) ++{ ++ fh_otg_core_if_t *core_if; ++ fh_otg_dev_if_t *dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ fh_otg_pcd_ep_t *ep; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++#ifdef FH_EN_ISOC ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ return; ++ } ++#endif /* FH_EN_ISOC */ ++ ++ core_if = GET_CORE_IF(pcd); ++ dev_if = core_if->dev_if; ++ ++ dieptsiz.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ ++ FH_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" ++ " stopped=%d\n", ep->fh_ep.xfer_buff, ++ ep->fh_ep.xfer_count, ep->fh_ep.xfer_len, ep->stopped); ++ /* ++ * If xfersize is 0 and pktcnt in not 0, resend the last packet. ++ */ ++ if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && ++ ep->fh_ep.start_xfer_buff != 0) { ++ if (ep->fh_ep.total_len <= ep->fh_ep.maxpacket) { ++ ep->fh_ep.xfer_count = 0; ++ ep->fh_ep.xfer_buff = ep->fh_ep.start_xfer_buff; ++ ep->fh_ep.xfer_len = ep->fh_ep.xfer_count; ++ } else { ++ ep->fh_ep.xfer_count -= ep->fh_ep.maxpacket; ++ /* convert packet size to dwords. */ ++ ep->fh_ep.xfer_buff -= ep->fh_ep.maxpacket; ++ ep->fh_ep.xfer_len = ep->fh_ep.xfer_count; ++ } ++ ep->stopped = 0; ++ FH_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x " ++ "xfer_len=%0x stopped=%d\n", ++ ep->fh_ep.xfer_buff, ++ ep->fh_ep.xfer_count, ep->fh_ep.xfer_len, ++ ep->stopped); ++ if (epnum == 0) { ++ fh_otg_ep0_start_transfer(core_if, &ep->fh_ep); ++ } else { ++ fh_otg_ep_start_transfer(core_if, &ep->fh_ep); ++ } ++ } ++} ++ ++/* ++ * This function create new nextep sequnce based on Learn Queue. ++ * ++ * @param core_if Programming view of FH_otg controller ++ */ ++void predict_nextep_seq( fh_otg_core_if_t * core_if) ++{ ++ fh_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ uint8_t seqnum[MAX_EPS_CHANNELS]; ++ uint8_t intkn_seq[TOKEN_Q_DEPTH]; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint8_t temp; ++ int ndx = 0; ++ int start = 0; ++ int end = 0; ++ int sort_done = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ ++ FH_DEBUGPL(DBG_PCD, "dev_token_q_depth=%d\n", TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = FH_READ_REG32(addr); ++ FH_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ if (dtknqr1.b.wrap_bit) { ++ ndx = dtknqr1.b.intknwptr; ++ end = ndx - 1; ++ if (end < 0) ++ end = TOKEN_Q_DEPTH - 1; ++ } else { ++ ndx = 0; ++ end = dtknqr1.b.intknwptr - 1; ++ if (end < 0) ++ end = 0; ++ } ++ start = ndx; ++ ++ /* Fill seqnum[] by initial values: EP number + 31 */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ seqnum[i] = i + 31; ++ } ++ ++ /* Fill intkn_seq[] from in_tkn_epnums[0] */ ++ for (i = 0; (i < 6) && (i < TOKEN_Q_DEPTH); i++) ++ intkn_seq[i] = (in_tkn_epnums[0] >> ((7 - i) * 4)) & 0xf; ++ ++ if (TOKEN_Q_DEPTH > 6) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 6; (i < 14) && (i < TOKEN_Q_DEPTH); i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 14) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 14; (i < 22) && (i < TOKEN_Q_DEPTH); i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 22) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i = 22; (i < 30) && (i < TOKEN_Q_DEPTH); i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, ++ start, end); ++ for (i = 0; i < TOKEN_Q_DEPTH; i++) ++ FH_DEBUGPL(DBG_PCDV, "%d\n", intkn_seq[i]); ++ ++ /* Update seqnum based on intkn_seq[] */ ++ i = 0; ++ do { ++ seqnum[intkn_seq[ndx]] = i; ++ ndx++; ++ i++; ++ if (ndx == TOKEN_Q_DEPTH) ++ ndx = 0; ++ } while (i < TOKEN_Q_DEPTH); ++ ++ /* Mark non active EP's in seqnum[] by 0xff */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == 0xff) ++ seqnum[i] = 0xff; ++ } ++ ++ /* Sort seqnum[] */ ++ sort_done = 0; ++ while (!sort_done) { ++ sort_done = 1; ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] > seqnum[i + 1]) { ++ temp = seqnum[i]; ++ seqnum[i] = seqnum[i + 1]; ++ seqnum[i + 1] = temp; ++ sort_done = 0; ++ } ++ } ++ } ++ ++ ndx = start + seqnum[0]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ core_if->first_in_nextep_seq = intkn_seq[ndx]; ++ ++ /* Update seqnum[] by EP numbers */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ ndx = start + i; ++ if (seqnum[i] < 31) { ++ ndx = start + seqnum[i]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ seqnum[i] = intkn_seq[ndx]; ++ } else { ++ if (seqnum[i] < 0xff) { ++ seqnum[i] = seqnum[i] - 31; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Update nextep_seq[] based on seqnum[] */ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ if (seqnum[i] != 0xff) { ++ if (seqnum[i + 1] != 0xff) { ++ core_if->nextep_seq[seqnum[i]] = seqnum[i + 1]; ++ } else { ++ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; ++ break; ++ } ++ } else { ++ break; ++ } ++ } ++ ++ FH_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ FH_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ ++ /* Flush the Learning Queue */ ++ resetctl.d32 = FH_READ_REG32(&core_if->core_global_regs->grstctl); ++ resetctl.b.intknqflsh = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ ++} ++ ++/** ++ * handle the IN EP disable interrupt. ++ */ ++static inline void handle_in_ep_disable_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ gintmsk_data_t gintmsk_data; ++ depctl_data_t depctl; ++ uint32_t diepdma; ++ uint32_t remain_to_transfer = 0; ++ uint8_t i; ++ uint32_t xfer_size; ++ ++ ep = get_in_ep(pcd, epnum); ++ fh_ep = &ep->fh_ep; ++ ++ if (fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ fh_otg_flush_tx_fifo(core_if, fh_ep->tx_fifo_num); ++ complete_ep(ep); ++ return; ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); ++ dieptsiz.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ ++ FH_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++ ++ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { ++ if (ep->stopped) { ++ if (core_if->en_multiple_tx_fifo) ++ /* Flush the Tx FIFO */ ++ fh_otg_flush_tx_fifo(core_if, fh_ep->tx_fifo_num); ++ /* Clear the Global IN NP NAK */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ } else { ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ FH_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); ++ } ++ return; ++ } ++ ++ if (core_if->start_predict > 2) { // NP IN EP ++ core_if->start_predict--; ++ return; ++ } ++ ++ core_if->start_predict--; ++ ++ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now ++ ++ predict_nextep_seq(core_if); ++ ++ /* Update all active IN EP's NextEP field based of nextep_seq[] */ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP ++ depctl.b.nextep = core_if->nextep_seq[i]; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ } ++ /* Flush Shared NP TxFIFO */ ++ fh_otg_flush_tx_fifo(core_if, 0); ++ /* Rewind buffers */ ++ if (!core_if->dma_desc_enable) { ++ i = core_if->first_in_nextep_seq; ++ do { ++ ep = get_in_ep(pcd, i); ++ dieptsiz.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ xfer_size = ep->fh_ep.total_len - ep->fh_ep.xfer_count; ++ if (xfer_size > ep->fh_ep.maxxfer) ++ xfer_size = ep->fh_ep.maxxfer; ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ if (xfer_size == 0) { ++ remain_to_transfer = 0; ++ } else { ++ if ((xfer_size % ep->fh_ep.maxpacket) == 0) { ++ remain_to_transfer = ++ dieptsiz.b.pktcnt * ep->fh_ep.maxpacket; ++ } else { ++ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->fh_ep.maxpacket) ++ + (xfer_size % ep->fh_ep.maxpacket); ++ } ++ } ++ diepdma = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); ++ dieptsiz.b.xfersize = remain_to_transfer; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); ++ diepdma = ep->fh_ep.dma_addr + (xfer_size - remain_to_transfer); ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ } else { // dma_desc_enable ++ FH_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); ++ } ++ ++ /* Restart transfers in predicted sequences */ ++ i = core_if->first_in_nextep_seq; ++ do { ++ dieptsiz.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Unmask EP Mismatch interrupt */ ++ gintmsk_data.d32 = 0; ++ gintmsk_data.b.epmismatch = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); ++ ++ core_if->start_predict = 0; ++ ++ } ++} ++ ++/** ++ * Handler for the IN EP timeout handshake interrupt. ++ */ ++static inline void handle_in_ep_timeout_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ ++#ifdef DEBUG ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ uint32_t num = 0; ++#endif ++ dctl_data_t dctl = {.d32 = 0 }; ++ fh_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ /* Disable the NP Tx Fifo Empty Interrrupt */ ++ if (!core_if->dma_enable) { ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ /** @todo NGS Check EP type. ++ * Implement for Periodic EPs */ ++ /* ++ * Non-periodic EP ++ */ ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ ++ /* Set Global IN NAK */ ++ dctl.b.sgnpinnak = 1; ++ FH_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ ep->stopped = 1; ++ ++#ifdef DEBUG ++ dieptsiz.d32 = FH_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz); ++ FH_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++#endif ++ ++#ifdef DISABLE_PERIODIC_EP ++ /* ++ * Set the NAK bit for this EP to ++ * start the disable process. ++ */ ++ diepctl.d32 = 0; ++ diepctl.b.snak = 1; ++ FH_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, ++ diepctl.d32); ++ ep->disabling = 1; ++ ep->stopped = 1; ++#endif ++} ++ ++/** ++ * Handler for the IN EP NAK interrupt. ++ */ ++static inline int32_t handle_in_ep_nak_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ fh_otg_core_if_t *core_if; ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP Babble interrupt. ++ */ ++static inline int32_t handle_out_ep_babble_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ fh_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "OUT EP Babble"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.babble = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NAK interrupt. ++ */ ++static inline int32_t handle_out_ep_nak_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ fh_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NYET interrupt. ++ */ ++static inline int32_t handle_out_ep_nyet_intr(fh_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ fh_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nyet = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++static void handle_xfercompl_iso_ddma (fh_otg_dev_if_t *dev_if, fh_otg_pcd_ep_t *ep) ++{ ++ depctl_data_t depctl; ++ fh_ep_t *fh_ep; ++ uint32_t doepdma; ++ fh_dma_t dma_desc_addr; ++ fh_otg_dev_dma_desc_t *dma_desc; ++ int index = 0; ++ uint8_t epnum; ++ ++ fh_ep = &ep->fh_ep; ++ epnum = fh_ep->num; ++ ++ complete_ddma_iso_ep(ep); ++ ++ if (fh_ep->is_in) { ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (!depctl.b.epena) { ++ if (fh_ep->use_add_buf) { ++ FH_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ fh_ep->use_add_buf = 0; ++ fh_ep->iso_desc_first = 0; ++ if (fh_ep->iso_desc_second) { ++ depctl_data_t diepctl; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ fh_ep->dma_desc_addr1); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ FH_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ FH_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 1\n"); ++ } ++ } else { ++ FH_DEBUGPL(DBG_PCD, "go to first buffer \n"); ++ fh_ep->use_add_buf = 1; ++ fh_ep->iso_desc_second = 0; ++ if (fh_ep->iso_desc_first) { ++ depctl_data_t diepctl; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepdma, ++ fh_ep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ FH_MODIFY_REG32(&dev_if->in_ep_regs[epnum]->diepctl, ++ 0, diepctl.d32); ++ } else { ++ FH_DEBUGPL(DBG_PCD, "DDMA: No more ISOC requests 2\n"); ++ } ++ } ++ } ++ } else { ++ depctl.d32 = FH_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ doepdma = FH_READ_REG32(&dev_if->out_ep_regs[epnum]->doepdma); ++ ++ if (fh_ep->use_add_buf) { ++ index = fh_ep->iso_desc_first; ++ dma_desc_addr = fh_ep->dma_desc_addr; ++ } else { ++ index = fh_ep->iso_desc_second; ++ dma_desc_addr = fh_ep->dma_desc_addr1; ++ } ++ ++ if (index == (doepdma - dma_desc_addr)/sizeof(fh_otg_dev_dma_desc_t)) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ FH_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } ++ dma_desc = fh_ep->desc_addr + fh_ep->iso_desc_first; ++ if (!depctl.b.epena) { ++ if (fh_ep->use_add_buf) { ++ FH_DEBUGPL(DBG_PCD, "go to second buffer \n"); ++ fh_ep->use_add_buf = 0; ++ fh_ep->iso_desc_first = 0; ++ if (fh_ep->iso_desc_second) { ++ FH_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, fh_ep->dma_desc_addr1); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ FH_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 1!!! \n"); ++ } ++ } else { ++ fh_ep->use_add_buf = 1; ++ fh_ep->iso_desc_second = 0; ++ if (fh_ep->iso_desc_first) { ++ FH_DEBUGPL(DBG_PCD, "go to first buffer"); ++ FH_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepdma, fh_ep->dma_desc_addr); ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ FH_MODIFY_REG32(&dev_if->out_ep_regs[epnum]->doepctl, 0, depctl.d32); ++ } else { ++ FH_DEBUGPL(DBG_PCD, "DDMA: There are no more ISOC requests 2!!! \n"); ++ } ++ } ++ } ++ } ++} ++/** ++ * This interrupt indicates that an IN EP has a pending Interrupt. ++ * The sequence for handling the IN EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each IN EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DIEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Time-out Handshake" log error ++ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx ++ * FIFO. ++ * -# If "IN Token EP Mismatch" (disable, this is handled by EP ++ * Mismatch Interrupt) ++ */ ++static int32_t fh_otg_pcd_handle_in_ep_intr(fh_otg_pcd_t * pcd) ++{ ++#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ diepint_data_t diepint = {.d32=0}; \ ++ diepint.b.__intr = 1; \ ++ FH_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ ++ diepint.d32); \ ++} while (0) ++ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ fh_otg_dev_if_t *dev_if = core_if->dev_if; ++ diepint_data_t diepint = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ uint32_t ep_intr; ++ uint32_t epnum = 0; ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = fh_otg_read_dev_all_in_ep_intr(core_if); ++ ++ /* Service the Device IN interrupts for each endpoint */ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ uint32_t empty_msk; ++ /* Get EP pointer */ ++ ep = get_in_ep(pcd, epnum); ++ fh_ep = &ep->fh_ep; ++ ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ empty_msk = ++ FH_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", ++ epnum, empty_msk, depctl.d32); ++ ++ FH_DEBUGPL(DBG_PCD, ++ "EP%d-%s: type=%d, mps=%d\n", ++ fh_ep->num, (fh_ep->is_in ? "IN" : "OUT"), ++ fh_ep->type, fh_ep->maxpacket); ++ ++ diepint.d32 = ++ fh_otg_read_dev_in_ep_intr(core_if, fh_ep); ++ ++ FH_DEBUGPL(DBG_PCDV, ++ "EP %d Interrupt Register - 0x%x\n", epnum, ++ diepint.d32); ++ /* Transfer complete */ ++ if (diepint.b.xfercompl) { ++ /* Disable the NP Tx FIFO Empty ++ * Interrupt */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ FH_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } else { ++ /* Disable the Tx FIFO Empty Interrupt for this EP */ ++ uint32_t fifoemptymsk = ++ 0x1 << fh_ep->num; ++ FH_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ fifoemptymsk, 0); ++ } ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl); ++ ++ /* Complete the transfer */ ++ if (epnum == 0) { ++ handle_ep0(pcd); ++ } ++#ifdef FH_EN_ISOC ++ else if (fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_iso_ep(pcd, ep); ++ } ++#endif /* FH_EN_ISOC */ ++#ifdef FH_UTE_PER_IO ++ else if (fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++ } ++#endif /* FH_UTE_PER_IO */ ++ else { ++#if 0 ++ if (core_if->dma_desc_enable ++ && fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ handle_xfercompl_iso_ddma(dev_if, ep); ++ } else { ++ if (fh_ep->type == FH_OTG_EP_TYPE_ISOC ++ && fh_ep->bInterval > 1) { ++ fh_ep->frame_num += fh_ep->bInterval; ++ if (fh_ep->frame_num > 0x3FFF) ++ { ++ fh_ep->frm_overrun = 1; ++ fh_ep->frame_num &= 0x3FFF; ++ } else ++ fh_ep->frm_overrun = 0; ++ } ++#else ++ { ++#endif ++ complete_ep(ep); ++ if (diepint.b.nak) ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ } ++ /* Endpoint disable */ ++ if (diepint.b.epdisabled) { ++ FH_DEBUGPL(DBG_ANY, "EP%d IN disabled\n", ++ epnum); ++ handle_in_ep_disable_intr(pcd, epnum); ++ ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled); ++ } ++ /* AHB Error */ ++ if (diepint.b.ahberr) { ++ FH_ERROR("EP%d IN AHB Error\n", epnum); ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* TimeOUT Handshake (non-ISOC IN EPs) */ ++ if (diepint.b.timeout) { ++ FH_ERROR("EP%d IN Time-out\n", epnum); ++ handle_in_ep_timeout_intr(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, timeout); ++ } ++ /** IN Token received with TxF Empty */ ++ if (diepint.b.intktxfemp) { ++ FH_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN TxFifo Empty\n", ++ epnum); ++ if (!ep->stopped && epnum != 0) { ++ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ FH_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepeachintmsk ++ [epnum], diepmsk.d32, 0); ++ } else { ++ FH_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepmsk, ++ diepmsk.d32, 0); ++ } ++ } else if (core_if->dma_desc_enable ++ && epnum == 0 ++ && pcd->ep0state == ++ EP0_OUT_STATUS_PHASE) { ++ // EP0 IN set STALL ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ FH_WRITE_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); ++ } ++ /** IN Token Received with EP mismatch */ ++ if (diepint.b.intknepmis) { ++ FH_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN EP Mismatch\n", epnum); ++ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); ++ } ++ /** IN Endpoint NAK Effective */ ++ if (diepint.b.inepnakeff) { ++ FH_DEBUGPL(DBG_ANY, ++ "EP%d IN EP NAK Effective\n", ++ epnum); ++ /* Periodic EP */ ++ if (ep->disabling) { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ FH_MODIFY_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); ++ ++ } ++ ++ /** IN EP Tx FIFO Empty Intr */ ++ if (diepint.b.emptyintr) { ++ FH_DEBUGPL(DBG_ANY, ++ "EP%d Tx FIFO Empty Intr \n", ++ epnum); ++ write_empty_tx_fifo(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr); ++ ++ } ++ ++ /** IN EP BNA Intr */ ++ if (diepint.b.bna) { ++ CLEAR_IN_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef FH_EN_ISOC ++ if (fh_ep->type == ++ FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (fh_ep->next_frame != ++ 0xffffffff) ++ fh_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* FH_EN_ISOC */ ++ { ++ fh_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* NAK Interrupt */ ++ if (diepint.b.nak) { ++ FH_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", ++ epnum); ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (ep->fh_ep.frame_num == 0xFFFFFFFF) { ++ ep->fh_ep.frame_num = core_if->frame_num; ++ fh_otg_pcd_start_iso_ddma(core_if, ep); ++ } else { ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } else { ++ depctl_data_t depctl; ++ if (ep->fh_ep.frame_num == 0xFFFFFFFF) { ++ ep->fh_ep.frame_num = core_if->frame_num; ++ if (ep->fh_ep.bInterval > 1) { ++ depctl.d32 = 0; ++ depctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (ep->fh_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ FH_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ } ++ ep->fh_ep.frame_num += ep->fh_ep.bInterval; ++ if (fh_ep->frame_num > 0x3FFF) { ++ fh_ep->frm_overrun = 1; ++ fh_ep->frame_num &= 0x3FFF; ++ } else { ++ fh_ep->frm_overrun = 0; ++ } ++ } ++ } ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++#undef CLEAR_IN_EP_INTR ++} ++ ++/** ++ * This interrupt indicates that an OUT EP has a pending Interrupt. ++ * The sequence for handling the OUT EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each OUT EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DOEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Setup Phase Done" process Setup Packet (See Standard USB ++ * Command Processing) ++ */ ++static int32_t fh_otg_pcd_handle_out_ep_intr(fh_otg_pcd_t * pcd) ++{ ++#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ doepint_data_t doepint = {.d32=0}; \ ++ doepint.b.__intr = 1; \ ++ FH_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ ++ doepint.d32); \ ++} while (0) ++ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ uint32_t ep_intr; ++ doepint_data_t doepint = {.d32 = 0 }; ++ uint32_t epnum = 0; ++ fh_otg_pcd_ep_t *ep; ++ fh_ep_t *fh_ep; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ ++ FH_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = fh_otg_read_dev_all_out_ep_intr(core_if); ++ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ /* Get EP pointer */ ++ ep = get_out_ep(pcd, epnum); ++ fh_ep = &ep->fh_ep; ++ ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, ++ "EP%d-%s: type=%d, mps=%d\n", ++ fh_ep->num, (fh_ep->is_in ? "IN" : "OUT"), ++ fh_ep->type, fh_ep->maxpacket); ++#endif ++ doepint.d32 = ++ fh_otg_read_dev_out_ep_intr(core_if, fh_ep); ++ ++ /* Transfer complete */ ++ if (doepint.b.xfercompl) { ++ ++ if (epnum == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ FH_DEBUGPL(DBG_PCDV, "in xfer xomplete DOEPINT=%x doepint=%x\n", ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), ++ doepint.d32); ++ FH_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable == 0) { ++ doepint_data_t doepint; ++ doepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (doepint.b.stsphsercvd) ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ goto exit_xfercompl; ++ } ++ } ++ /* In case of DDMA look at SR bit to go to the Data Stage */ ++ if (core_if->dma_desc_enable) { ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ if (pcd->ep0state == EP0_IDLE) { ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ if(pcd->data_terminated) { ++ pcd->data_terminated = 0; ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ fh_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); ++ } ++ if (status.b.sr) { ++ if (doepint.b.setup) { ++ FH_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ FH_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } else { ++ fh_otg_pcd_request_t *req; ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ diepint_data_t diepint0; ++ diepint0.d32 = FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ ++ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { ++ FH_ERROR("EP0 is stalled/disconnected\n"); ++ } ++ ++ /* Clear IN xfercompl if set */ ++ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_DATA_PHASE)) { ++ FH_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ ++ if ((pcd->ep0state == EP0_OUT_STATUS_PHASE) || ++ (ep->fh_ep.xfer_count != ep->fh_ep.total_len ++ && pcd->ep0state == EP0_OUT_DATA_PHASE)) ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ if (status.b.sr) { ++ if (FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ FH_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ FH_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->fh_ep.xfer_count != ep->fh_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ fh_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->fh_ep.xfer_count, 8); ++ } ++ req->actual = ep->fh_ep.xfer_count; ++ fh_otg_request_done(ep, req, -ECONNRESET); ++ ep->fh_ep.start_xfer_buff = 0; ++ ep->fh_ep.xfer_buff = 0; ++ ep->fh_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ FH_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ FH_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a && core_if->dma_enable ++ && core_if->dma_desc_enable == 0) { ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ doepint_temp.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->fh_ep.num]->doepint); ++ doeptsize0.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->fh_ep.num]->doeptsiz); ++ if (((ep->fh_ep.xfer_count == ep->fh_ep.total_len || doeptsize0.b.xfersize == 64) && ++ pcd->ep0state == EP0_OUT_DATA_PHASE && doepint.b.stsphsercvd) || ++ (doeptsize0.b.xfersize == 24 && pcd->ep0state == EP0_IN_STATUS_PHASE)) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ FH_DEBUGPL(DBG_PCDV, "WA for xfercompl along with stsphs \n"); ++ doepint.b.xfercompl = 0; ++ ep0_out_start(core_if, pcd); ++ goto exit_xfercompl; ++ } ++ ++ if (pcd->ep0state == EP0_IDLE) { ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ } ++ /* Delay is needed for core to update setup ++ * packet count from 3 to 2 after receiving ++ * setup packet*/ ++ fh_udelay(100); ++ doepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (doeptsize0.b.supcnt == 3) { ++ FH_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); ++ ep->fh_ep.stp_rollover = 1; ++ } ++ if (doepint.b.setup) { ++retry: ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ ep->fh_ep.stp_rollover = 0; ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ FH_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ FH_DEBUGPL(DBG_ANY, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ doepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if(doepint.b.setup) ++ goto retry; ++ ep0_out_start(core_if, pcd); ++ } ++ } else { ++ fh_otg_pcd_request_t *req; ++ diepint_data_t diepint0 = {.d32 = 0}; ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ depctl_data_t diepctl0; ++ diepint0.d32 = FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ diepctl0.d32 = FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0state == EP0_IN_DATA_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (diepint0.b.xfercompl) { ++ FH_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ if (diepctl0.b.epena) { ++ diepint_data_t diepint = {.d32 = 0}; ++ diepctl0.b.snak = 1; ++ FH_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl, diepctl0.d32); ++ do { ++ fh_udelay(10); ++ diepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ FH_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint.d32); ++ diepctl0.d32 = 0; ++ diepctl0.b.epdis = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ diepctl0.d32); ++ do { ++ fh_udelay(10); ++ diepint.d32 = FH_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ FH_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, ++ diepint.d32); ++ } ++ } ++ doepint_temp.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->fh_ep.num]->doepint); ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ FH_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ FH_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->fh_ep.xfer_count != ep->fh_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ fh_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->fh_ep.xfer_count, 8); ++ } ++ req->actual = ep->fh_ep.xfer_count; ++ fh_otg_request_done(ep, req, -ECONNRESET); ++ ep->fh_ep.start_xfer_buff = 0; ++ ep->fh_ep.xfer_buff = 0; ++ ep->fh_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ FH_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ depctl_data_t depctl = {.d32 = 0}; ++ depctl.b.cnak = 1; ++ ep0_out_start(core_if, pcd); ++ /* Core not updating setup packet count ++ * in case of PET testing - @TODO vahrama ++ * to check with HW team further */ ++ if (!core_if->otg_ver) { ++ FH_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepctl, 0, depctl.d32); ++ } ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ FH_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++exit_xfercompl: ++ FH_DEBUGPL(DBG_PCDV, "after DOEPINT=%x doepint=%x\n", ++ fh_otg_read_dev_out_ep_intr(core_if, fh_ep), doepint.d32); ++ } else { ++ if (core_if->dma_desc_enable == 0 ++ || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++ } ++#ifdef FH_EN_ISOC ++ } else if (fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ if (doepint.b.pktdrpsts == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, ++ epnum, ++ xfercompl); ++ complete_iso_ep(pcd, ep); ++ } else { ++ ++ doepint_data_t doepint = {.d32 = 0 }; ++ doepint.b.xfercompl = 1; ++ doepint.b.pktdrpsts = 1; ++ FH_WRITE_REG32 ++ (&core_if->dev_if->out_ep_regs ++ [epnum]->doepint, ++ doepint.d32); ++ if (handle_iso_out_pkt_dropped ++ (core_if, fh_ep)) { ++ complete_iso_ep(pcd, ++ ep); ++ } ++ } ++#endif /* FH_EN_ISOC */ ++#ifdef FH_UTE_PER_IO ++ } else if (fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++#endif /* FH_UTE_PER_IO */ ++ } else { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ ++ if (core_if->core_params->dev_out_nak) { ++ FH_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); ++ pcd->core_if->ep_xfer_info[epnum].state = 0; ++#ifdef DEBUG ++ print_memory_payload(pcd, fh_ep); ++#endif ++ } ++ if (core_if->dma_desc_enable && fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * handle_xfercompl_iso_ddma ++ * (core_if->dev_if, ep); ++ */ ++ complete_ep(ep); ++ } else { ++ complete_ep(ep); ++ } ++ } ++ ++ } ++ if (doepint.b.stsphsercvd) { ++ deptsiz0_data_t deptsiz; ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doeptsiz); ++ if ((core_if->dma_desc_enable) || (core_if->dma_enable && ++ core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ do_setup_in_status_phase(pcd); ++ } ++ } ++ ++ /* Endpoint disable */ ++ if (doepint.b.epdisabled) { ++ ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); ++ if (core_if->core_params->dev_out_nak) { ++#ifdef DEBUG ++ print_memory_payload(pcd, fh_ep); ++#endif ++ /* In case of timeout condition */ ++ if (core_if->ep_xfer_info[epnum].state == 2) { ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ /* Unmask goutnakeff interrupt which was masked ++ * during handle nak out interrupt */ ++ gintmsk.b.goutnakeff = 1; ++ FH_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ ++ complete_ep(ep); ++ } ++ } ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) ++ { ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0}; ++ fh_otg_pcd_request_t *req = 0; ++ ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++ /* Get any pending requests */ ++ if (!FH_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = FH_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ FH_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ } else { ++ fh_otg_request_done(ep, req, 0); ++ start_next_request(ep); ++ } ++ } else { ++ FH_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ } ++ } ++ } ++ /* AHB Error */ ++ if (doepint.b.ahberr) { ++ FH_ERROR("EP%d OUT AHB Error\n", epnum); ++ FH_ERROR("EP%d DEPDMA=0x%08x \n", ++ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); ++ CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* Setup Phase Done (contorl EPs) */ ++ if (doepint.b.setup) { ++#ifdef DEBUG_EP0 ++ FH_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); ++#endif ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ ++ handle_ep0(pcd); ++ } ++ ++ /** OUT EP BNA Intr */ ++ if (doepint.b.bna) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef FH_EN_ISOC ++ if (fh_ep->type == ++ FH_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (fh_ep->next_frame != ++ 0xffffffff) ++ fh_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* FH_EN_ISOC */ ++ if (ep->fh_ep.type != FH_OTG_EP_TYPE_ISOC) { ++ fh_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* Babble Interrupt */ ++ if (doepint.b.babble) { ++ FH_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", ++ epnum); ++ handle_out_ep_babble_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, babble); ++ } ++ if (doepint.b.outtknepdis) { ++ FH_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ ++ disabled\n",epnum); ++ if (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ if (core_if->dma_desc_enable) { ++ if (!ep->fh_ep.iso_transfer_started) { ++ ep->fh_ep.frame_num = core_if->frame_num; ++ fh_otg_pcd_start_iso_ddma(core_if, ep); ++ } ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0}; ++ ep->fh_ep.frame_num = core_if->frame_num; ++ if (ep->fh_ep.bInterval > 1) { ++ depctl_data_t depctl; ++ depctl.d32 = FH_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl); ++ if (ep->fh_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ FH_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl, depctl.d32); ++ } ++ ++ start_next_request(ep); ++ doepmsk.b.outtknepdis = 1; ++ FH_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ doepmsk.d32, 0); ++ } ++ } ++ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); ++ } ++ ++ /* NAK Interrutp */ ++ if (doepint.b.nak) { ++ FH_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); ++ handle_out_ep_nak_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nak); ++ } ++ /* NYET Interrutp */ ++ if (doepint.b.nyet) { ++ FH_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum); ++ handle_out_ep_nyet_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nyet); ++ } ++ } ++ ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++ ++#undef CLEAR_OUT_EP_INTR ++} ++static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) ++{ ++ int retval = 0; ++ if(!frm_overrun && curr_fr >= trgt_fr) ++ retval = 1; ++ else if (frm_overrun ++ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) ++ retval = 1; ++ return retval; ++} ++ ++/** ++ * Incomplete ISO IN Transfer Interrupt. ++ * This interrupt indicates one of the following conditions occurred ++ * while transmitting an ISOC transaction. ++ * - Corrupted IN Token for ISOC EP. ++ * - Packet not complete in FIFO. ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in fh_ep structure ++ * -# Disable EP; when "Endpoint Disabled" interrupt is received ++ * Flush FIFO ++ */ ++int32_t fh_otg_pcd_handle_incomplete_isoc_in_intr(fh_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++#ifdef FH_EN_ISOC ++ fh_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ fh_ep_t *fh_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ fh_ep = &pcd->in_ep[i].fh_ep; ++ if (fh_ep->active && fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), fh_ep); ++ if (fh_ep->cur_pkt >= fh_ep->pkt_cnt) { ++ fh_ep->cur_pkt = 0; ++ fh_ep->proc_buf_num = ++ (fh_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (fh_ep->proc_buf_num) { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff1; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr1; ++ } else { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff0; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ fh_ep->next_frame = dsts.b.soffn; ++ ++ fh_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ fh_ep); ++ } ++ } ++ } ++ ++#else ++ depctl_data_t depctl = {.d32 = 0 }; ++ fh_ep_t *fh_ep; ++ fh_otg_dev_if_t *dev_if; ++ int i; ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ FH_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ fh_ep = &pcd->in_ep[i-1].fh_ep; ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena && fh_ep->type == FH_OTG_EP_TYPE_ISOC) { ++ if (drop_transfer(fh_ep->frame_num, GET_CORE_IF(pcd)->frame_num, ++ fh_ep->frm_overrun)) ++ { ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ FH_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); ++ } ++ } ++ } ++ ++ /*intr_mask.b.incomplisoin = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); */ ++#endif //FH_EN_ISOC ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoin = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Incomplete ISO OUT Transfer Interrupt. ++ * ++ * This interrupt indicates that the core has dropped an ISO OUT ++ * packet. The following conditions can be the cause: ++ * - FIFO Full, the entire packet would not fit in the FIFO. ++ * - CRC Error ++ * - Corrupted Token ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in fh_ep structure ++ * -# Read any data from the FIFO ++ * -# Disable EP. When "Endpoint Disabled" interrupt is received ++ * re-enable EP. ++ */ ++int32_t fh_otg_pcd_handle_incomplete_isoc_out_intr(fh_otg_pcd_t * pcd) ++{ ++ ++ gintsts_data_t gintsts; ++ ++#ifdef FH_EN_ISOC ++ fh_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ fh_ep_t *fh_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_out_eps; ++i) { ++ fh_ep = &pcd->in_ep[i].fh_ep; ++ if (pcd->out_ep[i].fh_ep.active && ++ pcd->out_ep[i].fh_ep.type == FH_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ FH_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); ++ depctl.d32 = ++ FH_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), ++ &pcd->out_ep[i].fh_ep); ++ if (fh_ep->cur_pkt >= fh_ep->pkt_cnt) { ++ fh_ep->cur_pkt = 0; ++ fh_ep->proc_buf_num = ++ (fh_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (fh_ep->proc_buf_num) { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff1; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr1; ++ } else { ++ fh_ep->cur_pkt_addr = ++ fh_ep->xfer_buff0; ++ fh_ep->cur_pkt_dma_addr = ++ fh_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ FH_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ fh_ep->next_frame = dsts.b.soffn; ++ ++ fh_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ fh_ep); ++ } ++ } ++ } ++#else ++ /** @todo implement ISR */ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ fh_otg_core_if_t *core_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ fh_ep_t *fh_ep = NULL; ++ int i; ++ core_if = GET_CORE_IF(pcd); ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ fh_ep = &pcd->out_ep[i].fh_ep; ++ depctl.d32 = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doepctl); ++ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { ++ core_if->dev_if->isoc_ep = fh_ep; ++ deptsiz.d32 = ++ FH_READ_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doeptsiz); ++ break; ++ } ++ } ++ dctl.d32 = FH_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = FH_READ_REG32(&core_if->core_global_regs->gintsts); ++ intr_mask.d32 = FH_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ if (!intr_mask.b.goutnakeff) { ++ /* Unmask it */ ++ intr_mask.b.goutnakeff = 1; ++ FH_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); ++ } ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ FH_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ depctl.d32 = FH_READ_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doepctl); ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } ++ FH_WRITE_REG32(&core_if->dev_if->out_ep_regs[fh_ep->num]->doepctl, depctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++#endif /* FH_EN_ISOC */ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoout = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Global IN NAK Effective interrupt. ++ * ++ */ ++int32_t fh_otg_pcd_handle_in_nak_effective(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int i; ++ ++ FH_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); ++ ++ /* Disable all active IN EPs */ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ diepctl.d32 = FH_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { ++ if (core_if->start_predict > 0) ++ core_if->start_predict++; ++ diepctl.b.epdis = 1; ++ diepctl.b.snak = 1; ++ FH_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32); ++ } ++ } ++ ++ ++ /* Disable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.ginnakeff = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * OUT NAK Effective. ++ * ++ */ ++int32_t fh_otg_pcd_handle_out_nak_effective(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ depctl_data_t doepctl; ++ int i; ++ ++ /* Disable the Global OUT NAK Effective Interrupt */ ++ intr_mask.b.goutnakeff = 1; ++ FH_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* If DEV OUT NAK enabled */ ++ if (pcd->core_if->core_params->dev_out_nak) { ++ /* Run over all out endpoints to determine the ep number on ++ * which the timeout has happened ++ */ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ if (pcd->core_if->ep_xfer_info[i].state == 2) ++ break; ++ } ++ if (i > dev_if->num_out_eps) { ++ dctl_data_t dctl; ++ dctl.d32 = ++ FH_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ FH_WRITE_REG32(&dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ goto out; ++ } ++ ++ /* Disable the endpoint */ ++ doepctl.d32 = FH_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ FH_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ return 1; ++ } ++ /* We come here from Incomplete ISO OUT handler */ ++ if (dev_if->isoc_ep) { ++ fh_ep_t *fh_ep = (fh_ep_t *) dev_if->isoc_ep; ++ uint32_t epnum = fh_ep->num; ++ doepint_data_t doepint; ++ doepint.d32 = ++ FH_READ_REG32(&dev_if->out_ep_regs[fh_ep->num]->doepint); ++ dev_if->isoc_ep = NULL; ++ doepctl.d32 = ++ FH_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ FH_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ FH_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, ++ doepctl.d32); ++ return 1; ++ } else ++ FH_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "Global OUT NAK Effective\n"); ++ ++out: ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ FH_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * PCD interrupt handler. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * ++ * All interrupt registers are processed from LSB to MSB. ++ * ++ */ ++int32_t fh_otg_pcd_handle_intr(fh_otg_pcd_t * pcd) ++{ ++ fh_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++#ifdef VERBOSE ++ fh_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ gintsts_data_t gintr_status; ++ int32_t retval = 0; ++ ++ if (fh_otg_check_haps_status(core_if) == -1 ) { ++ FH_WARN("HAPS is disconnected"); ++ return retval; ++ } ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ FH_READ_REG32(&global_regs->gintsts), ++ FH_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ if (fh_otg_is_device_mode(core_if)) { ++ FH_SPINLOCK(pcd->lock); ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ FH_READ_REG32(&global_regs->gintsts), ++ FH_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ gintr_status.d32 = fh_otg_read_core_intr(core_if); ++ ++ FH_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", ++ __func__, gintr_status.d32); ++ ++ if (gintr_status.b.sofintr) { ++ retval |= fh_otg_pcd_handle_sof_intr(pcd); ++ } ++ if (gintr_status.b.rxstsqlvl) { ++ retval |= ++ fh_otg_pcd_handle_rx_status_q_level_intr(pcd); ++ } ++ if (gintr_status.b.nptxfempty) { ++ retval |= fh_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); ++ } ++ if (gintr_status.b.goutnakeff) { ++ retval |= fh_otg_pcd_handle_out_nak_effective(pcd); ++ } ++ if (gintr_status.b.i2cintr) { ++ retval |= fh_otg_pcd_handle_i2c_intr(pcd); ++ } ++ if (gintr_status.b.erlysuspend) { ++ retval |= fh_otg_pcd_handle_early_suspend_intr(pcd); ++ } ++ if (gintr_status.b.usbreset) { ++ retval |= fh_otg_pcd_handle_usb_reset_intr(pcd); ++ } ++ if (gintr_status.b.enumdone) { ++ retval |= fh_otg_pcd_handle_enum_done_intr(pcd); ++ } ++ if (gintr_status.b.isooutdrop) { ++ retval |= ++ fh_otg_pcd_handle_isoc_out_packet_dropped_intr ++ (pcd); ++ } ++ if (gintr_status.b.eopframe) { ++ retval |= ++ fh_otg_pcd_handle_end_periodic_frame_intr(pcd); ++ } ++ if (gintr_status.b.inepint) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= fh_otg_pcd_handle_in_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.outepintr) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= fh_otg_pcd_handle_out_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.epmismatch) { ++ retval |= fh_otg_pcd_handle_ep_mismatch_intr(pcd); ++ } ++ if (gintr_status.b.fetsusp) { ++ retval |= fh_otg_pcd_handle_ep_fetsusp_intr(pcd); ++ } ++ if (gintr_status.b.ginnakeff) { ++ retval |= fh_otg_pcd_handle_in_nak_effective(pcd); ++ } ++ if (gintr_status.b.incomplisoin) { ++ retval |= ++ fh_otg_pcd_handle_incomplete_isoc_in_intr(pcd); ++ } ++ if (gintr_status.b.incomplisoout) { ++ retval |= ++ fh_otg_pcd_handle_incomplete_isoc_out_intr(pcd); ++ } ++ ++ /* In MPI mode Device Endpoints interrupts are asserted ++ * without setting outepintr and inepint bits set, so these ++ * Interrupt handlers are called without checking these bit-fields ++ */ ++ if (core_if->multiproc_int_enable) { ++ retval |= fh_otg_pcd_handle_in_ep_intr(pcd); ++ retval |= fh_otg_pcd_handle_out_ep_intr(pcd); ++ } ++#ifdef VERBOSE ++ FH_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, ++ FH_READ_REG32(&global_regs->gintsts)); ++#endif ++ FH_SPINUNLOCK(pcd->lock); ++ } ++ return retval; ++} ++ ++#endif /* FH_HOST_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_linux.c b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_linux.c +new file mode 100644 +index 00000000..ebeed66d +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_pcd_linux.c +@@ -0,0 +1,1447 @@ ++ /* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_pcd_linux.c $ ++ * $Revision: #30 $ ++ * $Date: 2015/08/06 $ ++ * $Change: 2913039 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef FH_HOST_ONLY ++ ++/** @file ++ * This file implements the Peripheral Controller Driver. ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for ++ * translating requests from the Function Driver into the appropriate ++ * actions on the FH_otg controller. It isolates the Function Driver ++ * from the specifics of the controller by providing an API to the ++ * Function Driver. ++ * ++ * The Peripheral Controller Driver for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. ++ * (Gadget Driver is the Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file ++ * <code><linux/usb_gadget.h></code>. The USB EP operations API is ++ * defined in the structure <code>usb_ep_ops</code> and the USB ++ * Controller API is defined in the structure ++ * <code>usb_gadget_ops</code>. ++ * ++ */ ++#include <linux/platform_device.h> ++ ++#include "fh_otg_os_dep.h" ++#include "fh_otg_pcd_if.h" ++#include "fh_otg_pcd.h" ++#include "fh_otg_driver.h" ++#include "fh_otg_dbg.h" ++ ++static struct gadget_wrapper { ++ fh_otg_pcd_t *pcd; ++ ++ struct usb_gadget gadget; ++ struct usb_gadget_driver *driver; ++ ++ struct usb_ep ep0; ++ struct usb_ep in_ep[16]; ++ struct usb_ep out_ep[16]; ++ ++} *gadget_wrapper; ++ ++/* Display the contents of the buffer */ ++extern void dump_msg(const u8 * buf, unsigned int length); ++/** ++ * Get the fh_otg_pcd_ep_t* from usb_ep* pointer - NULL in case ++ * if the endpoint is not found ++ */ ++static struct fh_otg_pcd_ep *ep_from_handle(fh_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/* USB Endpoint Operations */ ++/* ++ * The following sections briefly describe the behavior of the Gadget ++ * API endpoint operations implemented in the FH_otg driver ++ * software. Detailed descriptions of the generic behavior of each of ++ * these functions can be found in the Linux header file ++ * include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper ++ * function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper ++ * functions. Within each section, the corresponding FH_otg PCD ++ * function name is specified. ++ * ++ */ ++ ++/** ++ * This function is called by the Gadget Driver for each EP to be ++ * configured for the current configuration (SET_CONFIGURATION). ++ * ++ * This function initializes the fh_otg_ep_t data structure, and then ++ * calls fh_otg_ep_activate. ++ */ ++static int ep_enable(struct usb_ep *usb_ep, ++ const struct usb_endpoint_descriptor *ep_desc) ++{ ++ int retval; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); ++ ++ if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { ++ FH_WARN("%s, bad ep or descriptor\n", __func__); ++ return -EINVAL; ++ } ++ if (usb_ep == &gadget_wrapper->ep0) { ++ FH_WARN("%s, bad ep(0)\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check FIFO size? */ ++ if (!ep_desc->wMaxPacketSize) { ++ FH_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); ++ return -ERANGE; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ FH_WARN("%s, bogus device state\n", __func__); ++ return -ESHUTDOWN; ++ } ++ ++ /* Delete after check - MAS */ ++#if 0 ++ nat = (uint32_t) ep_desc->wMaxPacketSize; ++ printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat); ++ nat = (nat >> 11) & 0x03; ++ printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat); ++#endif ++ retval = fh_otg_pcd_ep_enable(gadget_wrapper->pcd, ++ (const uint8_t *)ep_desc, ++ (void *)usb_ep); ++ if (retval) { ++ FH_WARN("fh_otg_pcd_ep_enable failed\n"); ++ return -EINVAL; ++ } ++ ++ usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); ++ ++ return 0; ++} ++ ++/** ++ * This function is called when an EP is disabled due to disconnect or ++ * change in configuration. Any pending requests will terminate with a ++ * status of -ESHUTDOWN. ++ * ++ * This function modifies the fh_otg_ep_t data structure for this EP, ++ * and then calls fh_otg_ep_deactivate. ++ */ ++static int ep_disable(struct usb_ep *usb_ep) ++{ ++ int retval; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep); ++ if (!usb_ep) { ++ FH_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, ++ usb_ep ? usb_ep->name : NULL); ++ return -EINVAL; ++ } ++ ++ retval = fh_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function allocates a request object to use with the specified ++ * endpoint. ++ * ++ * @param ep The endpoint to be used with with the request ++ * @param gfp_flags the GFP_* flags to use. ++ */ ++static struct usb_request *fh_otg_pcd_alloc_request(struct usb_ep *ep, ++ gfp_t gfp_flags) ++{ ++ struct usb_request *usb_req; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags); ++ if (0 == ep) { ++ FH_WARN("%s() %s\n", __func__, "Invalid EP!\n"); ++ return 0; ++ } ++ usb_req = kmalloc(sizeof(*usb_req), gfp_flags); ++ if (0 == usb_req) { ++ FH_WARN("%s() %s\n", __func__, "request allocation failed!\n"); ++ return 0; ++ } ++ memset(usb_req, 0, sizeof(*usb_req)); ++ usb_req->dma = FH_DMA_ADDR_INVALID; ++ ++ return usb_req; ++} ++ ++/** ++ * This function frees a request object. ++ * ++ * @param ep The endpoint associated with the request ++ * @param req The request being freed ++ */ ++static void fh_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) ++{ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req); ++ ++ if (0 == ep || 0 == req) { ++ FH_WARN("%s() %s\n", __func__, ++ "Invalid ep or req argument!\n"); ++ return; ++ } ++ ++ kfree(req); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++/** ++ * This function allocates an I/O buffer to be used for a transfer ++ * to/from the specified endpoint. ++ * ++ * @param usb_ep The endpoint to be used with with the request ++ * @param bytes The desired number of bytes for the buffer ++ * @param dma Pointer to the buffer's DMA address; must be valid ++ * @param gfp_flags the GFP_* flags to use. ++ * @return address of a new buffer or null is buffer could not be allocated. ++ */ ++static void *fh_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, ++ dma_addr_t * dma, gfp_t gfp_flags) ++{ ++ void *buf; ++ fh_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, ++ dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if ((bytes & 0x3UL) != 0) { ++ FH_WARN("%s() Buffer size is not a multiple of" ++ "DWORD size (%d)", __func__, bytes); ++ } ++ ++ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if (((int)buf & 0x3UL) != 0) { ++ FH_WARN("%s() Buffer is not DWORD aligned (%p)", ++ __func__, buf); ++ } ++ ++ return buf; ++} ++ ++/** ++ * This function frees an I/O buffer that was allocated by alloc_buffer. ++ * ++ * @param usb_ep the endpoint associated with the buffer ++ * @param buf address of the buffer ++ * @param dma The buffer's DMA address ++ * @param bytes The number of bytes of the buffer ++ */ ++static void fh_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, ++ dma_addr_t dma, unsigned bytes) ++{ ++ fh_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes); ++ ++ dma_free_coherent(NULL, bytes, buf, dma); ++} ++#endif ++ ++/** ++ * This function is used to submit an I/O Request to an EP. ++ * ++ * - When the request completes the request's completion callback ++ * is called to return the request to the driver. ++ * - An EP, except control EPs, may have multiple requests ++ * pending. ++ * - Once submitted the request cannot be examined or modified. ++ * - Each request is turned into one or more packets. ++ * - A BULK EP can queue any amount of data; the transfer is ++ * packetized. ++ * - Zero length Packets are specified with the request 'zero' ++ * flag. ++ */ ++static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, ++ gfp_t gfp_flags) ++{ ++ fh_otg_pcd_t *pcd; ++ struct fh_otg_pcd_ep *ep; ++ int retval, is_isoc_ep, is_in_ep; ++ dma_addr_t dma_addr; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", ++ __func__, usb_ep, usb_req, gfp_flags); ++ ++ if (!usb_req || !usb_req->complete || !usb_req->buf) { ++ FH_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ FH_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ FH_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ FH_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", ++ usb_ep->name, usb_req, usb_req->length, usb_req->buf); ++ ++ usb_req->status = -EINPROGRESS; ++ usb_req->actual = 0; ++ ++ ep = ep_from_handle(pcd, usb_ep); ++ if (ep == NULL) { ++ is_isoc_ep = 0; ++ is_in_ep = 0; ++ } else { ++ is_isoc_ep = (ep->fh_ep.type == FH_OTG_EP_TYPE_ISOC) ? 1 : 0; ++ is_in_ep = ep->fh_ep.is_in; ++ } ++ ++ dma_addr = usb_req->dma; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ struct platform_device *dev = ++ gadget_wrapper->pcd->otg_dev->os_dep.pdev; ++ if (dma_addr == FH_DMA_ADDR_INVALID) { ++ if (usb_req->length != 0) { ++ dma_addr = dma_map_single(&dev->dev, ++ usb_req->buf, ++ usb_req->length, ++ is_in_ep ? ++ DMA_TO_DEVICE : DMA_FROM_DEVICE); ++ usb_req->dma = dma_addr; ++ } else { ++ dma_addr = 0; ++ } ++ } ++ } ++#endif ++ ++#ifdef FH_UTE_PER_IO ++ if (is_isoc_ep == 1) { ++ retval = ++ fh_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, ++ dma_addr, usb_req->length, ++ usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0, ++ &usb_req->ext_req); ++ if (retval) ++ return -EINVAL; ++ ++ return 0; ++ } ++#endif ++ retval = fh_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0); ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function cancels an I/O request from an EP. ++ */ ++static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++ ++ if (!usb_ep || !usb_req) { ++ FH_WARN("bad argument\n"); ++ return -EINVAL; ++ } ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ FH_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ if (fh_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * usb_ep_set_halt stalls an endpoint. ++ * ++ * usb_ep_clear_halt clears an endpoint halt and resets its data ++ * toggle. ++ * ++ * Both of these functions are implemented with the same underlying ++ * function. The behavior depends on the value argument. ++ * ++ * @param[in] usb_ep the Endpoint to halt or clear halt. ++ * @param[in] value ++ * - 0 means clear_halt. ++ * - 1 means set_halt, ++ * - 2 means clear stall lock flag. ++ * - 3 means set stall lock flag. ++ */ ++static int ep_halt(struct usb_ep *usb_ep, int value) ++{ ++ int retval = 0; ++ ++ FH_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value); ++ ++ if (!usb_ep) { ++ FH_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ retval = fh_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value); ++ if (retval == -FH_E_AGAIN) { ++ return -EAGAIN; ++ } else if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++static int ep_wedge(struct usb_ep *usb_ep) ++{ ++ FH_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name); ++ ++ return ep_halt(usb_ep, 3); ++} ++#endif ++ ++#ifdef FH_EN_ISOC ++/** ++ * This function is used to submit an ISOC Transfer Request to an EP. ++ * ++ * - Every time a sync period completes the request's completion callback ++ * is called to provide data to the gadget driver. ++ * - Once submitted the request cannot be modified. ++ * - Each request is turned into periodic data packets untill ISO ++ * Transfer is stopped.. ++ */ ++static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, ++ gfp_t gfp_flags) ++{ ++ int retval = 0; ++ ++ if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { ++ FH_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ FH_PRINTF("bad params\n"); ++ return -EINVAL; ++ } ++ ++ req->status = -EINPROGRESS; ++ ++ retval = ++ fh_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0, ++ req->buf1, req->dma0, req->dma1, ++ req->sync_frame, req->data_pattern_frame, ++ req->data_per_frame, ++ req-> ++ flags & USB_REQ_ISO_ASAP ? -1 : ++ req->start_frame, req->buf_proc_intrvl, ++ req, gfp_flags == GFP_ATOMIC ? 1 : 0); ++ ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function stops ISO EP Periodic Data Transfer. ++ */ ++static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) ++{ ++ int retval = 0; ++ if (!usb_ep) { ++ FH_WARN("bad ep\n"); ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ FH_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ FH_WARN("bogus device state\n"); ++ } ++ ++ fh_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep, ++ int packets, gfp_t gfp_flags) ++{ ++ struct usb_iso_request *pReq = NULL; ++ uint32_t req_size; ++ ++ req_size = sizeof(struct usb_iso_request); ++ req_size += ++ (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); ++ ++ pReq = kmalloc(req_size, gfp_flags); ++ if (!pReq) { ++ FH_WARN("Can't allocate Iso Request\n"); ++ return 0; ++ } ++ pReq->iso_packet_desc0 = (void *)(pReq + 1); ++ ++ pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; ++ ++ return pReq; ++} ++ ++static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) ++{ ++ kfree(req); ++} ++ ++static struct usb_isoc_ep_ops fh_otg_pcd_ep_ops = { ++ .ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = fh_otg_pcd_alloc_request, ++ .free_request = fh_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = fh_otg_pcd_alloc_buffer, ++ .free_buffer = fh_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ }, ++ ++ .iso_ep_start = iso_ep_start, ++ .iso_ep_stop = iso_ep_stop, ++ .alloc_iso_request = alloc_iso_request, ++ .free_iso_request = free_iso_request, ++}; ++ ++#else ++ ++static struct usb_ep_ops fh_otg_pcd_ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = fh_otg_pcd_alloc_request, ++ .free_request = fh_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = fh_otg_pcd_alloc_buffer, ++ .free_buffer = fh_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ ++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ .set_wedge = ep_wedge, ++ #endif ++ ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ ++}; ++ ++#endif /* _EN_ISOC_ */ ++/* Gadget Operations */ ++/** ++ * The following gadget operations will be implemented in the FH_otg ++ * PCD. Functions in the API that are not described below are not ++ * implemented. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_gadget_ops. The Gadget Driver calls the ++ * wrapper function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper functions ++ * (except for ioctl, which doesn't have a wrapper function). Within ++ * each section, the corresponding FH_otg PCD function name is ++ * specified. ++ * ++ */ ++ ++/** ++ *Gets the USB Frame number of the last SOF. ++ */ ++static int get_frame_number(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ return fh_otg_pcd_get_frame_number(d->pcd); ++} ++ ++#ifdef CONFIG_USB_FH_OTG_LPM ++static int test_lpm_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return fh_otg_pcd_is_lpm_enabled(d->pcd); ++} ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++static int test_besl_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return fh_otg_pcd_is_besl_enabled(d->pcd); ++} ++static int get_param_baseline_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return fh_otg_pcd_get_param_baseline_besl(d->pcd); ++} ++static int get_param_deep_besl(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return fh_otg_pcd_get_param_deep_besl(d->pcd); ++} ++#endif ++#endif ++ ++/** ++ * Initiates Session Request Protocol (SRP) to wakeup the host if no ++ * session is in progress. If a session is already in progress, but ++ * the device is suspended, remote wakeup signaling is started. ++ * ++ */ ++static int wakeup(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ fh_otg_pcd_wakeup(d->pcd); ++ return 0; ++} ++ ++static int d_pullup(struct usb_gadget *gadget, int is_on) ++{ ++ struct gadget_wrapper *d; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ if (gadget == 0) ++ return -ENODEV; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ if (is_on) ++ fh_otg_pcd_disconnect_soft(d->pcd, 0); ++ else ++ fh_otg_pcd_disconnect_soft(d->pcd, 1); ++ ++ return 0; ++} ++ ++static const struct usb_gadget_ops fh_otg_pcd_ops = { ++ .get_frame = get_frame_number, ++ .wakeup = wakeup, ++ .pullup = d_pullup, ++#ifdef CONFIG_USB_FH_OTG_LPM ++ .lpm_support = test_lpm_enabled, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ .besl_support = test_besl_enabled, ++ .get_baseline_besl = get_param_baseline_besl, ++ .get_deep_besl = get_param_deep_besl, ++#endif ++#endif ++ // current versions must always be self-powered ++}; ++ ++static int _setup(fh_otg_pcd_t * pcd, uint8_t * bytes) ++{ ++ int retval = -FH_E_NOT_SUPPORTED; ++ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { ++ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, ++ (struct usb_ctrlrequest ++ *)bytes); ++ } ++ ++ if (retval == -ENOTSUPP) { ++ retval = -FH_E_NOT_SUPPORTED; ++ } else if (retval < 0) { ++ retval = -FH_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++#ifdef FH_EN_ISOC ++static int _isoc_complete(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num) ++{ ++ int i, packet_count; ++ struct usb_gadget_iso_packet_descriptor *iso_packet = 0; ++ struct usb_iso_request *iso_req = req_handle; ++ ++ if (proc_buf_num) { ++ iso_packet = iso_req->iso_packet_desc1; ++ } else { ++ iso_packet = iso_req->iso_packet_desc0; ++ } ++ packet_count = ++ fh_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle); ++ for (i = 0; i < packet_count; ++i) { ++ int status; ++ int actual; ++ int offset; ++ fh_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle, ++ i, &status, &actual, &offset); ++ switch (status) { ++ case -FH_E_NO_DATA: ++ status = -ENODATA; ++ break; ++ default: ++ if (status) { ++ FH_PRINTF("unknown status in isoc packet\n"); ++ } ++ ++ } ++ iso_packet[i].status = status; ++ iso_packet[i].offset = offset; ++ iso_packet[i].actual_length = actual; ++ } ++ ++ iso_req->status = 0; ++ iso_req->process_buffer(ep_handle, iso_req); ++ ++ return 0; ++} ++#endif /* FH_EN_ISOC */ ++ ++#ifdef FH_UTE_PER_IO ++/** ++ * Copy the contents of the extended request to the Linux usb_request's ++ * extended part and call the gadget's completion. ++ * ++ * @param pcd Pointer to the pcd structure ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param req_handle Void pointer to the usb_request structure ++ * @param status Request status returned from the portable logic ++ * @param ereq_port Void pointer to the extended request structure ++ * created in the the portable part that contains the ++ * results of the processed iso packets. ++ */ ++static int _xisoc_complete(fh_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, void *ereq_port) ++{ ++ struct fh_ute_iso_req_ext *ereqorg = NULL; ++ struct fh_iso_xreq_port *ereqport = NULL; ++ struct fh_ute_iso_packet_descriptor *desc_org = NULL; ++ int i; ++ struct usb_request *req; ++ //struct fh_ute_iso_packet_descriptor * ++ //int status = 0; ++ ++ req = (struct usb_request *)req_handle; ++ ereqorg = &req->ext_req; ++ ereqport = (struct fh_iso_xreq_port *)ereq_port; ++ desc_org = ereqorg->per_io_frame_descs; ++ ++ if (req && req->complete) { ++ /* Copy the request data from the portable logic to our request */ ++ for (i = 0; i < ereqport->pio_pkt_count; i++) { ++ desc_org[i].actual_length = ++ ereqport->per_io_frame_descs[i].actual_length; ++ desc_org[i].status = ++ ereqport->per_io_frame_descs[i].status; ++ } ++ ++ switch (status) { ++ case -FH_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -FH_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -FH_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -FH_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ } ++ ++ /* And call the gadget's completion */ ++ req->complete(ep_handle, req); ++ } ++ ++ return 0; ++} ++#endif /* FH_UTE_PER_IO */ ++ ++static int _complete(fh_otg_pcd_t *pcd, void *ep_handle, ++ void *req_handle, int32_t status, uint32_t actual) ++{ ++ struct usb_request *req = (struct usb_request *)req_handle; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ if (GET_CORE_IF(pcd)->dma_enable && req->length != 0) { ++ struct platform_device *dev = ++ gadget_wrapper->pcd->otg_dev->os_dep.pdev; ++ struct fh_otg_pcd_ep *ep = ep_from_handle(pcd, ep_handle); ++ int is_in_ep = 0; ++ ++ if (ep) ++ is_in_ep = ep->fh_ep.is_in; ++ ++ if (FH_DMA_ADDR_INVALID != req->dma) { ++ dma_unmap_single(&dev->dev, ++ req->dma, ++ req->length, ++ is_in_ep ? ++ PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); ++ req->dma = FH_DMA_ADDR_INVALID; ++ } ++ }; ++#endif ++ ++ if (req && req->complete) { ++ switch (status) { ++ case -FH_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -FH_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -FH_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -FH_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ ++ } ++ ++ req->actual = actual; ++ FH_SPINUNLOCK(pcd->lock); ++ req->complete(ep_handle, req); ++ FH_SPINLOCK(pcd->lock); ++ } ++ ++ return 0; ++} ++ ++static int _connect(fh_otg_pcd_t * pcd, int speed) ++{ ++ gadget_wrapper->gadget.speed = speed; ++ return 0; ++} ++ ++static int _disconnect(fh_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { ++ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++static int _resume(fh_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { ++ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); ++ } ++ ++ return 0; ++} ++ ++static int _suspend(fh_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { ++ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++/** ++ * This function updates the otg values in the gadget structure. ++ */ ++static int _hnp_changed(fh_otg_pcd_t * pcd) ++{ ++ ++ if (!gadget_wrapper->gadget.is_otg) ++ return 0; ++ ++ gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd); ++ gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd); ++ gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd); ++ return 0; ++} ++ ++static int _reset(fh_otg_pcd_t * pcd) ++{ ++ return 0; ++} ++ ++#ifdef FH_UTE_CFI ++static int _cfi_setup(fh_otg_pcd_t * pcd, void *cfi_req) ++{ ++ int retval = -FH_E_INVALID; ++ if (gadget_wrapper->driver->cfi_feature_setup) { ++ retval = ++ gadget_wrapper->driver-> ++ cfi_feature_setup(&gadget_wrapper->gadget, ++ (struct cfi_usb_ctrlrequest *)cfi_req); ++ } ++ ++ return retval; ++} ++#endif ++ ++static const struct fh_otg_pcd_function_ops fops = { ++ .complete = _complete, ++#ifdef FH_EN_ISOC ++ .isoc_complete = _isoc_complete, ++#endif ++ .setup = _setup, ++ .disconnect = _disconnect, ++ .connect = _connect, ++ .resume = _resume, ++ .suspend = _suspend, ++ .hnp_changed = _hnp_changed, ++ .reset = _reset, ++#ifdef FH_UTE_CFI ++ .cfi_setup = _cfi_setup, ++#endif ++#ifdef FH_UTE_PER_IO ++ .xisoc_complete = _xisoc_complete, ++#endif ++}; ++ ++/** ++ * This function is the top level PCD interrupt handler. ++ */ ++static irqreturn_t fh_otg_pcd_irq(int irq, void *dev) ++{ ++ fh_otg_pcd_t *pcd = dev; ++ int32_t retval = IRQ_NONE; ++ ++ retval = fh_otg_pcd_handle_intr(pcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function initialized the usb_ep structures to there default ++ * state. ++ * ++ * @param d Pointer on gadget_wrapper. ++ */ ++void gadget_add_eps(struct gadget_wrapper *d) ++{ ++ static const char *names[] = { ++ ++ "ep0", ++ "ep1in", ++ "ep2out", ++ "ep3in", ++ "ep4out", ++ "ep5in", ++ "ep6out", ++ "ep7in", ++ "ep8out", ++ "ep9in", ++ "ep10out", ++ "ep11in", ++ "ep12out", ++ }; ++ ++ int i; ++ struct usb_ep *ep; ++ int8_t dev_endpoints; ++ ++ FH_DEBUGPL(DBG_PCDV, "%s\n", __func__); ++ ++ INIT_LIST_HEAD(&d->gadget.ep_list); ++ d->gadget.ep0 = &d->ep0; ++ d->gadget.speed = USB_SPEED_UNKNOWN; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ d->gadget.max_speed = USB_SPEED_HIGH; ++#endif ++ ++ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &d->ep0; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[0]; ++ ep->ops = (struct usb_ep_ops *)&fh_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++#endif ++ ++ fh_otg_pcd_ep_enable(d->pcd, NULL, ep); ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ ++ /** ++ * Initialize the EP structures. ++ */ ++ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->in_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[d->pcd->in_ep[i].fh_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&fh_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++#endif ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->out_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[d->pcd->out_ep[i].fh_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&fh_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) ++ ep->maxpacket_limit = MAX_PACKET_SIZE; ++#endif ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ ++ /* remove ep0 from the list. There is a ep0 pointer. */ ++ list_del_init(&d->ep0.ep_list); ++ ++ d->ep0.maxpacket = MAX_EP0_SIZE; ++} ++ ++/** ++ * This function releases the Gadget device. ++ * required by device_unregister(). ++ * ++ * @todo Should this do something? Should it free the PCD? ++ */ ++static void fh_otg_pcd_gadget_release(struct device *dev) ++{ ++ FH_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); ++} ++ ++static struct gadget_wrapper *alloc_wrapper(struct platform_device *_dev) ++{ ++ static char pcd_name[] = "fh_otg"; ++ fh_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++ ++ struct gadget_wrapper *d; ++ int retval; ++ ++ d = FH_ALLOC(sizeof(*d)); ++ if (d == NULL) { ++ return NULL; ++ } ++ ++ memset(d, 0, sizeof(*d)); ++ ++ d->gadget.name = pcd_name; ++ d->pcd = otg_dev->pcd; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ strcpy(d->gadget.dev.bus_id, "gadget"); ++#else ++ dev_set_name(&d->gadget.dev, "%s", "gadget"); ++#endif ++ ++ d->gadget.dev.parent = &_dev->dev; ++ d->gadget.dev.release = fh_otg_pcd_gadget_release; ++ d->gadget.ops = &fh_otg_pcd_ops; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ d->gadget.is_dualspeed = fh_otg_pcd_is_dualspeed(otg_dev->pcd); ++#endif ++ d->gadget.is_otg = fh_otg_pcd_is_otg(otg_dev->pcd); ++ ++ d->driver = 0; ++ /* Register the gadget device */ ++ retval = device_register(&d->gadget.dev); ++ if (retval != 0) { ++ FH_ERROR("device_register failed\n"); ++ FH_FREE(d); ++ return NULL; ++ } ++ ++ return d; ++} ++ ++static void free_wrapper(struct gadget_wrapper *d) ++{ ++ if (d->driver) { ++ /* should have been done already by driver model core */ ++ FH_WARN("driver '%s' is still registered\n", ++ d->driver->driver.name); ++ usb_gadget_unregister_driver(d->driver); ++ } ++ ++ device_unregister(&d->gadget.dev); ++ FH_FREE(d); ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++int pcd_init(struct platform_device *dev, int irq) ++{ ++ fh_otg_device_t *otg_dev = platform_get_drvdata(dev); ++ ++ int retval = 0; ++ ++ printk(KERN_ERR "%s(%p)\n", __func__, dev); ++ ++ otg_dev->pcd = fh_otg_pcd_init(otg_dev->core_if); ++ ++ if (!otg_dev->pcd) { ++ FH_ERROR("fh_otg_pcd_init failed\n"); ++ return -ENOMEM; ++ } ++ ++ otg_dev->pcd->otg_dev = otg_dev; ++ gadget_wrapper = alloc_wrapper(dev); ++ ++ /* ++ * Initialize EP structures ++ */ ++ gadget_add_eps(gadget_wrapper); ++ /* ++ * Setup interupt handler ++ */ ++ ++ retval = request_irq(irq, fh_otg_pcd_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ gadget_wrapper->gadget.name, otg_dev->pcd); ++ if (retval != 0) { ++ FH_ERROR("request of irq%d failed\n", irq); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++ ++ fh_otg_pcd_start(gadget_wrapper->pcd, &fops); ++ platform_set_drvdata(dev, otg_dev); ++ ++ return retval; ++} ++ ++/** ++ * Cleanup the PCD. ++ */ ++void pcd_remove(struct platform_device *dev, int irq) ++{ ++ ++ fh_otg_device_t *otg_dev = platform_get_drvdata(dev); ++ fh_otg_pcd_t *pcd = otg_dev->pcd; ++ ++ printk(KERN_ERR "%s(%p)(%p)\n", __func__, dev, otg_dev); ++ ++ /* ++ * Free the IRQ ++ */ ++ printk(KERN_ERR "pcd free irq :%d\n", irq); ++ free_irq(irq, pcd); ++ free_wrapper(gadget_wrapper); ++ fh_otg_pcd_remove(otg_dev->pcd); ++ otg_dev->pcd = 0; ++} ++ ++/** ++ * This function registers a gadget driver with the PCD. ++ * ++ * When a driver is successfully registered, it will receive control ++ * requests including set_configuration(), which enables non-control ++ * requests. then usb traffic follows until a disconnect is reported. ++ * then a host may connect again, or the driver might get unbound. ++ * ++ * @param driver The driver being registered ++ * @param bind The bind function of gadget driver ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++int usb_gadget_register_driver(struct usb_gadget_driver *driver) ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) ++#else ++int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ++ int (*bind)(struct usb_gadget *)) ++#endif ++{ ++ int retval; ++ ++ FH_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!driver || ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) ++ driver->speed == USB_SPEED_UNKNOWN || ++#else ++ driver->max_speed == USB_SPEED_UNKNOWN || ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ !driver->bind || ++#else ++ !bind || ++#endif ++ !driver->unbind || !driver->disconnect || !driver->setup) { ++ FH_DEBUGPL(DBG_PCDV, "EINVAL\n"); ++ return -EINVAL; ++ } ++ if (gadget_wrapper == 0) { ++ FH_DEBUGPL(DBG_PCDV, "ENODEV\n"); ++ return -ENODEV; ++ } ++ if (gadget_wrapper->driver != 0) { ++ FH_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); ++ return -EBUSY; ++ } ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ ++ FH_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++ retval = driver->bind(&gadget_wrapper->gadget); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ retval = driver->bind(&gadget_wrapper->gadget,gadget_wrapper->driver); ++#else ++ retval = bind(&gadget_wrapper->gadget); ++#endif ++ if (retval) { ++ FH_ERROR("bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = 0; ++ gadget_wrapper->gadget.dev.driver = 0; ++ return retval; ++ } ++ FH_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) ++EXPORT_SYMBOL(usb_gadget_register_driver); ++#else ++EXPORT_SYMBOL(usb_gadget_probe_driver); ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,1) ++ ++int usb_udc_attach_driver(const char *name, struct usb_gadget_driver *driver) ++ { ++ int retval; ++ if(strcmp(name, "fh_otg")){ ++ FH_ERROR("NO FH DEV FOUND \n"); ++ return -ENODEV; ++ } ++ ++ FH_DEBUGPL(DBG_PCD, "Registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!driver || driver->max_speed == USB_SPEED_UNKNOWN || !driver->bind || ++ !driver->unbind || !driver->disconnect || !driver->setup) { ++ FH_DEBUGPL(DBG_PCDV, "EINVAL\n"); ++ return -EINVAL; ++ } ++ if (gadget_wrapper == 0) { ++ FH_DEBUGPL(DBG_PCDV, "ENODEV\n"); ++ return -ENODEV; ++ } ++ if (gadget_wrapper->driver != 0) { ++ FH_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); ++ return -EBUSY; ++ } ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ ++ FH_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); ++ retval = driver->bind(&gadget_wrapper->gadget,gadget_wrapper->driver); ++ if (retval) { ++ FH_ERROR("bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = 0; ++ gadget_wrapper->gadget.dev.driver = 0; ++ return retval; ++ } ++ FH_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++EXPORT_SYMBOL(usb_udc_attach_driver); ++ ++void usb_gadget_set_state(struct usb_gadget *gadget, ++ enum usb_device_state state) ++{ ++ gadget->state = state; ++ FH_SCHEDULE_SYSTEM_WORK(&gadget->work); ++} ++EXPORT_SYMBOL_GPL(usb_gadget_set_state); ++ ++#endif ++ ++ ++ ++/** ++ * This function unregisters a gadget driver ++ * ++ * @param driver The driver being unregistered ++ */ ++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ++{ ++ //FH_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); ++ ++ if (gadget_wrapper == 0) { ++ FH_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, ++ -ENODEV); ++ return -ENODEV; ++ } ++ if (driver == 0 || driver != gadget_wrapper->driver) { ++ FH_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, ++ -EINVAL); ++ return -EINVAL; ++ } ++ ++ driver->unbind(&gadget_wrapper->gadget); ++ gadget_wrapper->driver = 0; ++ ++ FH_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name); ++ return 0; ++} ++ ++EXPORT_SYMBOL(usb_gadget_unregister_driver); ++ ++#endif /* FH_HOST_ONLY */ +diff --git a/drivers/usb/host/fh_otg/fh_otg/fh_otg_regs.h b/drivers/usb/host/fh_otg/fh_otg/fh_otg_regs.h +new file mode 100644 +index 00000000..e1070282 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/fh_otg_regs.h +@@ -0,0 +1,2558 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/fh_otg_regs.h $ ++ * $Revision: #105 $ ++ * $Date: 2015/10/12 $ ++ * $Change: 2972621 $ ++ * ++ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, ++ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless ++ * otherwise expressly agreed to in writing between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product under ++ * any End User Software License Agreement or Agreement for Licensed Product ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __FH_OTG_REGS_H__ ++#define __FH_OTG_REGS_H__ ++ ++#include "fh_otg_core_if.h" ++ ++/** ++ * @file ++ * ++ * This file contains the data structures for accessing the FH_otg core registers. ++ * ++ * The application interfaces with the HS OTG core by reading from and ++ * writing to the Control and Status Register (CSR) space through the ++ * AHB Slave interface. These registers are 32 bits wide, and the ++ * addresses are 32-bit-block aligned. ++ * CSRs are classified as follows: ++ * - Core Global Registers ++ * - Device Mode Registers ++ * - Device Global Registers ++ * - Device Endpoint Specific Registers ++ * - Host Mode Registers ++ * - Host Global Registers ++ * - Host Port CSRs ++ * - Host Channel Specific Registers ++ * ++ * Only the Core Global registers can be accessed in both Device and ++ * Host modes. When the HS OTG core is operating in one mode, either ++ * Device or Host, the application must not access registers from the ++ * other mode. When the core switches from one mode to another, the ++ * registers in the new mode of operation must be reprogrammed as they ++ * would be after a power-on reset. ++ */ ++ ++/****************************************************************************/ ++/** FH_otg Core registers . ++ * The fh_otg_core_global_regs structure defines the size ++ * and relative field offsets for the Core Global registers. ++ */ ++typedef struct fh_otg_core_global_regs { ++ /** OTG Control and Status Register. <i>Offset: 000h</i> */ ++ volatile uint32_t gotgctl; ++ /** OTG Interrupt Register. <i>Offset: 004h</i> */ ++ volatile uint32_t gotgint; ++ /**Core AHB Configuration Register. <i>Offset: 008h</i> */ ++ volatile uint32_t gahbcfg; ++ ++#define FH_GLBINTRMASK 0x0001 ++#define FH_DMAENABLE 0x0020 ++#define FH_NPTXEMPTYLVL_EMPTY 0x0080 ++#define FH_NPTXEMPTYLVL_HALFEMPTY 0x0000 ++#define FH_PTXEMPTYLVL_EMPTY 0x0100 ++#define FH_PTXEMPTYLVL_HALFEMPTY 0x0000 ++ ++ /**Core USB Configuration Register. <i>Offset: 00Ch</i> */ ++ volatile uint32_t gusbcfg; ++ /**Core Reset Register. <i>Offset: 010h</i> */ ++ volatile uint32_t grstctl; ++ /**Core Interrupt Register. <i>Offset: 014h</i> */ ++ volatile uint32_t gintsts; ++ /**Core Interrupt Mask Register. <i>Offset: 018h</i> */ ++ volatile uint32_t gintmsk; ++ /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */ ++ volatile uint32_t grxstsr; ++ /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/ ++ volatile uint32_t grxstsp; ++ /**Receive FIFO Size Register. <i>Offset: 024h</i> */ ++ volatile uint32_t grxfsiz; ++ /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */ ++ volatile uint32_t gnptxfsiz; ++ /**Non Periodic Transmit FIFO/Queue Status Register (Read ++ * Only). <i>Offset: 02Ch</i> */ ++ volatile uint32_t gnptxsts; ++ /**I2C Access Register. <i>Offset: 030h</i> */ ++ volatile uint32_t gi2cctl; ++ /**PHY Vendor Control Register. <i>Offset: 034h</i> */ ++ volatile uint32_t gpvndctl; ++ /**General Purpose Input/Output Register. <i>Offset: 038h</i> */ ++ volatile uint32_t ggpio; ++ /**User ID Register. <i>Offset: 03Ch</i> */ ++ volatile uint32_t guid; ++ /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */ ++ volatile uint32_t gsnpsid; ++ /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */ ++ volatile uint32_t ghwcfg1; ++ /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */ ++ volatile uint32_t ghwcfg2; ++#define FH_SLAVE_ONLY_ARCH 0 ++#define FH_EXT_DMA_ARCH 1 ++#define FH_INT_DMA_ARCH 2 ++ ++#define FH_MODE_HNP_SRP_CAPABLE 0 ++#define FH_MODE_SRP_ONLY_CAPABLE 1 ++#define FH_MODE_NO_HNP_SRP_CAPABLE 2 ++#define FH_MODE_SRP_CAPABLE_DEVICE 3 ++#define FH_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define FH_MODE_SRP_CAPABLE_HOST 5 ++#define FH_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */ ++ volatile uint32_t ghwcfg3; ++ /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/ ++ volatile uint32_t ghwcfg4; ++ /** Core LPM Configuration register <i>Offset: 054h</i>*/ ++ volatile uint32_t glpmcfg; ++ /** Global PowerDn Register <i>Offset: 058h</i> */ ++ volatile uint32_t gpwrdn; ++ /** Global DFIFO SW Config Register <i>Offset: 05Ch</i> */ ++ volatile uint32_t gdfifocfg; ++ /** ADP Control Register <i>Offset: 060h</i> */ ++ volatile uint32_t adpctl; ++ /** Reserved <i>Offset: 064h-0FFh</i> */ ++ volatile uint32_t reserved39[39]; ++ /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */ ++ volatile uint32_t hptxfsiz; ++ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, ++ otherwise Device Transmit FIFO#n Register. ++ * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */ ++ volatile uint32_t dtxfsiz[15]; ++ ++} fh_otg_core_global_regs_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Control ++ * and Status Register (GOTGCTL). Set the bits using the bit ++ * fields then write the <i>d32</i> value to the register. ++ */ ++typedef union gotgctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned sesreqscs:1; ++ unsigned sesreq:1; ++ unsigned vbvalidoven:1; ++ unsigned vbvalidovval:1; ++ unsigned avalidoven:1; ++ unsigned avalidovval:1; ++ unsigned bvalidoven:1; ++ unsigned bvalidovval:1; ++ unsigned hstnegscs:1; ++ unsigned hnpreq:1; ++ unsigned hstsethnpen:1; ++ unsigned devhnpen:1; ++ unsigned reserved12_15:4; ++ unsigned conidsts:1; ++ unsigned dbnctime:1; ++ unsigned asesvld:1; ++ unsigned bsesvld:1; ++ unsigned otgver:1; ++ unsigned reserved1:1; ++ unsigned multvalidbc:5; ++ unsigned chirpen:1; ++ unsigned reserved28_31:4; ++ } b; ++} gotgctl_data_t; ++ ++/** ++ * This union represents the bit fields of the Core OTG Interrupt Register ++ * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i> ++ * value to the register. ++ */ ++typedef union gotgint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Current Mode */ ++ unsigned reserved0_1:2; ++ ++ /** Session End Detected */ ++ unsigned sesenddet:1; ++ ++ unsigned reserved3_7:5; ++ ++ /** Session Request Success Status Change */ ++ unsigned sesreqsucstschng:1; ++ /** Host Negotiation Success Status Change */ ++ unsigned hstnegsucstschng:1; ++ ++ unsigned reserved10_16:7; ++ ++ /** Host Negotiation Detected */ ++ unsigned hstnegdet:1; ++ /** A-Device Timeout Change */ ++ unsigned adevtoutchng:1; ++ /** Debounce Done */ ++ unsigned debdone:1; ++ /** Multi-Valued input changed */ ++ unsigned mvic:1; ++ ++ unsigned reserved31_21:11; ++ ++ } b; ++} gotgint_data_t; ++ ++/** ++ * This union represents the bit fields of the Core AHB Configuration ++ * Register (GAHBCFG). Set/clear the bits using the bit fields then ++ * write the <i>d32</i> value to the register. ++ */ ++typedef union gahbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned glblintrmsk:1; ++#define FH_GAHBCFG_GLBINT_ENABLE 1 ++ ++ unsigned hburstlen:4; ++#define FH_GAHBCFG_INT_DMA_BURST_SINGLE 0 ++#define FH_GAHBCFG_INT_DMA_BURST_INCR 1 ++#define FH_GAHBCFG_INT_DMA_BURST_INCR4 3 ++#define FH_GAHBCFG_INT_DMA_BURST_INCR8 5 ++#define FH_GAHBCFG_INT_DMA_BURST_INCR16 7 ++ ++ unsigned dmaenable:1; ++#define FH_GAHBCFG_DMAENABLE 1 ++ unsigned reserved:1; ++ unsigned nptxfemplvl_txfemplvl:1; ++ unsigned ptxfemplvl:1; ++#define FH_GAHBCFG_TXFEMPTYLVL_EMPTY 1 ++#define FH_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 ++ unsigned reserved9_20:12; ++ unsigned remmemsupp:1; ++ unsigned notialldmawrit:1; ++ unsigned ahbsingle:1; ++ unsigned reserved24_31:8; ++ } b; ++} gahbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core USB Configuration ++ * Register (GUSBCFG). Set the bits using the bit fields then write ++ * the <i>d32</i> value to the register. ++ */ ++typedef union gusbcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned toutcal:3; ++ unsigned phyif:1; ++ unsigned ulpi_utmi_sel:1; ++ unsigned fsintf:1; ++ unsigned physel:1; ++ unsigned ddrsel:1; ++ unsigned srpcap:1; ++ unsigned hnpcap:1; ++ unsigned usbtrdtim:4; ++ unsigned reserved1:1; ++ unsigned phylpwrclksel:1; ++ unsigned otgutmifssel:1; ++ unsigned ulpi_fsls:1; ++ unsigned ulpi_auto_res:1; ++ unsigned ulpi_clk_sus_m:1; ++ unsigned ulpi_ext_vbus_drv:1; ++ unsigned ulpi_int_vbus_indicator:1; ++ unsigned term_sel_dl_pulse:1; ++ unsigned indicator_complement:1; ++ unsigned indicator_pass_through:1; ++ unsigned ulpi_int_prot_dis:1; ++ unsigned ic_usb_cap:1; ++ unsigned ic_traffic_pull_remove:1; ++ unsigned tx_end_delay:1; ++ unsigned force_host_mode:1; ++ unsigned force_dev_mode:1; ++ unsigned reserved31:1; ++ } b; ++} gusbcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core Reset Register ++ * (GRSTCTL). Set/clear the bits using the bit fields then write the ++ * <i>d32</i> value to the register. ++ */ ++typedef union grstctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Core Soft Reset (CSftRst) (Device and Host) ++ * ++ * The application can flush the control logic in the ++ * entire core using this bit. This bit resets the ++ * pipelines in the AHB Clock domain as well as the ++ * PHY Clock domain. ++ * ++ * The state machines are reset to an IDLE state, the ++ * control bits in the CSRs are cleared, all the ++ * transmit FIFOs and the receive FIFO are flushed. ++ * ++ * The status mask bits that control the generation of ++ * the interrupt, are cleared, to clear the ++ * interrupt. The interrupt status bits are not ++ * cleared, so the application can get the status of ++ * any events that occurred in the core after it has ++ * set this bit. ++ * ++ * Any transactions on the AHB are terminated as soon ++ * as possible following the protocol. Any ++ * transactions on the USB are terminated immediately. ++ * ++ * The configuration settings in the CSRs are ++ * unchanged, so the software doesn't have to ++ * reprogram these registers (Device ++ * Configuration/Host Configuration/Core System ++ * Configuration/Core PHY Configuration). ++ * ++ * The application can write to this bit, any time it ++ * wants to reset the core. This is a self clearing ++ * bit and the core clears this bit after all the ++ * necessary logic is reset in the core, which may ++ * take several clocks, depending on the current state ++ * of the core. ++ */ ++ unsigned csftrst:1; ++ /** Hclk Soft Reset ++ * ++ * The application uses this bit to reset the control logic in ++ * the AHB clock domain. Only AHB clock domain pipelines are ++ * reset. ++ */ ++ unsigned hsftrst:1; ++ /** Host Frame Counter Reset (Host Only)<br> ++ * ++ * The application can reset the (micro)frame number ++ * counter inside the core, using this bit. When the ++ * (micro)frame counter is reset, the subsequent SOF ++ * sent out by the core, will have a (micro)frame ++ * number of 0. ++ */ ++ unsigned hstfrm:1; ++ /** In Token Sequence Learning Queue Flush ++ * (INTknQFlsh) (Device Only) ++ */ ++ unsigned intknqflsh:1; ++ /** RxFIFO Flush (RxFFlsh) (Device and Host) ++ * ++ * The application can flush the entire Receive FIFO ++ * using this bit. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is reading from the RxFIFO nor the MAC ++ * is writing the data in to the FIFO. The ++ * application should wait until the bit is cleared ++ * before performing any other operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned rxfflsh:1; ++ /** TxFIFO Flush (TxFFlsh) (Device and Host). ++ * ++ * This bit is used to selectively flush a single or ++ * all transmit FIFOs. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. The application should write into ++ * this bit, only after making sure that neither the ++ * DMA engine is writing into the TxFIFO nor the MAC ++ * is reading the data out of the FIFO. The ++ * application should wait until the core clears this ++ * bit, before performing any operations. This bit ++ * will takes 8 clocks (slowest of PHY or AHB clock) ++ * to clear. ++ */ ++ unsigned txfflsh:1; ++ ++ /** TxFIFO Number (TxFNum) (Device and Host). ++ * ++ * This is the FIFO number which needs to be flushed, ++ * using the TxFIFO Flush bit. This field should not ++ * be changed until the TxFIFO Flush bit is cleared by ++ * the core. ++ * - 0x0 : Non Periodic TxFIFO Flush ++ * - 0x1 : Periodic TxFIFO #1 Flush in device mode ++ * or Periodic TxFIFO in host mode ++ * - 0x2 : Periodic TxFIFO #2 Flush in device mode. ++ * - ... ++ * - 0xF : Periodic TxFIFO #15 Flush in device mode ++ * - 0x10: Flush all the Transmit NonPeriodic and ++ * Transmit Periodic FIFOs in the core ++ */ ++ unsigned txfnum:5; ++ /** Reserved */ ++ unsigned reserved11_29:19; ++ /** DMA Request Signal. Indicated DMA request is in ++ * probress. Used for debug purpose. */ ++ unsigned dmareq:1; ++ /** AHB Master Idle. Indicates the AHB Master State ++ * Machine is in IDLE condition. */ ++ unsigned ahbidle:1; ++ } b; ++} grstctl_t; ++ ++/** ++ * This union represents the bit fields of the Core Interrupt Mask ++ * Register (GINTMSK). Set/clear the bits using the bit fields then ++ * write the <i>d32</i> value to the register. ++ */ ++typedef union gintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepintr:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintmsk_data_t; ++/** ++ * This union represents the bit fields of the Core Interrupt Register ++ * (GINTSTS). Set/clear the bits using the bit fields then write the ++ * <i>d32</i> value to the register. ++ */ ++typedef union gintsts_data { ++ /** raw register data */ ++ uint32_t d32; ++#define FH_SOF_INTR_MASK 0x0008 ++ /** register bits */ ++ struct { ++#define FH_HOST_MODE 1 ++ unsigned curmode:1; ++ unsigned modemismatch:1; ++ unsigned otgintr:1; ++ unsigned sofintr:1; ++ unsigned rxstsqlvl:1; ++ unsigned nptxfempty:1; ++ unsigned ginnakeff:1; ++ unsigned goutnakeff:1; ++ unsigned ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepint:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ unsigned portintr:1; ++ unsigned hcintr:1; ++ unsigned ptxfempty:1; ++ unsigned lpmtranrcvd:1; ++ unsigned conidstschng:1; ++ unsigned disconnect:1; ++ unsigned sessreqintr:1; ++ unsigned wkupintr:1; ++ } b; ++} gintsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i> ++ * element then read out the bits using the <i>b</i>it elements. ++ */ ++typedef union device_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned epnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++#define FH_STS_DATA_UPDT 0x2 // OUT Data Packet ++#define FH_STS_XFER_COMP 0x3 // OUT Data Transfer Complete ++ ++#define FH_DSTS_GOUT_NAK 0x1 // Global OUT NAK ++#define FH_DSTS_SETUP_COMP 0x4 // Setup Phase Complete ++#define FH_DSTS_SETUP_UPDT 0x6 // SETUP Packet ++ unsigned pktsts:4; ++ unsigned fn:4; ++ unsigned reserved25_31:7; ++ } b; ++} device_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i> ++ * element then read out the bits using the <i>b</i>it elements. ++ */ ++typedef union host_grxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned chnum:4; ++ unsigned bcnt:11; ++ unsigned dpid:2; ++ ++ unsigned pktsts:4; ++#define FH_GRXSTS_PKTSTS_IN 0x2 ++#define FH_GRXSTS_PKTSTS_IN_XFER_COMP 0x3 ++#define FH_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 ++#define FH_GRXSTS_PKTSTS_CH_HALTED 0x7 ++ ++ unsigned reserved21_31:11; ++ } b; ++} host_grxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, ++ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element ++ * then read out the bits using the <i>b</i>it elements. ++ */ ++typedef union fifosize_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned startaddr:16; ++ unsigned depth:16; ++ } b; ++} fifosize_data_t; ++ ++/** ++ * This union represents the bit fields in the Non-Periodic Transmit ++ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the ++ * <i>d32</i> element then read out the bits using the <i>b</i>it ++ * elements. ++ */ ++typedef union gnptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned nptxfspcavail:16; ++ unsigned nptxqspcavail:8; ++ /** Top of the Non-Periodic Transmit Request Queue ++ * - bit 24 - Terminate (Last entry for the selected ++ * channel/EP) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - IN/OUT ++ * - 2'b01 - Zero Length OUT ++ * - 2'b10 - PING/Complete Split ++ * - 2'b11 - Channel Halt ++ * - bits 30:27 - Channel/EP Number ++ */ ++ unsigned nptxqtop_terminate:1; ++ unsigned nptxqtop_token:2; ++ unsigned nptxqtop_chnep:4; ++ unsigned reserved:1; ++ } b; ++} gnptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Transmit ++ * FIFO Status Register (DTXFSTS). Read the register into the ++ * <i>d32</i> element then read out the bits using the <i>b</i>it ++ * elements. ++ */ ++typedef union dtxfsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned txfspcavail:16; ++ unsigned reserved:16; ++ } b; ++} dtxfsts_data_t; ++ ++/** ++ * This union represents the bit fields in the I2C Control Register ++ * (I2CCTL). Read the register into the <i>d32</i> element then read out the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union gi2cctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:8; ++ unsigned regaddr:8; ++ unsigned addr:7; ++ unsigned i2cen:1; ++ unsigned ack:1; ++ unsigned i2csuspctl:1; ++ unsigned i2cdevaddr:2; ++ unsigned i2cdatse0:1; ++ unsigned reserved:1; ++ unsigned rw:1; ++ unsigned bsydne:1; ++ } b; ++} gi2cctl_data_t; ++ ++/** ++ * This union represents the bit fields in the PHY Vendor Control Register ++ * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union gpvndctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned regdata:8; ++ unsigned vctrl:8; ++ unsigned regaddr16_21:6; ++ unsigned regwr:1; ++ unsigned reserved23_24:2; ++ unsigned newregreq:1; ++ unsigned vstsbsy:1; ++ unsigned vstsdone:1; ++ unsigned reserved28_30:3; ++ unsigned disulpidrvr:1; ++ } b; ++} gpvndctl_data_t; ++ ++/** ++ * This union represents the bit fields in the General Purpose ++ * Input/Output Register (GGPIO). ++ * Read the register into the <i>d32</i> element then read out the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union ggpio_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned gpi:16; ++ unsigned gpo:16; ++ } b; ++} ggpio_data_t; ++ ++/** ++ * This union represents the bit fields in the User ID Register ++ * (GUID). Read the register into the <i>d32</i> element then read out the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union guid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} guid_data_t; ++ ++/** ++ * This union represents the bit fields in the Synopsys ID Register ++ * (GSNPSID). Read the register into the <i>d32</i> element then read out the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union gsnpsid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} gsnpsid_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config1 ++ * Register. Read the register into the <i>d32</i> element then read ++ * out the bits using the <i>b</i>it elements. ++ */ ++typedef union hwcfg1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ep_dir0:2; ++ unsigned ep_dir1:2; ++ unsigned ep_dir2:2; ++ unsigned ep_dir3:2; ++ unsigned ep_dir4:2; ++ unsigned ep_dir5:2; ++ unsigned ep_dir6:2; ++ unsigned ep_dir7:2; ++ unsigned ep_dir8:2; ++ unsigned ep_dir9:2; ++ unsigned ep_dir10:2; ++ unsigned ep_dir11:2; ++ unsigned ep_dir12:2; ++ unsigned ep_dir13:2; ++ unsigned ep_dir14:2; ++ unsigned ep_dir15:2; ++ } b; ++} hwcfg1_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config2 ++ * Register. Read the register into the <i>d32</i> element then read ++ * out the bits using the <i>b</i>it elements. ++ */ ++typedef union hwcfg2_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG2 */ ++ unsigned op_mode:3; ++#define FH_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0 ++#define FH_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1 ++#define FH_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2 ++#define FH_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 ++#define FH_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 ++#define FH_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 ++#define FH_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 ++ ++ unsigned architecture:2; ++ unsigned point2point:1; ++ unsigned hs_phy_type:2; ++#define FH_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 ++#define FH_HWCFG2_HS_PHY_TYPE_UTMI 1 ++#define FH_HWCFG2_HS_PHY_TYPE_ULPI 2 ++#define FH_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 ++ ++ unsigned fs_phy_type:2; ++ unsigned num_dev_ep:4; ++ unsigned num_host_chan:4; ++ unsigned perio_ep_supported:1; ++ unsigned dynamic_fifo:1; ++ unsigned multi_proc_int:1; ++ unsigned reserved21:1; ++ unsigned nonperio_tx_q_depth:2; ++ unsigned host_perio_tx_q_depth:2; ++ unsigned dev_token_q_depth:5; ++ unsigned otg_enable_ic_usb:1; ++ } b; ++} hwcfg2_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config3 ++ * Register. Read the register into the <i>d32</i> element then read ++ * out the bits using the <i>b</i>it elements. ++ */ ++typedef union hwcfg3_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /* GHWCFG3 */ ++ unsigned xfer_size_cntr_width:4; ++ unsigned packet_size_cntr_width:3; ++ unsigned otg_func:1; ++ unsigned i2c:1; ++ unsigned vendor_ctrl_if:1; ++ unsigned optional_features:1; ++ unsigned synch_reset_type:1; ++ unsigned adp_supp:1; ++ unsigned otg_enable_hsic:1; ++ unsigned bc_support:1; ++ unsigned otg_lpm_en:1; ++ unsigned dfifo_depth:16; ++ } b; ++} hwcfg3_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config4 ++ * Register. Read the register into the <i>d32</i> element then read ++ * out the bits using the <i>b</i>it elements. ++ */ ++typedef union hwcfg4_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned num_dev_perio_in_ep:4; ++ unsigned power_optimiz:1; ++ unsigned min_ahb_freq:1; ++ unsigned hiber:1; ++ unsigned xhiber:1; ++ unsigned reserved:6; ++ unsigned utmi_phy_data_width:2; ++ unsigned num_dev_mode_ctrl_ep:4; ++ unsigned iddig_filt_en:1; ++ unsigned vbus_valid_filt_en:1; ++ unsigned a_valid_filt_en:1; ++ unsigned b_valid_filt_en:1; ++ unsigned session_end_filt_en:1; ++ unsigned ded_fifo_en:1; ++ unsigned num_in_eps:4; ++ unsigned desc_dma:1; ++ unsigned desc_dma_dyn:1; ++ } b; ++} hwcfg4_data_t; ++ ++/** ++ * This union represents the bit fields of the Core LPM Configuration ++ * Register (GLPMCFG). Set the bits using bit fields then write ++ * the <i>d32</i> value to the register. ++ */ ++typedef union glpmctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** LPM-Capable (LPMCap) (Device and Host) ++ * The application uses this bit to control ++ * the FH_otg core LPM capabilities. ++ */ ++ unsigned lpm_cap_en:1; ++ /** LPM response programmed by application (AppL1Res) (Device) ++ * Handshake response to LPM token pre-programmed ++ * by device application software. ++ */ ++ unsigned appl_resp:1; ++ /** Host Initiated Resume Duration (HIRD) (Device and Host) ++ * In Host mode this field indicates the value of HIRD ++ * to be sent in an LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token HIRD bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned hird:4; ++ /** RemoteWakeEnable (bRemoteWake) (Device and Host) ++ * In Host mode this bit indicates the value of remote ++ * wake up to be sent in wIndex field of LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token bRemoteWake bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned rem_wkup_en:1; ++ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host) ++ * The application uses this bit to control ++ * the utmi_sleep_n assertion to the PHY when in L1 state. ++ */ ++ unsigned en_utmi_sleep:1; ++ /** HIRD Threshold (HIRD_Thres) (Device and Host) ++ */ ++ unsigned hird_thres:5; ++ /** LPM Response (CoreL1Res) (Device and Host) ++ * In Host mode this bit contains handsake response to ++ * LPM transaction. ++ * In Device mode the response of the core to ++ * LPM transaction received is reflected in these two bits. ++ - 0x0 : ERROR (No handshake response) ++ - 0x1 : STALL ++ - 0x2 : NYET ++ - 0x3 : ACK ++ */ ++ unsigned lpm_resp:2; ++ /** Port Sleep Status (SlpSts) (Device and Host) ++ * This bit is set as long as a Sleep condition ++ * is present on the USB bus. ++ */ ++ unsigned prt_sleep_sts:1; ++ /** Sleep State Resume OK (L1ResumeOK) (Device and Host) ++ * Indicates that the application or host ++ * can start resume from Sleep state. ++ */ ++ unsigned sleep_state_resumeok:1; ++ /** LPM channel Index (LPM_Chnl_Indx) (Host) ++ * The channel number on which the LPM transaction ++ * has to be applied while sending ++ * an LPM transaction to the local device. ++ */ ++ unsigned lpm_chan_index:4; ++ /** LPM Retry Count (LPM_Retry_Cnt) (Host) ++ * Number host retries that would be performed ++ * if the device response was not valid response. ++ */ ++ unsigned retry_count:3; ++ /** Send LPM Transaction (SndLPM) (Host) ++ * When set by application software, ++ * an LPM transaction containing two tokens ++ * is sent. ++ */ ++ unsigned send_lpm:1; ++ /** LPM Retry status (LPM_RetryCnt_Sts) (Host) ++ * Number of LPM Host Retries still remaining ++ * to be transmitted for the current LPM sequence ++ */ ++ unsigned retry_count_sts:3; ++ /** Enable Best Effort Service Latency (BESL) (Device and Host) ++ * This bit enables the BESL features as defined in the LPM errata ++ */ ++ unsigned en_besl:1; ++ ++ unsigned reserved29:1; ++ /** In host mode once this bit is set, the host ++ * configures to drive the HSIC Idle state on the bus. ++ * It then waits for the device to initiate the Connect sequence. ++ * In device mode once this bit is set, the device waits for ++ * the HSIC Idle line state on the bus. Upon receving the Idle ++ * line state, it initiates the HSIC Connect sequence. ++ */ ++ unsigned hsic_connect:1; ++ /** This bit overrides and functionally inverts ++ * the if_select_hsic input port signal. ++ */ ++ unsigned inv_sel_hsic:1; ++ } b; ++} glpmcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core ADP Timer, Control and ++ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write ++ * the <i>d32</i> value to the register. ++ */ ++typedef union adpctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Probe Discharge (PRB_DSCHG) ++ * These bits set the times for TADP_DSCHG. ++ * These bits are defined as follows: ++ * 2'b00 - 4 msec ++ * 2'b01 - 8 msec ++ * 2'b10 - 16 msec ++ * 2'b11 - 32 msec ++ */ ++ unsigned prb_dschg:2; ++ /** Probe Delta (PRB_DELTA) ++ * These bits set the resolution for RTIM value. ++ * The bits are defined in units of 32 kHz clock cycles as follows: ++ * 2'b00 - 1 cycles ++ * 2'b01 - 2 cycles ++ * 2'b10 - 3 cycles ++ * 2'b11 - 4 cycles ++ * For example if this value is chosen to 2'b01, it means that RTIM ++ * increments for every 3(three) 32Khz clock cycles. ++ */ ++ unsigned prb_delta:2; ++ /** Probe Period (PRB_PER) ++ * These bits sets the TADP_PRD as shown in Figure 4 as follows: ++ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) ++ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) ++ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) ++ * 2'b11 - Reserved ++ */ ++ unsigned prb_per:2; ++ /** These bits capture the latest time it took for VBUS to ramp from ++ * VADP_SINK to VADP_PRB. ++ * 0x000 - 1 cycles ++ * 0x001 - 2 cycles ++ * 0x002 - 3 cycles ++ * etc ++ * 0x7FF - 2048 cycles ++ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. ++ */ ++ unsigned rtim:11; ++ /** Enable Probe (EnaPrb) ++ * When programmed to 1'b1, the core performs a probe operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enaprb:1; ++ /** Enable Sense (EnaSns) ++ * When programmed to 1'b1, the core performs a Sense operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enasns:1; ++ /** ADP Reset (ADPRes) ++ * When set, ADP controller is reset. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpres:1; ++ /** ADP Enable (ADPEn) ++ * When set, the core performs either ADP probing or sensing ++ * based on EnaPrb or EnaSns. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpen:1; ++ /** ADP Probe Interrupt (ADP_PRB_INT) ++ * When this bit is set, it means that the VBUS ++ * voltage is greater than VADP_PRB or VADP_PRB is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int:1; ++ /** ++ * ADP Sense Interrupt (ADP_SNS_INT) ++ * When this bit is set, it means that the VBUS voltage is greater than ++ * VADP_SNS value or VADP_SNS is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int:1; ++ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) ++ * This bit is relevant only for an ADP probe. ++ * When this bit is set, it means that the ramp time has ++ * completed ie ADPCTL.RTIM has reached its terminal value ++ * of 0x7FF. This is a debug feature that allows software ++ * to read the ramp time after each cycle. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int:1; ++ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int_msk:1; ++ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int_msk:1; ++ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int_msk:1; ++ /** Access Request ++ * 2'b00 - Read/Write Valid (updated by the core) ++ * 2'b01 - Read ++ * 2'b00 - Write ++ * 2'b00 - Reserved ++ */ ++ unsigned ar:2; ++ /** Reserved */ ++ unsigned reserved29_31:3; ++ } b; ++} adpctl_data_t; ++ ++//////////////////////////////////////////// ++// Device Registers ++/** ++ * Device Global Registers. <i>Offsets 800h-BFFh</i> ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Registers. ++ * ++ * <i>These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown.</i> ++ */ ++typedef struct fh_otg_dev_global_regs { ++ /** Device Configuration Register. <i>Offset 800h</i> */ ++ volatile uint32_t dcfg; ++ /** Device Control Register. <i>Offset: 804h</i> */ ++ volatile uint32_t dctl; ++ /** Device Status Register (Read Only). <i>Offset: 808h</i> */ ++ volatile uint32_t dsts; ++ /** Reserved. <i>Offset: 80Ch</i> */ ++ uint32_t unused; ++ /** Device IN Endpoint Common Interrupt Mask ++ * Register. <i>Offset: 810h</i> */ ++ volatile uint32_t diepmsk; ++ /** Device OUT Endpoint Common Interrupt Mask ++ * Register. <i>Offset: 814h</i> */ ++ volatile uint32_t doepmsk; ++ /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */ ++ volatile uint32_t daint; ++ /** Device All Endpoints Interrupt Mask Register. <i>Offset: ++ * 81Ch</i> */ ++ volatile uint32_t daintmsk; ++ /** Device IN Token Queue Read Register-1 (Read Only). ++ * <i>Offset: 820h</i> */ ++ volatile uint32_t dtknqr1; ++ /** Device IN Token Queue Read Register-2 (Read Only). ++ * <i>Offset: 824h</i> */ ++ volatile uint32_t dtknqr2; ++ /** Device VBUS discharge Register. <i>Offset: 828h</i> */ ++ volatile uint32_t dvbusdis; ++ /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */ ++ volatile uint32_t dvbuspulse; ++ /** Device IN Token Queue Read Register-3 (Read Only). / ++ * Device Thresholding control register (Read/Write) ++ * <i>Offset: 830h</i> */ ++ volatile uint32_t dtknqr3_dthrctl; ++ /** Device IN Token Queue Read Register-4 (Read Only). / ++ * Device IN EPs empty Inr. Mask Register (Read/Write) ++ * <i>Offset: 834h</i> */ ++ volatile uint32_t dtknqr4_fifoemptymsk; ++ /** Device Each Endpoint Interrupt Register (Read Only). / ++ * <i>Offset: 838h</i> */ ++ volatile uint32_t deachint; ++ /** Device Each Endpoint Interrupt mask Register (Read/Write). / ++ * <i>Offset: 83Ch</i> */ ++ volatile uint32_t deachintmsk; ++ /** Device Each In Endpoint Interrupt mask Register (Read/Write). / ++ * <i>Offset: 840h</i> */ ++ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; ++ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / ++ * <i>Offset: 880h</i> */ ++ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; ++} fh_otg_device_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device Configuration ++ * Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. Write the ++ * <i>d32</i> member to the dcfg register. ++ */ ++typedef union dcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Device Speed */ ++ unsigned devspd:2; ++ /** Non Zero Length Status OUT Handshake */ ++ unsigned nzstsouthshk:1; ++#define FH_DCFG_SEND_STALL 1 ++ ++ unsigned ena32khzs:1; ++ /** Device Addresses */ ++ unsigned devaddr:7; ++ /** Periodic Frame Interval */ ++ unsigned perfrint:2; ++#define FH_DCFG_FRAME_INTERVAL_80 0 ++#define FH_DCFG_FRAME_INTERVAL_85 1 ++#define FH_DCFG_FRAME_INTERVAL_90 2 ++#define FH_DCFG_FRAME_INTERVAL_95 3 ++ ++ /** Enable Device OUT NAK for bulk in DDMA mode */ ++ unsigned endevoutnak:1; ++ ++ unsigned reserved14_17:4; ++ /** In Endpoint Mis-match count */ ++ unsigned epmscnt:5; ++ /** Enable Descriptor DMA in Device mode */ ++ unsigned descdma:1; ++ unsigned perschintvl:2; ++ unsigned resvalid:6; ++ } b; ++} dcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Control ++ * Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union dctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Remote Wakeup */ ++ unsigned rmtwkupsig:1; ++ /** Soft Disconnect */ ++ unsigned sftdiscon:1; ++ /** Global Non-Periodic IN NAK Status */ ++ unsigned gnpinnaksts:1; ++ /** Global OUT NAK Status */ ++ unsigned goutnaksts:1; ++ /** Test Control */ ++ unsigned tstctl:3; ++ /** Set Global Non-Periodic IN NAK */ ++ unsigned sgnpinnak:1; ++ /** Clear Global Non-Periodic IN NAK */ ++ unsigned cgnpinnak:1; ++ /** Set Global OUT NAK */ ++ unsigned sgoutnak:1; ++ /** Clear Global OUT NAK */ ++ unsigned cgoutnak:1; ++ /** Power-On Programming Done */ ++ unsigned pwronprgdone:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Global Multi Count */ ++ unsigned gmc:2; ++ /** Ignore Frame Number for ISOC EPs */ ++ unsigned ifrmnum:1; ++ /** NAK on Babble */ ++ unsigned nakonbble:1; ++ /** Enable Continue on BNA */ ++ unsigned encontonbna:1; ++ /** Enable deep sleep besl reject feature*/ ++ unsigned besl_reject:1; ++ ++ unsigned reserved17_31:13; ++ } b; ++} dctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Status ++ * Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union dsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Suspend Status */ ++ unsigned suspsts:1; ++ /** Enumerated Speed */ ++ unsigned enumspd:2; ++#define FH_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 ++#define FH_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 ++#define FH_DSTS_ENUMSPD_LS_PHY_6MHZ 2 ++#define FH_DSTS_ENUMSPD_FS_PHY_48MHZ 3 ++ /** Erratic Error */ ++ unsigned errticerr:1; ++ unsigned reserved4_7:4; ++ /** Frame or Microframe Number of the received SOF */ ++ unsigned soffn:14; ++ unsigned reserved22_31:10; ++ } b; ++} dsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP Interrupt ++ * Register and the Device IN EP Common Mask Register. ++ * ++ * - Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union diepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete mask */ ++ unsigned xfercompl:1; ++ /** Endpoint disable mask */ ++ unsigned epdisabled:1; ++ /** AHB Error mask */ ++ unsigned ahberr:1; ++ /** TimeOUT Handshake mask (non-ISOC EPs) */ ++ unsigned timeout:1; ++ /** IN Token received with TxF Empty mask */ ++ unsigned intktxfemp:1; ++ /** IN Token Received with EP mismatch mask */ ++ unsigned intknepmis:1; ++ /** IN Endpoint NAK Effective mask */ ++ unsigned inepnakeff:1; ++ /** Reserved */ ++ unsigned emptyintr:1; ++ ++ unsigned txfifoundrn:1; ++ ++ /** BNA Interrupt mask */ ++ unsigned bna:1; ++ ++ unsigned reserved10_12:3; ++ /** BNA Interrupt mask */ ++ unsigned nak:1; ++ ++ unsigned reserved14_31:18; ++ } b; ++} diepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union diepint_data diepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP Interrupt ++ * Registerand Device OUT EP Common Interrupt Mask Register. ++ * ++ * - Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union doepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete */ ++ unsigned xfercompl:1; ++ /** Endpoint disable */ ++ unsigned epdisabled:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** Setup Phase Done (contorl EPs) */ ++ unsigned setup:1; ++ /** OUT Token Received when Endpoint Disabled */ ++ unsigned outtknepdis:1; ++ ++ unsigned stsphsercvd:1; ++ /** Back-to-Back SETUP Packets Received */ ++ unsigned back2backsetup:1; ++ ++ unsigned reserved7:1; ++ /** OUT packet Error */ ++ unsigned outpkterr:1; ++ /** BNA Interrupt */ ++ unsigned bna:1; ++ ++ unsigned reserved10:1; ++ /** Packet Drop Status */ ++ unsigned pktdrpsts:1; ++ /** Babble Interrupt */ ++ unsigned babble:1; ++ /** NAK Interrupt */ ++ unsigned nak:1; ++ /** NYET Interrupt */ ++ unsigned nyet:1; ++ /** Bit indicating setup packet received */ ++ unsigned sr:1; ++ ++ unsigned reserved16_31:16; ++ } b; ++} doepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union doepint_data doepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device All EP Interrupt ++ * and Mask Registers. ++ * - Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union daint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** IN Endpoint bits */ ++ unsigned in:16; ++ /** OUT Endpoint bits */ ++ unsigned out:16; ++ } ep; ++ struct { ++ /** IN Endpoint bits */ ++ unsigned inep0:1; ++ unsigned inep1:1; ++ unsigned inep2:1; ++ unsigned inep3:1; ++ unsigned inep4:1; ++ unsigned inep5:1; ++ unsigned inep6:1; ++ unsigned inep7:1; ++ unsigned inep8:1; ++ unsigned inep9:1; ++ unsigned inep10:1; ++ unsigned inep11:1; ++ unsigned inep12:1; ++ unsigned inep13:1; ++ unsigned inep14:1; ++ unsigned inep15:1; ++ /** OUT Endpoint bits */ ++ unsigned outep0:1; ++ unsigned outep1:1; ++ unsigned outep2:1; ++ unsigned outep3:1; ++ unsigned outep4:1; ++ unsigned outep5:1; ++ unsigned outep6:1; ++ unsigned outep7:1; ++ unsigned outep8:1; ++ unsigned outep9:1; ++ unsigned outep10:1; ++ unsigned outep11:1; ++ unsigned outep12:1; ++ unsigned outep13:1; ++ unsigned outep14:1; ++ unsigned outep15:1; ++ } b; ++} daint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN Token Queue ++ * Read Registers. ++ * - Read the register into the <i>d32</i> member. ++ * - READ-ONLY Register ++ */ ++typedef union dtknq1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** In Token Queue Write Pointer */ ++ unsigned intknwptr:5; ++ /** Reserved */ ++ unsigned reserved05_06:2; ++ /** write pointer has wrapped. */ ++ unsigned wrap_bit:1; ++ /** EP Numbers of IN Tokens 0 ... 4 */ ++ unsigned epnums0_5:24; ++ } b; ++} dtknq1_data_t; ++ ++/** ++ * This union represents Threshold control Register ++ * - Read and write the register into the <i>d32</i> member. ++ * - READ-WRITABLE Register ++ */ ++typedef union dthrctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** non ISO Tx Thr. Enable */ ++ unsigned non_iso_thr_en:1; ++ /** ISO Tx Thr. Enable */ ++ unsigned iso_thr_en:1; ++ /** Tx Thr. Length */ ++ unsigned tx_thr_len:9; ++ /** AHB Threshold ratio */ ++ unsigned ahb_thr_ratio:2; ++ /** Reserved */ ++ unsigned reserved13_15:3; ++ /** Rx Thr. Enable */ ++ unsigned rx_thr_en:1; ++ /** Rx Thr. Length */ ++ unsigned rx_thr_len:9; ++ unsigned reserved26:1; ++ /** Arbiter Parking Enable*/ ++ unsigned arbprken:1; ++ /** Reserved */ ++ unsigned reserved28_31:4; ++ } b; ++} dthrctl_data_t; ++ ++/** ++ * Device Logical IN Endpoint-Specific Registers. <i>Offsets ++ * 900h-AFCh</i> ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * <i>These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown.</i> ++ */ ++typedef struct fh_otg_dev_in_ep_regs { ++ /** Device IN Endpoint Control Register. <i>Offset:900h + ++ * (ep_num * 20h) + 00h</i> */ ++ volatile uint32_t diepctl; ++ /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */ ++ uint32_t reserved04; ++ /** Device IN Endpoint Interrupt Register. <i>Offset:900h + ++ * (ep_num * 20h) + 08h</i> */ ++ volatile uint32_t diepint; ++ /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */ ++ uint32_t reserved0C; ++ /** Device IN Endpoint Transfer Size ++ * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */ ++ volatile uint32_t dieptsiz; ++ /** Device IN Endpoint DMA Address Register. <i>Offset:900h + ++ * (ep_num * 20h) + 14h</i> */ ++ volatile uint32_t diepdma; ++ /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h + ++ * (ep_num * 20h) + 18h</i> */ ++ volatile uint32_t dtxfsts; ++ /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h + ++ * (ep_num * 20h) + 1Ch</i> */ ++ volatile uint32_t diepdmab; ++} fh_otg_dev_in_ep_regs_t; ++ ++/** ++ * Device Logical OUT Endpoint-Specific Registers. <i>Offsets: ++ * B00h-CFCh</i> ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * <i>These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown.</i> ++ */ ++typedef struct fh_otg_dev_out_ep_regs { ++ /** Device OUT Endpoint Control Register. <i>Offset:B00h + ++ * (ep_num * 20h) + 00h</i> */ ++ volatile uint32_t doepctl; ++ /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */ ++ uint32_t reserved04; ++ /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h + ++ * (ep_num * 20h) + 08h</i> */ ++ volatile uint32_t doepint; ++ /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */ ++ uint32_t reserved0C; ++ /** Device OUT Endpoint Transfer Size Register. <i>Offset: ++ * B00h + (ep_num * 20h) + 10h</i> */ ++ volatile uint32_t doeptsiz; ++ /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h ++ * + (ep_num * 20h) + 14h</i> */ ++ volatile uint32_t doepdma; ++ /** Reserved. <i>Offset:B00h + * (ep_num * 20h) + 18h</i> */ ++ uint32_t unused; ++ /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h ++ * + (ep_num * 20h) + 1Ch</i> */ ++ uint32_t doepdmab; ++} fh_otg_dev_out_ep_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Control ++ * Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union depctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Maximum Packet Size ++ * IN/OUT EPn ++ * IN/OUT EP0 - 2 bits ++ * 2'b00: 64 Bytes ++ * 2'b01: 32 ++ * 2'b10: 16 ++ * 2'b11: 8 */ ++ unsigned mps:11; ++#define FH_DEP0CTL_MPS_64 0 ++#define FH_DEP0CTL_MPS_32 1 ++#define FH_DEP0CTL_MPS_16 2 ++#define FH_DEP0CTL_MPS_8 3 ++ ++ /** Next Endpoint ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned nextep:4; ++ ++ /** USB Active Endpoint */ ++ unsigned usbactep:1; ++ ++ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints) ++ * This field contains the PID of the packet going to ++ * be received or transmitted on this endpoint. The ++ * application should program the PID of the first ++ * packet going to be received or transmitted on this ++ * endpoint , after the endpoint is ++ * activated. Application use the SetD1PID and ++ * SetD0PID fields of this register to program either ++ * D0 or D1 PID. ++ * ++ * The encoding for this field is ++ * - 0: D0 ++ * - 1: D1 ++ */ ++ unsigned dpid:1; ++ ++ /** NAK Status */ ++ unsigned naksts:1; ++ ++ /** Endpoint Type ++ * 2'b00: Control ++ * 2'b01: Isochronous ++ * 2'b10: Bulk ++ * 2'b11: Interrupt */ ++ unsigned eptype:2; ++ ++ /** Snoop Mode ++ * OUT EPn/OUT EP0 ++ * IN EPn/IN EP0 - reserved */ ++ unsigned snp:1; ++ ++ /** Stall Handshake */ ++ unsigned stall:1; ++ ++ /** Tx Fifo Number ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned txfnum:4; ++ ++ /** Clear NAK */ ++ unsigned cnak:1; ++ /** Set NAK */ ++ unsigned snak:1; ++ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA0. Set Even ++ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to even (micro) ++ * frame. ++ */ ++ unsigned setd0pid:1; ++ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA1 Set Odd ++ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to odd (micro) frame. ++ */ ++ unsigned setd1pid:1; ++ ++ /** Endpoint Disable */ ++ unsigned epdis:1; ++ /** Endpoint Enable */ ++ unsigned epena:1; ++ } b; ++} depctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Transfer ++ * Size Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union deptsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:19; ++/** Max packet count for EP (pow(2,10)-1) */ ++#define MAX_PKT_CNT 1023 ++ /** Packet Count */ ++ unsigned pktcnt:10; ++ /** Multi Count - Periodic IN endpoints */ ++ unsigned mc:2; ++ unsigned reserved:1; ++ } b; ++} deptsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP 0 Transfer ++ * Size Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union deptsiz0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:7; ++ /** Reserved */ ++ unsigned reserved7_18:12; ++ /** Packet Count */ ++ unsigned pktcnt:2; ++ /** Reserved */ ++ unsigned reserved21_28:8; ++ /**Setup Packet Count (DOEPTSIZ0 Only) */ ++ unsigned supcnt:2; ++ unsigned reserved31; ++ } b; ++} deptsiz0_data_t; ++ ++///////////////////////////////////////////////// ++// DMA Descriptor Specific Structures ++// ++ ++/** Buffer status definitions */ ++ ++#define BS_HOST_READY 0x0 ++#define BS_DMA_BUSY 0x1 ++#define BS_DMA_DONE 0x2 ++#define BS_HOST_BUSY 0x3 ++ ++/** Receive/Transmit status definitions */ ++ ++#define RTS_SUCCESS 0x0 ++#define RTS_BUFFLUSH 0x1 ++#define RTS_RESERVED 0x2 ++#define RTS_BUFERR 0x3 ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet. Read the quadlet into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and ++ * <i>b_iso_in</i> elements. ++ */ ++typedef union dev_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned bytes:16; ++ /** NAK bit - only for OUT EPs */ ++ unsigned nak:1; ++ unsigned reserved17_22:6; ++ /** Multiple Transfer - only for OUT EPs */ ++ unsigned mtrf:1; ++ /** Setup Packet received - only for OUT EPs */ ++ unsigned sr:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned sts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b; ++ ++//#ifdef FH_EN_ISOC ++ /** iso out quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned rxbytes:11; ++ ++ unsigned reserved11:1; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Received ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Receive Status */ ++ unsigned rxsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_out; ++ ++ /** iso in quadlet bits */ ++ struct { ++ /** Transmited number of bytes */ ++ unsigned txbytes:12; ++ /** Frame Number */ ++ unsigned framenum:11; ++ /** Transmited ISO Data PID */ ++ unsigned pid:2; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** Short Packet */ ++ unsigned sp:1; ++ /** Last */ ++ unsigned l:1; ++ /** Transmit Status */ ++ unsigned txsts:2; ++ /** Buffer Status */ ++ unsigned bs:2; ++ } b_iso_in; ++//#endif /* FH_EN_ISOC */ ++} dev_dma_desc_sts_t; ++ ++/** ++ * DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct fh_otg_dev_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ dev_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} fh_otg_dev_dma_desc_t; ++ ++/** ++ * The fh_otg_dev_if structure contains information needed to manage ++ * the FH_otg controller acting in device mode. It represents the ++ * programming view of the device-specific aspects of the controller. ++ */ ++typedef struct fh_otg_dev_if { ++ /** Pointer to device Global registers. ++ * Device Global Registers starting at offset 800h ++ */ ++ fh_otg_device_global_regs_t *dev_global_regs; ++#define FH_DEV_GLOBAL_REG_OFFSET 0x800 ++ ++ /** ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ */ ++ fh_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; ++#define FH_DEV_IN_EP_REG_OFFSET 0x900 ++#define FH_EP_REG_OFFSET 0x20 ++ ++ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ ++ fh_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS]; ++#define FH_DEV_OUT_EP_REG_OFFSET 0xB00 ++ ++ /* Device configuration information */ ++ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ ++ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */ ++ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/ ++ ++ /** Size of periodic FIFOs (Bytes) */ ++ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Size of Tx FIFOs (Bytes) */ ++ uint16_t tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flags and length varaiables **/ ++ uint16_t rx_thr_en; ++ uint16_t iso_tx_thr_en; ++ uint16_t non_iso_tx_thr_en; ++ ++ uint16_t rx_thr_length; ++ uint16_t tx_thr_length; ++ ++ /** ++ * Pointers to the DMA Descriptors for EP0 Control ++ * transfers (virtual and physical) ++ */ ++ ++ /** 2 descriptors for SETUP packets */ ++ fh_dma_t dma_setup_desc_addr[2]; ++ fh_otg_dev_dma_desc_t *setup_desc_addr[2]; ++ ++ /** Pointer to Descriptor with latest SETUP packet */ ++ fh_otg_dev_dma_desc_t *psetup; ++ ++ /** Index of current SETUP handler descriptor */ ++ uint32_t setup_desc_index; ++ ++ /** Descriptor for Data In or Status In phases */ ++ fh_dma_t dma_in_desc_addr; ++ fh_otg_dev_dma_desc_t *in_desc_addr; ++ ++ /** Descriptor for Data Out or Status Out phases */ ++ fh_dma_t dma_out_desc_addr; ++ fh_otg_dev_dma_desc_t *out_desc_addr; ++ ++ /** Setup Packet Detected - if set clear NAK when queueing */ ++ uint32_t spd; ++ /** Isoc ep pointer on which incomplete happens */ ++ void *isoc_ep; ++ ++} fh_otg_dev_if_t; ++ ++///////////////////////////////////////////////// ++// Host Mode Register Structures ++// ++/** ++ * The Host Global Registers structure defines the size and relative ++ * field offsets for the Host Mode Global Registers. Host Global ++ * Registers offsets 400h-7FFh. ++*/ ++typedef struct fh_otg_host_global_regs { ++ /** Host Configuration Register. <i>Offset: 400h</i> */ ++ volatile uint32_t hcfg; ++ /** Host Frame Interval Register. <i>Offset: 404h</i> */ ++ volatile uint32_t hfir; ++ /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */ ++ volatile uint32_t hfnum; ++ /** Reserved. <i>Offset: 40Ch</i> */ ++ uint32_t reserved40C; ++ /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */ ++ volatile uint32_t hptxsts; ++ /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */ ++ volatile uint32_t haint; ++ /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */ ++ volatile uint32_t haintmsk; ++ /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */ ++ volatile uint32_t hflbaddr; ++} fh_otg_host_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Configuration Register. ++ * Read the register into the <i>d32</i> member then set/clear the bits using ++ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register. ++ */ ++typedef union hcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** FS/LS Phy Clock Select */ ++ unsigned fslspclksel:2; ++#define FH_HCFG_30_60_MHZ 0 ++#define FH_HCFG_48_MHZ 1 ++#define FH_HCFG_6_MHZ 2 ++ ++ /** FS/LS Only Support */ ++ unsigned fslssupp:1; ++ unsigned reserved3_6:4; ++ /** Enable 32-KHz Suspend Mode */ ++ unsigned ena32khzs:1; ++ /** Resume Validation Periiod */ ++ unsigned resvalid:8; ++ unsigned reserved16_22:7; ++ /** Enable Scatter/gather DMA in Host mode */ ++ unsigned descdma:1; ++ /** Frame List Entries */ ++ unsigned frlisten:2; ++ /** Enable Periodic Scheduling */ ++ unsigned perschedena:1; ++ unsigned reserved27_30:4; ++ unsigned modechtimen:1; ++ } b; ++} hcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfir_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frint:16; ++ unsigned hfirrldctrl:1; ++ unsigned reserved:15; ++ } b; ++} hfir_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Frame Remaing/Number ++ * Register. ++ */ ++typedef union hfnum_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned frnum:16; ++#define FH_HFNUM_MAX_FRNUM 0x3FFF ++ unsigned frrem:16; ++ } b; ++} hfnum_data_t; ++ ++typedef union hptxsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned ptxfspcavail:16; ++ unsigned ptxqspcavail:8; ++ /** Top of the Periodic Transmit Request Queue ++ * - bit 24 - Terminate (last entry for the selected channel) ++ * - bits 26:25 - Token Type ++ * - 2'b00 - Zero length ++ * - 2'b01 - Ping ++ * - 2'b10 - Disable ++ * - bits 30:27 - Channel Number ++ * - bit 31 - Odd/even microframe ++ */ ++ unsigned ptxqtop_terminate:1; ++ unsigned ptxqtop_token:2; ++ unsigned ptxqtop_chnum:4; ++ unsigned ptxqtop_odd:1; ++ } b; ++} hptxsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Port Control and Status ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the ++ * hprt0 register. ++ */ ++typedef union hprt0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned prtconnsts:1; ++ unsigned prtconndet:1; ++ unsigned prtena:1; ++ unsigned prtenchng:1; ++ unsigned prtovrcurract:1; ++ unsigned prtovrcurrchng:1; ++ unsigned prtres:1; ++ unsigned prtsusp:1; ++ unsigned prtrst:1; ++ unsigned reserved9:1; ++ unsigned prtlnsts:2; ++ unsigned prtpwr:1; ++ unsigned prttstctl:4; ++ unsigned prtspd:2; ++#define FH_HPRT0_PRTSPD_HIGH_SPEED 0 ++#define FH_HPRT0_PRTSPD_FULL_SPEED 1 ++#define FH_HPRT0_PRTSPD_LOW_SPEED 2 ++ unsigned reserved19_31:13; ++ } b; ++} hprt0_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union haintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned ch0:1; ++ unsigned ch1:1; ++ unsigned ch2:1; ++ unsigned ch3:1; ++ unsigned ch4:1; ++ unsigned ch5:1; ++ unsigned ch6:1; ++ unsigned ch7:1; ++ unsigned ch8:1; ++ unsigned ch9:1; ++ unsigned ch10:1; ++ unsigned ch11:1; ++ unsigned ch12:1; ++ unsigned ch13:1; ++ unsigned ch14:1; ++ unsigned ch15:1; ++ unsigned reserved:16; ++ } b; ++ ++ struct { ++ unsigned chint:16; ++ unsigned reserved:16; ++ } b2; ++} haintmsk_data_t; ++ ++/** ++ * Host Channel Specific Registers. <i>500h-5FCh</i> ++ */ ++typedef struct fh_otg_hc_regs { ++ /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */ ++ volatile uint32_t hcchar; ++ /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */ ++ volatile uint32_t hcsplt; ++ /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */ ++ volatile uint32_t hcint; ++ /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */ ++ volatile uint32_t hcintmsk; ++ /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */ ++ volatile uint32_t hctsiz; ++ /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */ ++ volatile uint32_t hcdma; ++ volatile uint32_t reserved; ++ /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */ ++ volatile uint32_t hcdmab; ++} fh_otg_hc_regs_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Characteristics ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the ++ * hcchar register. ++ */ ++typedef union hcchar_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Maximum packet size in bytes */ ++ unsigned mps:11; ++ ++ /** Endpoint number */ ++ unsigned epnum:4; ++ ++ /** 0: OUT, 1: IN */ ++ unsigned epdir:1; ++ ++ unsigned reserved:1; ++ ++ /** 0: Full/high speed device, 1: Low speed device */ ++ unsigned lspddev:1; ++ ++ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */ ++ unsigned eptype:2; ++ ++ /** Packets per frame for periodic transfers. 0 is reserved. */ ++ unsigned multicnt:2; ++ ++ /** Device address */ ++ unsigned devaddr:7; ++ ++ /** ++ * Frame to transmit periodic transaction. ++ * 0: even, 1: odd ++ */ ++ unsigned oddfrm:1; ++ ++ /** Channel disable */ ++ unsigned chdis:1; ++ ++ /** Channel enable */ ++ unsigned chen:1; ++ } b; ++} hcchar_data_t; ++ ++typedef union hcsplt_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Port Address */ ++ unsigned prtaddr:7; ++ ++ /** Hub Address */ ++ unsigned hubaddr:7; ++ ++ /** Transaction Position */ ++ unsigned xactpos:2; ++#define FH_HCSPLIT_XACTPOS_MID 0 ++#define FH_HCSPLIT_XACTPOS_END 1 ++#define FH_HCSPLIT_XACTPOS_BEGIN 2 ++#define FH_HCSPLIT_XACTPOS_ALL 3 ++ ++ /** Do Complete Split */ ++ unsigned compsplt:1; ++ ++ /** Reserved */ ++ unsigned reserved:14; ++ ++ /** Split Enble */ ++ unsigned spltena:1; ++ } b; ++} hcsplt_data_t; ++ ++/** ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. ++ */ ++typedef union hcint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer Complete */ ++ unsigned xfercomp:1; ++ /** Channel Halted */ ++ unsigned chhltd:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** STALL Response Received */ ++ unsigned stall:1; ++ /** NAK Response Received */ ++ unsigned nak:1; ++ /** ACK Response Received */ ++ unsigned ack:1; ++ /** NYET Response Received */ ++ unsigned nyet:1; ++ /** Transaction Err */ ++ unsigned xacterr:1; ++ /** Babble Error */ ++ unsigned bblerr:1; ++ /** Frame Overrun */ ++ unsigned frmovrun:1; ++ /** Data Toggle Error */ ++ unsigned datatglerr:1; ++ /** Buffer Not Available (only for DDMA mode) */ ++ unsigned bna:1; ++ /** Exessive transaction error (only for DDMA mode) */ ++ unsigned xcs_xact:1; ++ /** Frame List Rollover interrupt */ ++ unsigned frm_list_roll:1; ++ /** Reserved */ ++ unsigned reserved14_31:18; ++ } b; ++} hcint_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Interrupt Mask ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the ++ * hcintmsk register. ++ */ ++typedef union hcintmsk_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ unsigned xfercompl:1; ++ unsigned chhltd:1; ++ unsigned ahberr:1; ++ unsigned stall:1; ++ unsigned nak:1; ++ unsigned ack:1; ++ unsigned nyet:1; ++ unsigned xacterr:1; ++ unsigned bblerr:1; ++ unsigned frmovrun:1; ++ unsigned datatglerr:1; ++ unsigned bna:1; ++ unsigned xcs_xact:1; ++ unsigned frm_list_roll:1; ++ unsigned reserved14_31:18; ++ } b; ++} hcintmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Host Channel Transfer Size ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the ++ * hcchar register. ++ */ ++ ++typedef union hctsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Total transfer size in bytes */ ++ unsigned xfersize:19; ++ ++ /** Data packets to transfer */ ++ unsigned pktcnt:10; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control), SETUP (Control) ++ */ ++ unsigned pid:2; ++#define FH_HCTSIZ_DATA0 0 ++#define FH_HCTSIZ_DATA1 2 ++#define FH_HCTSIZ_DATA2 1 ++#define FH_HCTSIZ_MDATA 3 ++#define FH_HCTSIZ_SETUP 3 ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b; ++ ++ /** register bits */ ++ struct { ++ /** Scheduling information */ ++ unsigned schinfo:8; ++ ++ /** Number of transfer descriptors. ++ * Max value: ++ * 64 in general, ++ * 256 only for HS isochronous endpoint. ++ */ ++ unsigned ntd:8; ++ ++ /** Data packets to transfer */ ++ unsigned reserved16_28:13; ++ ++ /** ++ * Packet ID for next data packet ++ * 0: DATA0 ++ * 1: DATA2 ++ * 2: DATA1 ++ * 3: MDATA (non-Control) ++ */ ++ unsigned pid:2; ++ ++ /** Do PING protocol when 1 */ ++ unsigned dopng:1; ++ } b_ddma; ++} hctsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Host DMA Address ++ * Register used in Descriptor DMA mode. ++ */ ++typedef union hcdma_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned reserved0_2:3; ++ /** Current Transfer Descriptor. Not used for ISOC */ ++ unsigned ctd:8; ++ /** Start Address of Descriptor List */ ++ unsigned dma_addr:21; ++ } b; ++} hcdma_data_t; ++ ++/** ++ * This union represents the bit fields in the DMA Descriptor ++ * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union host_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ ++ /* for non-isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:17; ++ /** QTD offset to jump when Short Packet received - only for IN EPs */ ++ unsigned qtd_offset:6; ++ /** ++ * Set to request the core to jump to alternate QTD if ++ * Short Packet received - only for IN EPs ++ */ ++ unsigned a_qtd:1; ++ /** ++ * Setup Packet bit. When set indicates that buffer contains ++ * setup packet. ++ */ ++ unsigned sup:1; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ /** End of List */ ++ unsigned eol:1; ++ unsigned reserved27:1; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++#define DMA_DESC_STS_PKTERR 1 ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b; ++ /* for isochronous */ ++ struct { ++ /** Number of bytes */ ++ unsigned n_bytes:12; ++ unsigned reserved12_24:13; ++ /** Interrupt On Complete */ ++ unsigned ioc:1; ++ unsigned reserved26_27:2; ++ /** Rx/Tx Status */ ++ unsigned sts:2; ++ unsigned reserved30:1; ++ /** Active Bit */ ++ unsigned a:1; ++ } b_isoc; ++} host_dma_desc_sts_t; ++ ++#define MAX_DMA_DESC_SIZE 131071 ++#define MAX_DMA_DESC_NUM_GENERIC 64 ++#define MAX_DMA_DESC_NUM_HS_ISOC 256 ++#define MAX_FRLIST_EN_NUM 64 ++/** ++ * Host-mode DMA Descriptor structure ++ * ++ * DMA Descriptor structure contains two quadlets: ++ * Status quadlet and Data buffer pointer. ++ */ ++typedef struct fh_otg_host_dma_desc { ++ /** DMA Descriptor status quadlet */ ++ host_dma_desc_sts_t status; ++ /** DMA Descriptor data buffer pointer */ ++ uint32_t buf; ++} fh_otg_host_dma_desc_t; ++ ++/** OTG Host Interface Structure. ++ * ++ * The OTG Host Interface Structure structure contains information ++ * needed to manage the FH_otg controller acting in host mode. It ++ * represents the programming view of the host-specific aspects of the ++ * controller. ++ */ ++typedef struct fh_otg_host_if { ++ /** Host Global Registers starting at offset 400h.*/ ++ fh_otg_host_global_regs_t *host_global_regs; ++#define FH_OTG_HOST_GLOBAL_REG_OFFSET 0x400 ++ ++ /** Host Port 0 Control and Status Register */ ++ volatile uint32_t *hprt0; ++#define FH_OTG_HOST_PORT_REGS_OFFSET 0x440 ++ ++ /** Host Channel Specific Registers at offsets 500h-5FCh. */ ++ fh_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS]; ++#define FH_OTG_HOST_CHAN_REGS_OFFSET 0x500 ++#define FH_OTG_CHAN_REGS_OFFSET 0x20 ++ ++ /* Host configuration information */ ++ /** Number of Host Channels (range: 1-16) */ ++ uint8_t num_host_channels; ++ /** Periodic EPs supported (0: no, 1: yes) */ ++ uint8_t perio_eps_supported; ++ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */ ++ uint16_t perio_tx_fifo_size; ++ ++} fh_otg_host_if_t; ++ ++/** ++ * This union represents the bit fields in the Power and Clock Gating Control ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union pcgcctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** Stop Pclk */ ++ unsigned stoppclk:1; ++ /** Gate Hclk */ ++ unsigned gatehclk:1; ++ /** Power Clamp */ ++ unsigned pwrclmp:1; ++ /** Reset Power Down Modules */ ++ unsigned rstpdwnmodule:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Enable Sleep Clock Gating (Enbl_L1Gating) */ ++ unsigned enbl_sleep_gating:1; ++ /** PHY In Sleep (PhySleep) */ ++ unsigned phy_in_sleep:1; ++ /** Deep Sleep*/ ++ unsigned deep_sleep:1; ++ unsigned resetaftsusp:1; ++ unsigned restoremode:1; ++ unsigned enbl_extnd_hiber:1; ++ unsigned extnd_hiber_pwrclmp:1; ++ unsigned extnd_hiber_switch:1; ++ unsigned ess_reg_restored:1; ++ unsigned prt_clk_sel:2; ++ unsigned port_power:1; ++ unsigned max_xcvrselect:2; ++ unsigned max_termsel:1; ++ unsigned mac_dev_addr:7; ++ unsigned p2hd_dev_enum_spd:2; ++ unsigned p2hd_prt_spd:2; ++ unsigned if_dev_mode:1; ++ } b; ++} pcgcctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Data FIFO Software ++ * Configuration Register. Read the register into the <i>d32</i> member then ++ * set/clear the bits using the <i>b</i>it elements. ++ */ ++typedef union gdfifocfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** OTG Data FIFO depth */ ++ unsigned gdfifocfg:16; ++ /** Start address of EP info controller */ ++ unsigned epinfobase:16; ++ } b; ++} gdfifocfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Power Down Register ++ * Register. Read the register into the <i>d32</i> member then set/clear the ++ * bits using the <i>b</i>it elements. ++ */ ++typedef union gpwrdn_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** PMU Interrupt Select */ ++ unsigned pmuintsel:1; ++ /** PMU Active */ ++ unsigned pmuactv:1; ++ /** Restore */ ++ unsigned restore:1; ++ /** Power Down Clamp */ ++ unsigned pwrdnclmp:1; ++ /** Power Down Reset */ ++ unsigned pwrdnrstn:1; ++ /** Power Down Switch */ ++ unsigned pwrdnswtch:1; ++ /** Disable VBUS */ ++ unsigned dis_vbus:1; ++ /** Line State Change */ ++ unsigned lnstschng:1; ++ /** Line state change mask */ ++ unsigned lnstchng_msk:1; ++ /** Reset Detected */ ++ unsigned rst_det:1; ++ /** Reset Detect mask */ ++ unsigned rst_det_msk:1; ++ /** Disconnect Detected */ ++ unsigned disconn_det:1; ++ /** Disconnect Detect mask */ ++ unsigned disconn_det_msk:1; ++ /** Connect Detected*/ ++ unsigned connect_det:1; ++ /** Connect Detected Mask*/ ++ unsigned connect_det_msk:1; ++ /** SRP Detected */ ++ unsigned srp_det:1; ++ /** SRP Detect mask */ ++ unsigned srp_det_msk:1; ++ /** Status Change Interrupt */ ++ unsigned sts_chngint:1; ++ /** Status Change Interrupt Mask */ ++ unsigned sts_chngint_msk:1; ++ /** Line State */ ++ unsigned linestate:2; ++ /** Indicates current mode(status of IDDIG signal) */ ++ unsigned idsts:1; ++ /** B Session Valid signal status*/ ++ unsigned bsessvld:1; ++ /** ADP Event Detected */ ++ unsigned adp_int:1; ++ /** Multi Valued ID pin */ ++ unsigned mult_val_id_bc:5; ++ /** Reserved 24_31 */ ++ unsigned reserved29_31:3; ++ } b; ++} gpwrdn_data_t; ++ ++#endif +diff --git a/drivers/usb/host/fh_otg/fh_otg/test/Makefile b/drivers/usb/host/fh_otg/fh_otg/test/Makefile +new file mode 100755 +index 00000000..fc453759 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/test/Makefile +@@ -0,0 +1,16 @@ ++ ++PERL=/usr/bin/perl ++PL_TESTS=test_sysfs.pl test_mod_param.pl ++ ++.PHONY : test ++test : perl_tests ++ ++perl_tests : ++ @echo ++ @echo Running perl tests ++ @for test in $(PL_TESTS); do \ ++ if $(PERL) ./$$test ; then \ ++ echo "=======> $$test, PASSED" ; \ ++ else echo "=======> $$test, FAILED" ; \ ++ fi \ ++ done +diff --git a/drivers/usb/host/fh_otg/fh_otg/test/fh_otg_test.pm b/drivers/usb/host/fh_otg/fh_otg/test/fh_otg_test.pm +new file mode 100755 +index 00000000..b4b4c294 +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/test/fh_otg_test.pm +@@ -0,0 +1,337 @@ ++package fh_otg_test; ++ ++use strict; ++use Exporter (); ++ ++use vars qw(@ISA @EXPORT ++$sysfsdir $paramdir $errors $params ++); ++ ++@ISA = qw(Exporter); ++ ++# ++# Globals ++# ++$sysfsdir = "/sys/devices/lm0"; ++$paramdir = "/sys/module/fh_otg"; ++$errors = 0; ++ ++$params = [ ++ { ++ NAME => "otg_cap", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 2 ++ }, ++ { ++ NAME => "dma_enable", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "dma_burst_size", ++ DEFAULT => 32, ++ ENUM => [1, 4, 8, 16, 32, 64, 128, 256], ++ LOW => 1, ++ HIGH => 256 ++ }, ++ { ++ NAME => "host_speed", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "host_support_fs_ls_low_power", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "host_ls_low_power_phy_clk", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "dev_speed", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "enable_dynamic_fifo", ++ DEFAULT => 1, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "data_fifo_size", ++ DEFAULT => 8192, ++ ENUM => [], ++ LOW => 32, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_rx_fifo_size", ++ DEFAULT => 1064, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_nperio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_1", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_2", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_3", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_4", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_5", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_6", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_7", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_8", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_9", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_10", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_11", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_12", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_13", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_14", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_15", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "host_rx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "host_nperio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "host_perio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "max_transfer_size", ++ DEFAULT => 65535, ++ ENUM => [], ++ LOW => 2047, ++ HIGH => 65535 ++ }, ++ { ++ NAME => "max_packet_count", ++ DEFAULT => 511, ++ ENUM => [], ++ LOW => 15, ++ HIGH => 511 ++ }, ++ { ++ NAME => "host_channels", ++ DEFAULT => 12, ++ ENUM => [], ++ LOW => 1, ++ HIGH => 16 ++ }, ++ { ++ NAME => "dev_endpoints", ++ DEFAULT => 6, ++ ENUM => [], ++ LOW => 1, ++ HIGH => 15 ++ }, ++ { ++ NAME => "phy_type", ++ DEFAULT => 1, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 2 ++ }, ++ { ++ NAME => "phy_utmi_width", ++ DEFAULT => 16, ++ ENUM => [8, 16], ++ LOW => 8, ++ HIGH => 16 ++ }, ++ { ++ NAME => "phy_ulpi_ddr", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ ]; ++ ++ ++# ++# ++sub check_arch { ++ $_ = `uname -m`; ++ chomp; ++ unless (m/armv4tl/) { ++ warn "# \n# Can't execute on $_. Run on integrator platform.\n# \n"; ++ return 0; ++ } ++ return 1; ++} ++ ++# ++# ++sub load_module { ++ my $params = shift; ++ print "\nRemoving Module\n"; ++ system "rmmod fh_otg"; ++ print "Loading Module\n"; ++ if ($params ne "") { ++ print "Module Parameters: $params\n"; ++ } ++ if (system("modprobe fh_otg $params")) { ++ warn "Unable to load module\n"; ++ return 0; ++ } ++ return 1; ++} ++ ++# ++# ++sub test_status { ++ my $arg = shift; ++ ++ print "\n"; ++ ++ if (defined $arg) { ++ warn "WARNING: $arg\n"; ++ } ++ ++ if ($errors > 0) { ++ warn "TEST FAILED with $errors errors\n"; ++ return 0; ++ } else { ++ print "TEST PASSED\n"; ++ return 0 if (defined $arg); ++ } ++ return 1; ++} ++ ++# ++# ++@EXPORT = qw( ++$sysfsdir ++$paramdir ++$params ++$errors ++check_arch ++load_module ++test_status ++); ++ ++1; +diff --git a/drivers/usb/host/fh_otg/fh_otg/test/test_mod_param.pl b/drivers/usb/host/fh_otg/fh_otg/test/test_mod_param.pl +new file mode 100755 +index 00000000..f7c6549c +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/test/test_mod_param.pl +@@ -0,0 +1,133 @@ ++#!/usr/bin/perl -w ++# ++# Run this program on the integrator. ++# ++# - Tests module parameter default values. ++# - Tests setting of valid module parameter values via modprobe. ++# - Tests invalid module parameter values. ++# ----------------------------------------------------------------------------- ++use strict; ++use fh_otg_test; ++ ++check_arch() or die; ++ ++# ++# ++sub test { ++ my ($param,$expected) = @_; ++ my $value = get($param); ++ ++ if ($value == $expected) { ++ print "$param = $value, okay\n"; ++ } ++ ++ else { ++ warn "ERROR: value of $param != $expected, $value\n"; ++ $errors ++; ++ } ++} ++ ++# ++# ++sub get { ++ my $param = shift; ++ my $tmp = `cat $paramdir/$param`; ++ chomp $tmp; ++ return $tmp; ++} ++ ++# ++# ++sub test_main { ++ ++ print "\nTesting Module Parameters\n"; ++ ++ load_module("") or die; ++ ++ # Test initial values ++ print "\nTesting Default Values\n"; ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ # Test low value ++ print "\nTesting Low Value\n"; ++ my $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} "; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{LOW}); ++ } ++ ++ # Test high value ++ print "\nTesting High Value\n"; ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} "; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{HIGH}); ++ } ++ ++ # Test Enum ++ print "\nTesting Enumerated\n"; ++ foreach (@{$params}) { ++ if (defined $_->{ENUM}) { ++ my $value; ++ foreach $value (@{$_->{ENUM}}) { ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $value); ++ } ++ } ++ } ++ ++ # Test Invalid Values ++ print "\nTesting Invalid Values\n"; ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ print "\nTesting Enumerated\n"; ++ foreach (@{$params}) { ++ if (defined $_->{ENUM}) { ++ my $value; ++ foreach $value (@{$_->{ENUM}}) { ++ $value = $value + 1; ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $_->{DEFAULT}); ++ $value = $value - 2; ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ } ++ } ++ ++ test_status() or die; ++} ++ ++test_main(); ++0; +diff --git a/drivers/usb/host/fh_otg/fh_otg/test/test_sysfs.pl b/drivers/usb/host/fh_otg/fh_otg/test/test_sysfs.pl +new file mode 100755 +index 00000000..0eecbc7f +--- /dev/null ++++ b/drivers/usb/host/fh_otg/fh_otg/test/test_sysfs.pl +@@ -0,0 +1,193 @@ ++#!/usr/bin/perl -w ++# ++# Run this program on the integrator ++# - Tests select sysfs attributes. ++# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc. ++# ----------------------------------------------------------------------------- ++use strict; ++use fh_otg_test; ++ ++check_arch() or die; ++ ++# ++# ++sub test { ++ my ($attr,$expected) = @_; ++ my $string = get($attr); ++ ++ if ($string eq $expected) { ++ printf("$attr = $string, okay\n"); ++ } ++ else { ++ warn "ERROR: value of $attr != $expected, $string\n"; ++ $errors ++; ++ } ++} ++ ++# ++# ++sub set { ++ my ($reg, $value) = @_; ++ system "echo $value > $sysfsdir/$reg"; ++} ++ ++# ++# ++sub get { ++ my $attr = shift; ++ my $string = `cat $sysfsdir/$attr`; ++ chomp $string; ++ if ($string =~ m/\s\=\s/) { ++ my $tmp; ++ ($tmp, $string) = split /\s=\s/, $string; ++ } ++ return $string; ++} ++ ++# ++# ++sub test_main { ++ print("\nTesting Sysfs Attributes\n"); ++ ++ load_module("") or die; ++ ++ # Test initial values of regoffset/regvalue/guid/gsnpsid ++ print("\nTesting Default Values\n"); ++ ++ test("regoffset", "0xffffffff"); ++ test("regvalue", "invalid offset"); ++ test("guid", "0x12345678"); # this will fail if it has been changed ++ test("gsnpsid", "0x4f54200a"); ++ ++ # Test operation of regoffset/regvalue ++ print("\nTesting regoffset\n"); ++ set('regoffset', '5a5a5a5a'); ++ test("regoffset", "0xffffffff"); ++ ++ set('regoffset', '0'); ++ test("regoffset", "0x00000000"); ++ ++ set('regoffset', '40000'); ++ test("regoffset", "0x00000000"); ++ ++ set('regoffset', '3ffff'); ++ test("regoffset", "0x0003ffff"); ++ ++ set('regoffset', '1'); ++ test("regoffset", "0x00000001"); ++ ++ print("\nTesting regvalue\n"); ++ set('regoffset', '3c'); ++ test("regvalue", "0x12345678"); ++ set('regvalue', '5a5a5a5a'); ++ test("regvalue", "0x5a5a5a5a"); ++ set('regvalue','a5a5a5a5'); ++ test("regvalue", "0xa5a5a5a5"); ++ set('guid','12345678'); ++ ++ # Test HNP Capable ++ print("\nTesting HNP Capable bit\n"); ++ set('hnpcapable', '1'); ++ test("hnpcapable", "0x1"); ++ set('hnpcapable','0'); ++ test("hnpcapable", "0x0"); ++ ++ set('regoffset','0c'); ++ ++ my $old = get('gusbcfg'); ++ print("setting hnpcapable\n"); ++ set('hnpcapable', '1'); ++ test("hnpcapable", "0x1"); ++ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9))); ++ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9))); ++ ++ $old = get('gusbcfg'); ++ print("clearing hnpcapable\n"); ++ set('hnpcapable', '0'); ++ test("hnpcapable", "0x0"); ++ test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9))); ++ test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9))); ++ ++ # Test SRP Capable ++ print("\nTesting SRP Capable bit\n"); ++ set('srpcapable', '1'); ++ test("srpcapable", "0x1"); ++ set('srpcapable','0'); ++ test("srpcapable", "0x0"); ++ ++ set('regoffset','0c'); ++ ++ $old = get('gusbcfg'); ++ print("setting srpcapable\n"); ++ set('srpcapable', '1'); ++ test("srpcapable", "0x1"); ++ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8))); ++ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8))); ++ ++ $old = get('gusbcfg'); ++ print("clearing srpcapable\n"); ++ set('srpcapable', '0'); ++ test("srpcapable", "0x0"); ++ test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8))); ++ test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8))); ++ ++ # Test GGPIO ++ print("\nTesting GGPIO\n"); ++ set('ggpio','5a5a5a5a'); ++ test('ggpio','0x5a5a0000'); ++ set('ggpio','a5a5a5a5'); ++ test('ggpio','0xa5a50000'); ++ set('ggpio','11110000'); ++ test('ggpio','0x11110000'); ++ set('ggpio','00001111'); ++ test('ggpio','0x00000000'); ++ ++ # Test DEVSPEED ++ print("\nTesting DEVSPEED\n"); ++ set('regoffset','800'); ++ $old = get('regvalue'); ++ set('devspeed','0'); ++ test('devspeed','0x0'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); ++ set('devspeed','1'); ++ test('devspeed','0x1'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); ++ set('devspeed','2'); ++ test('devspeed','0x2'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2)); ++ set('devspeed','3'); ++ test('devspeed','0x3'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3)); ++ set('devspeed','4'); ++ test('devspeed','0x0'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); ++ set('devspeed','5'); ++ test('devspeed','0x1'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); ++ ++ ++ # mode Returns the current mode:0 for device mode1 for host mode Read ++ # hnp Initiate the Host Negotiation Protocol. Read returns the status. Read/Write ++ # srp Initiate the Session Request Protocol. Read returns the status. Read/Write ++ # buspower Get or Set the Power State of the bus (0 - Off or 1 - On) Read/Write ++ # bussuspend Suspend the USB bus. Read/Write ++ # busconnected Get the connection status of the bus Read ++ ++ # gotgctl Get or set the Core Control Status Register. Read/Write ++ ## gusbcfg Get or set the Core USB Configuration Register Read/Write ++ # grxfsiz Get or set the Receive FIFO Size Register Read/Write ++ # gnptxfsiz Get or set the non-periodic Transmit Size Register Read/Write ++ # gpvndctl Get or set the PHY Vendor Control Register Read/Write ++ ## ggpio Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write ++ ## guid Get or set the value of the User ID Register Read/Write ++ ## gsnpsid Get the value of the Synopsys ID Regester Read ++ ## devspeed Get or set the device speed setting in the DCFG register Read/Write ++ # enumspeed Gets the device enumeration Speed. Read ++ # hptxfsiz Get the value of the Host Periodic Transmit FIFO Read ++ # hprt0 Get or Set the value in the Host Port Control and Status Register Read/Write ++ ++ test_status("TEST NYI") or die; ++} ++ ++test_main(); ++0; +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index f9cf3f04..d08a2708 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1003,7 +1003,7 @@ MODULE_LICENSE ("GPL"); + #define SA1111_DRIVER ohci_hcd_sa1111_driver + #endif + +-#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) ++#ifdef CONFIG_ARCH_S3C64XX + #include "ohci-s3c2410.c" + #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver + #endif +diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c +index 7c9a4d55..7aeb729b 100644 +--- a/drivers/usb/host/ohci-s3c2410.c ++++ b/drivers/usb/host/ohci-s3c2410.c +@@ -21,14 +21,21 @@ + + #include <linux/platform_device.h> + #include <linux/clk.h> +-#include <plat/usb-control.h> ++ ++#include <mach/hardware.h> ++#include <mach/usb-control.h> + + #define valid_port(idx) ((idx) == 1 || (idx) == 2) + ++extern void usb_host_clk_en(void); ++ + /* clock device associated with the hcd */ + + static struct clk *clk; ++ ++#if defined(CONFIG_ARCH_2410) + static struct clk *usb_clk; ++#endif + + /* forward definitions */ + +@@ -47,8 +54,10 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) + + dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); + ++#if defined(CONFIG_ARCH_2410) + clk_enable(usb_clk); + mdelay(2); /* let the bus clock stabilise */ ++#endif + + clk_enable(clk); + +@@ -56,8 +65,9 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) + info->hcd = hcd; + info->report_oc = s3c2410_hcd_oc; + +- if (info->enable_oc != NULL) ++ if (info->enable_oc != NULL) { + (info->enable_oc)(info, 1); ++ } + } + } + +@@ -71,12 +81,15 @@ static void s3c2410_stop_hc(struct platform_device *dev) + info->report_oc = NULL; + info->hcd = NULL; + +- if (info->enable_oc != NULL) ++ if (info->enable_oc != NULL) { + (info->enable_oc)(info, 0); ++ } + } + + clk_disable(clk); ++#if defined(CONFIG_ARCH_2410) + clk_disable(usb_clk); ++#endif + } + + /* ohci_s3c2410_hub_status_data +@@ -86,14 +99,14 @@ static void s3c2410_stop_hc(struct platform_device *dev) + */ + + static int +-ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf) ++ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf) + { + struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); + struct s3c2410_hcd_port *port; + int orig; + int portno; + +- orig = ohci_hub_status_data(hcd, buf); ++ orig = ohci_hub_status_data (hcd, buf); + + if (info == NULL) + return orig; +@@ -143,7 +156,7 @@ static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info, + * request. + */ + +-static int ohci_s3c2410_hub_control( ++static int ohci_s3c2410_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, +@@ -197,8 +210,9 @@ static int ohci_s3c2410_hub_control( + dev_dbg(hcd->self.controller, + "ClearPortFeature: OVER_CURRENT\n"); + +- if (valid_port(wIndex)) ++ if (valid_port(wIndex)) { + info->port[wIndex-1].oc_status = 0; ++ } + + goto out; + +@@ -239,11 +253,8 @@ static int ohci_s3c2410_hub_control( + desc->wHubCharacteristics |= cpu_to_le16(0x0001); + + if (info->enable_oc) { +- desc->wHubCharacteristics &= ~cpu_to_le16( +- HUB_CHAR_OCPM); +- desc->wHubCharacteristics |= cpu_to_le16( +- 0x0008 | +- 0x0001); ++ desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); ++ desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001); + } + + dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", +@@ -257,11 +268,13 @@ static int ohci_s3c2410_hub_control( + dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); + + if (valid_port(wIndex)) { +- if (info->port[wIndex-1].oc_changed) ++ if (info->port[wIndex-1].oc_changed) { + *data |= cpu_to_le32(RH_PS_OCIC); ++ } + +- if (info->port[wIndex-1].oc_status) ++ if (info->port[wIndex-1].oc_status) { + *data |= cpu_to_le32(RH_PS_POCI); ++ } + } + } + +@@ -319,7 +332,7 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) + */ + + static void +-usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) ++usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) + { + usb_remove_hcd(hcd); + s3c2410_stop_hc(dev); +@@ -337,12 +350,16 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) + * through the hotplug entry's driver_data. + * + */ +-static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, ++static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, + struct platform_device *dev) + { + struct usb_hcd *hcd = NULL; + int retval; + ++#if !defined(CONFIG_ARCH_2410) ++ usb_host_clk_en(); ++#endif ++ + s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); + s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); + +@@ -351,7 +368,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, + return -ENOMEM; + + hcd->rsrc_start = dev->resource[0].start; +- hcd->rsrc_len = resource_size(&dev->resource[0]); ++ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + dev_err(&dev->dev, "request_mem_region failed\n"); +@@ -362,16 +379,18 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, + clk = clk_get(&dev->dev, "usb-host"); + if (IS_ERR(clk)) { + dev_err(&dev->dev, "cannot get usb-host clock\n"); +- retval = PTR_ERR(clk); ++ retval = -ENOENT; + goto err_mem; + } + ++#if defined(CONFIG_ARCH_2410) + usb_clk = clk_get(&dev->dev, "usb-bus-host"); + if (IS_ERR(usb_clk)) { +- dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); +- retval = PTR_ERR(usb_clk); ++ dev_err(&dev->dev, "cannot get usb-host clock\n"); ++ retval = -ENOENT; + goto err_clk; + } ++#endif + + s3c2410_start_hc(dev, hcd); + +@@ -393,10 +412,13 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, + err_ioremap: + s3c2410_stop_hc(dev); + iounmap(hcd->regs); ++ ++#if defined(CONFIG_ARCH_2410) + clk_put(usb_clk); + + err_clk: + clk_put(clk); ++#endif + + err_mem: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +@@ -409,19 +431,17 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, + /*-------------------------------------------------------------------------*/ + + static int +-ohci_s3c2410_start(struct usb_hcd *hcd) ++ohci_s3c2410_start (struct usb_hcd *hcd) + { +- struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + +- ret = ohci_init(ohci); +- if (ret < 0) ++ if ((ret = ohci_init(ohci)) < 0) + return ret; + +- ret = ohci_run(ohci); +- if (ret < 0) { +- err("can't start %s", hcd->self.bus_name); +- ohci_stop(hcd); ++ if ((ret = ohci_run (ohci)) < 0) { ++ err ("can't start %s", hcd->self.bus_name); ++ ohci_stop (hcd); + return ret; + } + +@@ -473,12 +493,12 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { + + /* device driver */ + +-static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) ++static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) + { + return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); + } + +-static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) ++static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) + { + struct usb_hcd *hcd = platform_get_drvdata(pdev); + +@@ -488,7 +508,7 @@ static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) + + static struct platform_driver ohci_hcd_s3c2410_driver = { + .probe = ohci_hcd_s3c2410_drv_probe, +- .remove = __devexit_p(ohci_hcd_s3c2410_drv_remove), ++ .remove = ohci_hcd_s3c2410_drv_remove, + .shutdown = usb_hcd_platform_shutdown, + /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ + /*.resume = ohci_hcd_s3c2410_drv_resume, */ +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index 21d816e9..673ee6b0 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -606,7 +606,14 @@ config HP_WATCHDOG + will only load on an HP ProLiant system with a minimum of iLO2 support. + To compile this driver as a module, choose M here: the module will be + called hpwdt. +- ++ ++config FH_WATCHDOG ++ tristate "fullhan watchdog driver" ++ ++ help ++ A software monitoring watchdog and NMI sourcing driver. ++ ++ + config HPWDT_NMI_DECODING + bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" + depends on HP_WATCHDOG +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index ed26f709..0cb0e134 100644 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o + obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o + obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o + obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o ++obj-$(CONFIG_FH_WATCHDOG) += fh_wdt.o + + # AVR32 Architecture + obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o +diff --git a/drivers/watchdog/fh_wdt.c b/drivers/watchdog/fh_wdt.c +new file mode 100644 +index 00000000..17ff23c5 +--- /dev/null ++++ b/drivers/watchdog/fh_wdt.c +@@ -0,0 +1,501 @@ ++/* ++ * Copyright 2010-2011 Picochip Ltd., Jamie Iles ++ * http://www.picochip.com ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * This file implements a driver for the Synopsys DesignWare watchdog device ++ * in the many ARM subsystems. The watchdog has 16 different timeout periods ++ * and these are a function of the input clock frequency. ++ * ++ * The DesignWare watchdog cannot be stopped once it has been started so we ++ * use a software timer to implement a ping that will keep the watchdog alive. ++ * If we receive an expected close for the watchdog then we keep the timer ++ * running, otherwise the timer is stopped and the watchdog will expire. ++ */ ++#define pr_fmt(fmt) "fh_wdt: " fmt ++ ++#include <linux/bitops.h> ++#include <linux/clk.h> ++#include <linux/device.h> ++#include <linux/err.h> ++#include <linux/fs.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/miscdevice.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/pm.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/timer.h> ++#include <linux/uaccess.h> ++#include <linux/watchdog.h> ++#include <linux/interrupt.h> ++#include <mach/pmu.h> ++#include <mach/fh_wdt.h> ++ ++#define WDT_RESPONSE_MODE ++ ++#define WDT_TIMER_MODE ++ ++#ifndef WDT_TIMER_MODE ++#define WDT_NOTIMER_MODE ++#endif ++ ++#define WDOG_CONTROL_REG_OFFSET 0x00 ++#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 ++#define WDOG_CONTROL_REG_RMOD_MASK 0x02 ++#define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 ++#define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 ++#define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c ++#define WDOG_COUNTER_RESTART_KICK_VALUE 0x76 ++ ++/* Hardware timeout in seconds */ ++#define WDT_HW_TIMEOUT 2 ++/* User land timeout */ ++#define WDT_HEARTBEAT 15 ++static int heartbeat = WDT_HEARTBEAT; ++ ++/* The maximum TOP (timeout period) value that can be set in the watchdog. */ ++#define FH_WDT_MAX_TOP 15 ++ ++static int curr_clk_rate; ++static int nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " ++ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++#define WDT_TIMEOUT (HZ / 2) ++ ++struct fh_wdt_t fh_wdt; ++ ++static inline int fh_wdt_is_enabled(void) ++{ ++ return readl(fh_wdt.regs + WDOG_CONTROL_REG_OFFSET) & ++ WDOG_CONTROL_REG_WDT_EN_MASK; ++} ++ ++#define WDT_CLOCK clk_get_rate(fh_wdt.clk) ++ ++static inline int fh_wdt_top_in_seconds(unsigned top) ++{ ++ /* ++ * There are 16 possible timeout values in 0..15 where the number of ++ * cycles is 2 ^ (16 + i) and the watchdog counts down. ++ */ ++ return (1 << (16 + top)) / WDT_CLOCK; ++} ++ ++static inline void fh_wdt_set_next_heartbeat(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fh_wdt.lock, flags); ++ fh_wdt.next_heartbeat = jiffies + heartbeat * HZ; ++ spin_unlock_irqrestore(&fh_wdt.lock, flags); ++} ++ ++static int fh_wdt_set_top(unsigned top_s) ++{ ++ int i, val, top_val = FH_WDT_MAX_TOP; ++ unsigned long flags; ++ /* ++ * Iterate over the timeout values until we find the closest match. We ++ * always look for >=. ++ */ ++ spin_lock_irqsave(&fh_wdt.lock, flags); ++ for (i = 0; i <= FH_WDT_MAX_TOP; ++i) ++ if (fh_wdt_top_in_seconds(i) >= top_s) { ++ top_val = i; ++ break; ++ } ++ ++ /* Set the new value in the watchdog. */ ++ printk("[wdt] set topval: %d", top_val); ++ writel(top_val, fh_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); ++ ++ fh_wdt_set_next_heartbeat(); ++ ++ val = fh_wdt_top_in_seconds(top_val); ++ spin_unlock_irqrestore(&fh_wdt.lock, flags); ++ return val; ++} ++ ++#ifndef WDT_TIMER_MODE ++static int fh_wdt_get_top(void) ++{ ++ unsigned int val; ++ ++ val = readl(fh_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); ++ val = (1 << (16 + val)) / WDT_CLOCK; ++ return val; ++} ++#endif ++ ++static void fh_wdt_keepalive(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fh_wdt.lock, flags); ++ writel(WDOG_COUNTER_RESTART_KICK_VALUE, fh_wdt.regs + ++ WDOG_COUNTER_RESTART_REG_OFFSET); ++ spin_unlock_irqrestore(&fh_wdt.lock, flags); ++} ++ ++static void fh_wdt_ping(unsigned long data) ++{ ++ if (time_before(jiffies, fh_wdt.next_heartbeat) || ++ (!nowayout && !fh_wdt.in_use)) { ++ fh_wdt_keepalive(); ++ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT); ++ } else ++ pr_crit("keepalive missed, machine will reset\n"); ++} ++ ++static int fh_wdt_open(struct inode *inode, struct file *filp) ++{ ++ unsigned long flags; ++ ++ if (test_and_set_bit(0, &fh_wdt.in_use)) ++ return -EBUSY; ++ ++ /* Make sure we don't get unloaded. */ ++ __module_get(THIS_MODULE); ++ ++ spin_lock_irqsave(&fh_wdt.lock, flags); ++ ++ if(fh_wdt.plat_data && fh_wdt.plat_data->resume) ++ fh_wdt.plat_data->resume(); ++ ++ fh_wdt_set_top(WDT_HW_TIMEOUT); ++ if (!fh_wdt_is_enabled()) ++ { ++ /* ++ * The watchdog is not currently enabled. Set the timeout to ++ * the maximum and then start it. ++ */ ++ u32 value; ++ value = WDOG_CONTROL_REG_WDT_EN_MASK; ++#ifdef WDT_RESPONSE_MODE ++ value |= WDOG_CONTROL_REG_RMOD_MASK; ++#endif ++ writel(value, fh_wdt.regs + WDOG_CONTROL_REG_OFFSET); ++ fh_wdt_keepalive(); ++ } ++#ifdef WDT_TIMER_MODE ++ fh_wdt_set_next_heartbeat(); ++#else ++ del_timer(&fh_wdt.timer); ++#endif ++ spin_unlock_irqrestore(&fh_wdt.lock, flags); ++ ++ return nonseekable_open(inode, filp); ++} ++ ++ssize_t fh_wdt_write(struct file *filp, const char __user *buf, size_t len, ++ loff_t *offset) ++{ ++ if (!len) ++ return 0; ++ ++ if (!nowayout) { ++ size_t i; ++ ++ fh_wdt.expect_close = 0; ++ ++ for (i = 0; i < len; ++i) { ++ char c; ++ ++ if (get_user(c, buf + i)) ++ return -EFAULT; ++ ++ if (c == 'V') { ++ fh_wdt.expect_close = 1; ++ break; ++ } ++ } ++ } ++ ++ fh_wdt_set_next_heartbeat(); ++ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT); ++ ++ return len; ++} ++ ++#ifndef WDT_TIMER_MODE ++static u32 fh_wdt_time_left(void) ++{ ++ return readl(fh_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) / ++ WDT_CLOCK; ++} ++#endif ++ ++static const struct watchdog_info fh_wdt_ident = { ++ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | ++ WDIOF_MAGICCLOSE, ++ .identity = "Synopsys DesignWare Watchdog", ++}; ++ ++static long fh_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ unsigned long val; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ return copy_to_user((struct watchdog_info *)arg, &fh_wdt_ident, ++ sizeof(fh_wdt_ident)) ? -EFAULT : 0; ++ ++ case WDIOC_GETSTATUS: ++ case WDIOC_GETBOOTSTATUS: ++ return put_user(0, (int *)arg); ++ ++ case WDIOC_KEEPALIVE: ++#ifdef WDT_TIMER_MODE ++ fh_wdt_set_next_heartbeat(); ++#else ++ fh_wdt_keepalive(); ++#endif ++ return 0; ++ ++ case WDIOC_SETTIMEOUT: ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++#ifdef WDT_TIMER_MODE ++ pr_debug("[wdt] settime value %lu", val); ++ heartbeat = val; ++ fh_wdt_keepalive(); ++ fh_wdt_set_next_heartbeat(); ++#else ++ fh_wdt_set_top(val); ++ fh_wdt_keepalive(); ++#endif ++ return put_user(val , (int __user *)arg); ++ ++ case WDIOC_GETTIMEOUT: ++#ifdef WDT_TIMER_MODE ++ return put_user(heartbeat, (int __user *)arg); ++#else ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ return put_user(fh_wdt_time_left(), (int __user *)arg); ++#endif ++ ++ case WDIOC_GETTIMELEFT: ++#ifdef WDT_TIMER_MODE ++ val = (fh_wdt.next_heartbeat - fh_wdt.timer.expires) / HZ; ++ return put_user(val, (int __user *)arg); ++#else ++ /* Get the time left in hardware if use hardware-mode*/ ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ return put_user(fh_wdt_get_top(), (int __user *)arg); ++#endif ++ ++ case WDIOC_SETOPTIONS: ++ if (get_user(val, (int __user *)arg)) ++ return -EFAULT; ++ ++ if (val & WDIOS_DISABLECARD) { ++ if(fh_wdt.plat_data && fh_wdt.plat_data->pause) ++ fh_wdt.plat_data->pause(); ++ else ++ return -EPERM; ++ } ++ ++ if (val & WDIOS_ENABLECARD) { ++ if(fh_wdt.plat_data && fh_wdt.plat_data->resume) ++ fh_wdt.plat_data->resume(); ++ else ++ return -EPERM; ++ } ++ ++ return 0; ++ ++ default: ++ return -ENOTTY; ++ } ++} ++ ++#ifdef WDT_RESPONSE_MODE ++static irqreturn_t fh_wdt_interrupt(int this_irq, void *dev_id) ++{ ++ struct fh_wdt_t *fh_wdt = (struct fh_wdt_t *)dev_id; ++ ++ if (fh_wdt && fh_wdt->plat_data->intr) ++ return fh_wdt->plat_data->intr(fh_wdt); ++ else ++ return IRQ_HANDLED; ++} ++#endif ++ ++static int fh_wdt_release(struct inode *inode, struct file *filp) ++{ ++ clear_bit(0, &fh_wdt.in_use); ++#ifdef WDT_TIMER_MODE ++ if (!fh_wdt.expect_close) { ++ del_timer(&fh_wdt.timer); ++ if (!nowayout) ++ pr_crit("unexpected close, system will reboot soon\n"); ++ else ++ pr_crit("watchdog cannot be disabled, system will reboot soon\n"); ++ } ++ ++ fh_wdt.expect_close = 0; ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int fh_wdt_suspend(struct device *dev) ++{ ++ clk_disable(fh_wdt.clk); ++ writel(FH_WDT_MAX_TOP, fh_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); ++ curr_clk_rate = WDT_CLOCK; ++ fh_wdt_keepalive(); ++ ++ return 0; ++} ++ ++static int fh_wdt_resume(struct device *dev) ++{ ++ int err; ++ ++ clk_set_rate(fh_wdt.clk, curr_clk_rate); ++ err = clk_enable(fh_wdt.clk); ++ ++ if (err) ++ { ++ pr_err("an error occured during wdt resume, error no: %d\n", err); ++ return err; ++ } ++ ++ fh_wdt_keepalive(); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops fh_wdt_pm_ops = { ++ .suspend = fh_wdt_suspend, ++ .resume = fh_wdt_resume, ++}; ++#endif /* CONFIG_PM */ ++ ++static const struct file_operations wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .open = fh_wdt_open, ++ .write = fh_wdt_write, ++ .unlocked_ioctl = fh_wdt_ioctl, ++ .release = fh_wdt_release ++}; ++ ++static struct miscdevice fh_wdt_miscdev = { ++ .fops = &wdt_fops, ++ .name = "watchdog", ++ .minor = WATCHDOG_MINOR, ++}; ++ ++static int __devinit fh_wdt_drv_probe(struct platform_device *pdev) ++{ ++ int ret, irq; ++ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (!mem) ++ return -EINVAL; ++ ++ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), ++ "fh_wdt")) ++ return -ENOMEM; ++ ++ fh_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); ++ if (!fh_wdt.regs) ++ return -ENOMEM; ++#ifdef WDT_RESPONSE_MODE ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "no irq resource\n"); ++ return -ENXIO; ++ } ++ ++ ret = request_irq(irq, fh_wdt_interrupt, IRQF_DISABLED,\ ++ dev_name(&pdev->dev), ++ &fh_wdt); ++ if (ret) { ++ dev_err(&pdev->dev, "failure requesting irq %i\n", irq); ++ return -ENXIO; ++ } ++#endif ++ ++ fh_wdt.plat_data = dev_get_platdata(&pdev->dev); ++ fh_wdt.clk = clk_get( NULL,"wdt_clk"); ++ if (IS_ERR(fh_wdt.clk)) ++ return PTR_ERR(fh_wdt.clk); ++ ++ clk_set_rate(fh_wdt.clk, 1000000); ++ ++ ret = clk_enable(fh_wdt.clk); ++ if (ret) ++ goto out_put_clk; ++ ++ spin_lock_init(&fh_wdt.lock); ++ ++ ret = misc_register(&fh_wdt_miscdev); ++ if (ret) ++ goto out_disable_clk; ++ ++ fh_wdt_set_next_heartbeat(); ++ setup_timer(&fh_wdt.timer, fh_wdt_ping, 0); ++ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT); ++ ++ return 0; ++ ++out_disable_clk: ++ clk_disable(fh_wdt.clk); ++out_put_clk: ++ clk_put(fh_wdt.clk); ++ ++ return ret; ++} ++ ++static int __devexit fh_wdt_drv_remove(struct platform_device *pdev) ++{ ++ misc_deregister(&fh_wdt_miscdev); ++ ++ clk_disable(fh_wdt.clk); ++ clk_put(fh_wdt.clk); ++ ++ return 0; ++} ++ ++static struct platform_driver fh_wdt_driver = { ++ .probe = fh_wdt_drv_probe, ++ .remove = __devexit_p(fh_wdt_drv_remove), ++ .driver = { ++ .name = "fh_wdt", ++ .owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .pm = &fh_wdt_pm_ops, ++#endif /* CONFIG_PM */ ++ }, ++}; ++ ++static int __init fh_wdt_watchdog_init(void) ++{ ++ return platform_driver_register(&fh_wdt_driver); ++} ++module_init(fh_wdt_watchdog_init); ++ ++static void __exit fh_wdt_watchdog_exit(void) ++{ ++ platform_driver_unregister(&fh_wdt_driver); ++} ++module_exit(fh_wdt_watchdog_exit); ++ ++MODULE_AUTHOR("fullhan"); ++MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff --git a/fs/Kconfig b/fs/Kconfig +index 19891aab..77c5e665 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -192,6 +192,7 @@ source "fs/hfsplus/Kconfig" + source "fs/befs/Kconfig" + source "fs/bfs/Kconfig" + source "fs/efs/Kconfig" ++source "fs/yaffs2/Kconfig" + source "fs/jffs2/Kconfig" + # UBIFS File system configuration + source "fs/ubifs/Kconfig" +diff --git a/fs/Kconfig.pre.yaffs b/fs/Kconfig.pre.yaffs +new file mode 100644 +index 00000000..19891aab +--- /dev/null ++++ b/fs/Kconfig.pre.yaffs +@@ -0,0 +1,273 @@ ++# ++# File system configuration ++# ++ ++menu "File systems" ++ ++if BLOCK ++ ++source "fs/ext2/Kconfig" ++source "fs/ext3/Kconfig" ++source "fs/ext4/Kconfig" ++ ++config FS_XIP ++# execute in place ++ bool ++ depends on EXT2_FS_XIP ++ default y ++ ++source "fs/jbd/Kconfig" ++source "fs/jbd2/Kconfig" ++ ++config FS_MBCACHE ++# Meta block cache for Extended Attributes (ext2/ext3/ext4) ++ tristate ++ default y if EXT2_FS=y && EXT2_FS_XATTR ++ default y if EXT3_FS=y && EXT3_FS_XATTR ++ default y if EXT4_FS=y && EXT4_FS_XATTR ++ default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR ++ ++source "fs/reiserfs/Kconfig" ++source "fs/jfs/Kconfig" ++ ++source "fs/xfs/Kconfig" ++source "fs/gfs2/Kconfig" ++source "fs/ocfs2/Kconfig" ++source "fs/btrfs/Kconfig" ++source "fs/nilfs2/Kconfig" ++ ++endif # BLOCK ++ ++# Posix ACL utility routines ++# ++# Note: Posix ACLs can be implemented without these helpers. Never use ++# this symbol for ifdefs in core code. ++# ++config FS_POSIX_ACL ++ def_bool n ++ ++config EXPORTFS ++ tristate ++ ++config FILE_LOCKING ++ bool "Enable POSIX file locking API" if EXPERT ++ default y ++ help ++ This option enables standard file locking support, required ++ for filesystems like NFS and for the flock() system ++ call. Disabling this option saves about 11k. ++ ++source "fs/notify/Kconfig" ++ ++source "fs/quota/Kconfig" ++ ++source "fs/autofs4/Kconfig" ++source "fs/fuse/Kconfig" ++ ++config CUSE ++ tristate "Character device in Userspace support" ++ depends on FUSE_FS ++ help ++ This FUSE extension allows character devices to be ++ implemented in userspace. ++ ++ If you want to develop or use userspace character device ++ based on CUSE, answer Y or M. ++ ++config GENERIC_ACL ++ bool ++ select FS_POSIX_ACL ++ ++menu "Caches" ++ ++source "fs/fscache/Kconfig" ++source "fs/cachefiles/Kconfig" ++ ++endmenu ++ ++if BLOCK ++menu "CD-ROM/DVD Filesystems" ++ ++source "fs/isofs/Kconfig" ++source "fs/udf/Kconfig" ++ ++endmenu ++endif # BLOCK ++ ++if BLOCK ++menu "DOS/FAT/NT Filesystems" ++ ++source "fs/fat/Kconfig" ++source "fs/ntfs/Kconfig" ++ ++endmenu ++endif # BLOCK ++ ++menu "Pseudo filesystems" ++ ++source "fs/proc/Kconfig" ++source "fs/sysfs/Kconfig" ++ ++config TMPFS ++ bool "Virtual memory file system support (former shm fs)" ++ depends on SHMEM ++ help ++ Tmpfs is a file system which keeps all files in virtual memory. ++ ++ Everything in tmpfs is temporary in the sense that no files will be ++ created on your hard drive. The files live in memory and swap ++ space. If you unmount a tmpfs instance, everything stored therein is ++ lost. ++ ++ See <file:Documentation/filesystems/tmpfs.txt> for details. ++ ++config TMPFS_POSIX_ACL ++ bool "Tmpfs POSIX Access Control Lists" ++ depends on TMPFS ++ select TMPFS_XATTR ++ select GENERIC_ACL ++ help ++ POSIX Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the POSIX ACLs for ++ Linux website <http://acl.bestbits.at/>. ++ ++ If you don't know what Access Control Lists are, say N. ++ ++config TMPFS_XATTR ++ bool "Tmpfs extended attributes" ++ depends on TMPFS ++ default n ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ <http://acl.bestbits.at/> for details). ++ ++ Currently this enables support for the trusted.* and ++ security.* namespaces. ++ ++ You need this for POSIX ACL support on tmpfs. ++ ++ If unsure, say N. ++ ++config HUGETLBFS ++ bool "HugeTLB file system support" ++ depends on X86 || IA64 || SPARC64 || (S390 && 64BIT) || \ ++ SYS_SUPPORTS_HUGETLBFS || BROKEN ++ help ++ hugetlbfs is a filesystem backing for HugeTLB pages, based on ++ ramfs. For architectures that support it, say Y here and read ++ <file:Documentation/vm/hugetlbpage.txt> for details. ++ ++ If unsure, say N. ++ ++config HUGETLB_PAGE ++ def_bool HUGETLBFS ++ ++source "fs/configfs/Kconfig" ++ ++endmenu ++ ++menuconfig MISC_FILESYSTEMS ++ bool "Miscellaneous filesystems" ++ default y ++ ---help--- ++ Say Y here to get to see options for various miscellaneous ++ filesystems, such as filesystems that came from other ++ operating systems. ++ ++ This option alone does not add any kernel code. ++ ++ If you say N, all options in this submenu will be skipped and ++ disabled; if unsure, say Y here. ++ ++if MISC_FILESYSTEMS ++ ++source "fs/adfs/Kconfig" ++source "fs/affs/Kconfig" ++source "fs/ecryptfs/Kconfig" ++source "fs/hfs/Kconfig" ++source "fs/hfsplus/Kconfig" ++source "fs/befs/Kconfig" ++source "fs/bfs/Kconfig" ++source "fs/efs/Kconfig" ++source "fs/jffs2/Kconfig" ++# UBIFS File system configuration ++source "fs/ubifs/Kconfig" ++source "fs/logfs/Kconfig" ++source "fs/cramfs/Kconfig" ++source "fs/squashfs/Kconfig" ++source "fs/freevxfs/Kconfig" ++source "fs/minix/Kconfig" ++source "fs/omfs/Kconfig" ++source "fs/hpfs/Kconfig" ++source "fs/qnx4/Kconfig" ++source "fs/romfs/Kconfig" ++source "fs/pstore/Kconfig" ++source "fs/sysv/Kconfig" ++source "fs/ufs/Kconfig" ++source "fs/exofs/Kconfig" ++ ++endif # MISC_FILESYSTEMS ++ ++menuconfig NETWORK_FILESYSTEMS ++ bool "Network File Systems" ++ default y ++ depends on NET ++ ---help--- ++ Say Y here to get to see options for network filesystems and ++ filesystem-related networking code, such as NFS daemon and ++ RPCSEC security modules. ++ ++ This option alone does not add any kernel code. ++ ++ If you say N, all options in this submenu will be skipped and ++ disabled; if unsure, say Y here. ++ ++if NETWORK_FILESYSTEMS ++ ++source "fs/nfs/Kconfig" ++source "fs/nfsd/Kconfig" ++ ++config LOCKD ++ tristate ++ depends on FILE_LOCKING ++ ++config LOCKD_V4 ++ bool ++ depends on NFSD_V3 || NFS_V3 ++ depends on FILE_LOCKING ++ default y ++ ++config NFS_ACL_SUPPORT ++ tristate ++ select FS_POSIX_ACL ++ ++config NFS_COMMON ++ bool ++ depends on NFSD || NFS_FS ++ default y ++ ++source "net/sunrpc/Kconfig" ++source "fs/ceph/Kconfig" ++source "fs/cifs/Kconfig" ++source "fs/ncpfs/Kconfig" ++source "fs/coda/Kconfig" ++source "fs/afs/Kconfig" ++source "fs/9p/Kconfig" ++ ++endif # NETWORK_FILESYSTEMS ++ ++if BLOCK ++menu "Partition Types" ++ ++source "fs/partitions/Kconfig" ++ ++endmenu ++endif ++ ++source "fs/nls/Kconfig" ++source "fs/dlm/Kconfig" ++ ++endmenu +diff --git a/fs/Makefile b/fs/Makefile +index fb68c2b8..dbd3eb7e 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -124,3 +124,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/ + obj-$(CONFIG_EXOFS_FS) += exofs/ + obj-$(CONFIG_CEPH_FS) += ceph/ + obj-$(CONFIG_PSTORE) += pstore/ ++obj-$(CONFIG_YAFFS_FS) += yaffs2/ +diff --git a/fs/Makefile.pre.yaffs b/fs/Makefile.pre.yaffs +new file mode 100644 +index 00000000..fb68c2b8 +--- /dev/null ++++ b/fs/Makefile.pre.yaffs +@@ -0,0 +1,126 @@ ++# ++# Makefile for the Linux filesystems. ++# ++# 14 Sep 2000, Christoph Hellwig <hch@infradead.org> ++# Rewritten to use lists instead of if-statements. ++# ++ ++obj-y := open.o read_write.o file_table.o super.o \ ++ char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ ++ ioctl.o readdir.o select.o fifo.o dcache.o inode.o \ ++ attr.o bad_inode.o file.o filesystems.o namespace.o \ ++ seq_file.o xattr.o libfs.o fs-writeback.o \ ++ pnode.o drop_caches.o splice.o sync.o utimes.o \ ++ stack.o fs_struct.o statfs.o ++ ++ifeq ($(CONFIG_BLOCK),y) ++obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o ++else ++obj-y += no-block.o ++endif ++ ++obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o ++obj-y += notify/ ++obj-$(CONFIG_EPOLL) += eventpoll.o ++obj-$(CONFIG_ANON_INODES) += anon_inodes.o ++obj-$(CONFIG_SIGNALFD) += signalfd.o ++obj-$(CONFIG_TIMERFD) += timerfd.o ++obj-$(CONFIG_EVENTFD) += eventfd.o ++obj-$(CONFIG_AIO) += aio.o ++obj-$(CONFIG_FILE_LOCKING) += locks.o ++obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o ++obj-$(CONFIG_NFSD_DEPRECATED) += nfsctl.o ++obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o ++obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o ++obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o ++ ++# binfmt_script is always there ++obj-y += binfmt_script.o ++ ++obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o ++obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o ++obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o ++obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o ++obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o ++ ++obj-$(CONFIG_FS_MBCACHE) += mbcache.o ++obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o ++obj-$(CONFIG_NFS_COMMON) += nfs_common/ ++obj-$(CONFIG_GENERIC_ACL) += generic_acl.o ++ ++obj-$(CONFIG_FHANDLE) += fhandle.o ++ ++obj-y += quota/ ++ ++obj-$(CONFIG_PROC_FS) += proc/ ++obj-y += partitions/ ++obj-$(CONFIG_SYSFS) += sysfs/ ++obj-$(CONFIG_CONFIGFS_FS) += configfs/ ++obj-y += devpts/ ++ ++obj-$(CONFIG_PROFILING) += dcookies.o ++obj-$(CONFIG_DLM) += dlm/ ++ ++# Do not add any filesystems before this line ++obj-$(CONFIG_FSCACHE) += fscache/ ++obj-$(CONFIG_REISERFS_FS) += reiserfs/ ++obj-$(CONFIG_EXT3_FS) += ext3/ # Before ext2 so root fs can be ext3 ++obj-$(CONFIG_EXT2_FS) += ext2/ ++# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2 ++# unless explicitly requested by rootfstype ++obj-$(CONFIG_EXT4_FS) += ext4/ ++obj-$(CONFIG_JBD) += jbd/ ++obj-$(CONFIG_JBD2) += jbd2/ ++obj-$(CONFIG_CRAMFS) += cramfs/ ++obj-$(CONFIG_SQUASHFS) += squashfs/ ++obj-y += ramfs/ ++obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ ++obj-$(CONFIG_CODA_FS) += coda/ ++obj-$(CONFIG_MINIX_FS) += minix/ ++obj-$(CONFIG_FAT_FS) += fat/ ++obj-$(CONFIG_BFS_FS) += bfs/ ++obj-$(CONFIG_ISO9660_FS) += isofs/ ++obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ ++obj-$(CONFIG_HFS_FS) += hfs/ ++obj-$(CONFIG_ECRYPT_FS) += ecryptfs/ ++obj-$(CONFIG_VXFS_FS) += freevxfs/ ++obj-$(CONFIG_NFS_FS) += nfs/ ++obj-$(CONFIG_EXPORTFS) += exportfs/ ++obj-$(CONFIG_NFSD) += nfsd/ ++obj-$(CONFIG_LOCKD) += lockd/ ++obj-$(CONFIG_NLS) += nls/ ++obj-$(CONFIG_SYSV_FS) += sysv/ ++obj-$(CONFIG_CIFS) += cifs/ ++obj-$(CONFIG_NCP_FS) += ncpfs/ ++obj-$(CONFIG_HPFS_FS) += hpfs/ ++obj-$(CONFIG_NTFS_FS) += ntfs/ ++obj-$(CONFIG_UFS_FS) += ufs/ ++obj-$(CONFIG_EFS_FS) += efs/ ++obj-$(CONFIG_JFFS2_FS) += jffs2/ ++obj-$(CONFIG_LOGFS) += logfs/ ++obj-$(CONFIG_UBIFS_FS) += ubifs/ ++obj-$(CONFIG_AFFS_FS) += affs/ ++obj-$(CONFIG_ROMFS_FS) += romfs/ ++obj-$(CONFIG_QNX4FS_FS) += qnx4/ ++obj-$(CONFIG_AUTOFS4_FS) += autofs4/ ++obj-$(CONFIG_ADFS_FS) += adfs/ ++obj-$(CONFIG_FUSE_FS) += fuse/ ++obj-$(CONFIG_UDF_FS) += udf/ ++obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ ++obj-$(CONFIG_OMFS_FS) += omfs/ ++obj-$(CONFIG_JFS_FS) += jfs/ ++obj-$(CONFIG_XFS_FS) += xfs/ ++obj-$(CONFIG_9P_FS) += 9p/ ++obj-$(CONFIG_AFS_FS) += afs/ ++obj-$(CONFIG_NILFS2_FS) += nilfs2/ ++obj-$(CONFIG_BEFS_FS) += befs/ ++obj-$(CONFIG_HOSTFS) += hostfs/ ++obj-$(CONFIG_HPPFS) += hppfs/ ++obj-$(CONFIG_CACHEFILES) += cachefiles/ ++obj-$(CONFIG_DEBUG_FS) += debugfs/ ++obj-$(CONFIG_OCFS2_FS) += ocfs2/ ++obj-$(CONFIG_BTRFS_FS) += btrfs/ ++obj-$(CONFIG_GFS2_FS) += gfs2/ ++obj-$(CONFIG_EXOFS_FS) += exofs/ ++obj-$(CONFIG_CEPH_FS) += ceph/ ++obj-$(CONFIG_PSTORE) += pstore/ +diff --git a/fs/yaffs2/Kconfig b/fs/yaffs2/Kconfig +new file mode 100755 +index 00000000..658feea5 +--- /dev/null ++++ b/fs/yaffs2/Kconfig +@@ -0,0 +1,161 @@ ++# ++# yaffs file system configurations ++# ++ ++config YAFFS_FS ++ tristate "yaffs2 file system support" ++ default n ++ depends on MTD_BLOCK ++ select YAFFS_YAFFS1 ++ select YAFFS_YAFFS2 ++ help ++ yaffs2, or Yet Another Flash File System, is a file system ++ optimised for NAND Flash chips. ++ ++ To compile the yaffs2 file system support as a module, choose M ++ here: the module will be called yaffs2. ++ ++ If unsure, say N. ++ ++ Further information on yaffs2 is available at ++ <http://www.aleph1.co.uk/yaffs/>. ++ ++config YAFFS_YAFFS1 ++ bool "512 byte / page devices" ++ depends on YAFFS_FS ++ default y ++ help ++ Enable yaffs1 support -- yaffs for 512 byte / page devices ++ ++ Not needed for 2K-page devices. ++ ++ If unsure, say Y. ++ ++config YAFFS_9BYTE_TAGS ++ bool "Use older-style on-NAND data format with pageStatus byte" ++ depends on YAFFS_YAFFS1 ++ default n ++ help ++ ++ Older-style on-NAND data format has a "pageStatus" byte to record ++ chunk/page state. This byte is zero when the page is discarded. ++ Choose this option if you have existing on-NAND data using this ++ format that you need to continue to support. New data written ++ also uses the older-style format. Note: Use of this option ++ generally requires that MTD's oob layout be adjusted to use the ++ older-style format. See notes on tags formats and MTD versions ++ in yaffs_mtdif1.c. ++ ++ If unsure, say N. ++ ++config YAFFS_DOES_ECC ++ bool "Lets yaffs do its own ECC" ++ depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS ++ default n ++ help ++ This enables yaffs to use its own ECC functions instead of using ++ the ones from the generic MTD-NAND driver. ++ ++ If unsure, say N. ++ ++config YAFFS_ECC_WRONG_ORDER ++ bool "Use the same ecc byte order as Steven Hill's nand_ecc.c" ++ depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS ++ default n ++ help ++ This makes yaffs_ecc.c use the same ecc byte order as Steven ++ Hill's nand_ecc.c. If not set, then you get the same ecc byte ++ order as SmartMedia. ++ ++ If unsure, say N. ++ ++config YAFFS_YAFFS2 ++ bool "2048 byte (or larger) / page devices" ++ depends on YAFFS_FS ++ default y ++ help ++ Enable yaffs2 support -- yaffs for >= 2K bytes per page devices ++ ++ If unsure, say Y. ++ ++config YAFFS_AUTO_YAFFS2 ++ bool "Autoselect yaffs2 format" ++ depends on YAFFS_YAFFS2 ++ default y ++ help ++ Without this, you need to explicitely use yaffs2 as the file ++ system type. With this, you can say "yaffs" and yaffs or yaffs2 ++ will be used depending on the device page size (yaffs on ++ 512-byte page devices, yaffs2 on 2K page devices). ++ ++ If unsure, say Y. ++ ++config YAFFS_DISABLE_TAGS_ECC ++ bool "Disable yaffs from doing ECC on tags by default" ++ depends on YAFFS_FS && YAFFS_YAFFS2 ++ default n ++ help ++ This defaults yaffs to using its own ECC calculations on tags instead of ++ just relying on the MTD. ++ This behavior can also be overridden with tags_ecc_on and ++ tags_ecc_off mount options. ++ ++ If unsure, say N. ++ ++config YAFFS_ALWAYS_CHECK_CHUNK_ERASED ++ bool "Force chunk erase check" ++ depends on YAFFS_FS ++ default n ++ help ++ Normally yaffs only checks chunks before writing until an erased ++ chunk is found. This helps to detect any partially written ++ chunks that might have happened due to power loss. ++ ++ Enabling this forces on the test that chunks are erased in flash ++ before writing to them. This takes more time but is potentially ++ a bit more secure. ++ ++ Suggest setting Y during development and ironing out driver ++ issues etc. Suggest setting to N if you want faster writing. ++ ++ If unsure, say Y. ++ ++config YAFFS_EMPTY_LOST_AND_FOUND ++ bool "Empty lost and found on boot" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is enabled then the contents of lost and found is ++ automatically dumped at mount. ++ ++ If unsure, say N. ++ ++config YAFFS_DISABLE_BLOCK_REFRESHING ++ bool "Disable yaffs2 block refreshing" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is set, then block refreshing is disabled. ++ Block refreshing infrequently refreshes the oldest block in ++ a yaffs2 file system. This mechanism helps to refresh flash to ++ mitigate against data loss. This is particularly useful for MLC. ++ ++ If unsure, say N. ++ ++config YAFFS_DISABLE_BACKGROUND ++ bool "Disable yaffs2 background processing" ++ depends on YAFFS_FS ++ default n ++ help ++ If this is set, then background processing is disabled. ++ Background processing makes many foreground activities faster. ++ ++ If unsure, say N. ++ ++config YAFFS_XATTR ++ bool "Enable yaffs2 xattr support" ++ depends on YAFFS_FS ++ default y ++ help ++ If this is set then yaffs2 will provide xattr support. ++ If unsure, say Y. +diff --git a/fs/yaffs2/Makefile b/fs/yaffs2/Makefile +new file mode 100755 +index 00000000..f9a9fb1b +--- /dev/null ++++ b/fs/yaffs2/Makefile +@@ -0,0 +1,18 @@ ++# ++# Makefile for the linux YAFFS filesystem routines. ++# ++ ++obj-$(CONFIG_YAFFS_FS) += yaffs.o ++ ++yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o ++yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o ++yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o ++yaffs-y += yaffs_mtdif.o ++yaffs-y += yaffs_nameval.o yaffs_attribs.o ++yaffs-y += yaffs_allocator.o ++yaffs-y += yaffs_yaffs1.o ++yaffs-y += yaffs_yaffs2.o ++yaffs-y += yaffs_bitmap.o ++yaffs-y += yaffs_summary.o ++yaffs-y += yaffs_verify.o ++ +diff --git a/fs/yaffs2/yaffs_allocator.c b/fs/yaffs2/yaffs_allocator.c +new file mode 100755 +index 00000000..c8f2861c +--- /dev/null ++++ b/fs/yaffs2/yaffs_allocator.c +@@ -0,0 +1,357 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_allocator.h" ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yportenv.h" ++ ++/* ++ * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks ++ * of approx 100 objects that are themn allocated singly. ++ * This is basically a simplified slab allocator. ++ * ++ * We don't use the Linux slab allocator because slab does not allow ++ * us to dump all the objects in one hit when we do a umount and tear ++ * down all the tnodes and objects. slab requires that we first free ++ * the individual objects. ++ * ++ * Once yaffs has been mainlined I shall try to motivate for a change ++ * to slab to provide the extra features we need here. ++ */ ++ ++struct yaffs_tnode_list { ++ struct yaffs_tnode_list *next; ++ struct yaffs_tnode *tnodes; ++}; ++ ++struct yaffs_obj_list { ++ struct yaffs_obj_list *next; ++ struct yaffs_obj *objects; ++}; ++ ++struct yaffs_allocator { ++ int n_tnodes_created; ++ struct yaffs_tnode *free_tnodes; ++ int n_free_tnodes; ++ struct yaffs_tnode_list *alloc_tnode_list; ++ ++ int n_obj_created; ++ struct list_head free_objs; ++ int n_free_objects; ++ ++ struct yaffs_obj_list *allocated_obj_list; ++}; ++ ++static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ struct yaffs_tnode_list *tmp; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ while (allocator->alloc_tnode_list) { ++ tmp = allocator->alloc_tnode_list->next; ++ ++ kfree(allocator->alloc_tnode_list->tnodes); ++ kfree(allocator->alloc_tnode_list); ++ allocator->alloc_tnode_list = tmp; ++ } ++ ++ allocator->free_tnodes = NULL; ++ allocator->n_free_tnodes = 0; ++ allocator->n_tnodes_created = 0; ++} ++ ++static void yaffs_init_raw_tnodes(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator->alloc_tnode_list = NULL; ++ allocator->free_tnodes = NULL; ++ allocator->n_free_tnodes = 0; ++ allocator->n_tnodes_created = 0; ++} ++ ++static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ int i; ++ struct yaffs_tnode *new_tnodes; ++ u8 *mem; ++ struct yaffs_tnode *curr; ++ struct yaffs_tnode *next; ++ struct yaffs_tnode_list *tnl; ++ ++ if (!allocator) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ if (n_tnodes < 1) ++ return YAFFS_OK; ++ ++ /* make these things */ ++ new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS); ++ mem = (u8 *) new_tnodes; ++ ++ if (!new_tnodes) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs: Could not allocate Tnodes"); ++ return YAFFS_FAIL; ++ } ++ ++ /* New hookup for wide tnodes */ ++ for (i = 0; i < n_tnodes - 1; i++) { ++ curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size]; ++ next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size]; ++ curr->internal[0] = next; ++ } ++ ++ curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size]; ++ curr->internal[0] = allocator->free_tnodes; ++ allocator->free_tnodes = (struct yaffs_tnode *)mem; ++ ++ allocator->n_free_tnodes += n_tnodes; ++ allocator->n_tnodes_created += n_tnodes; ++ ++ /* Now add this bunch of tnodes to a list for freeing up. ++ * NB If we can't add this to the management list it isn't fatal ++ * but it just means we can't free this bunch of tnodes later. ++ */ ++ tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS); ++ if (!tnl) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Could not add tnodes to management list"); ++ return YAFFS_FAIL; ++ } else { ++ tnl->tnodes = new_tnodes; ++ tnl->next = allocator->alloc_tnode_list; ++ allocator->alloc_tnode_list = tnl; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added"); ++ ++ return YAFFS_OK; ++} ++ ++struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = ++ (struct yaffs_allocator *)dev->allocator; ++ struct yaffs_tnode *tn = NULL; ++ ++ if (!allocator) { ++ BUG(); ++ return NULL; ++ } ++ ++ /* If there are none left make more */ ++ if (!allocator->free_tnodes) ++ yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES); ++ ++ if (allocator->free_tnodes) { ++ tn = allocator->free_tnodes; ++ allocator->free_tnodes = allocator->free_tnodes->internal[0]; ++ allocator->n_free_tnodes--; ++ } ++ ++ return tn; ++} ++ ++/* FreeTnode frees up a tnode and puts it back on the free list */ ++void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ if (tn) { ++ tn->internal[0] = allocator->free_tnodes; ++ allocator->free_tnodes = tn; ++ allocator->n_free_tnodes++; ++ } ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++/*--------------- yaffs_obj alloaction ------------------------ ++ * ++ * Free yaffs_objs are stored in a list using obj->siblings. ++ * The blocks of allocated objects are stored in a linked list. ++ */ ++ ++static void yaffs_init_raw_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator->allocated_obj_list = NULL; ++ INIT_LIST_HEAD(&allocator->free_objs); ++ allocator->n_free_objects = 0; ++} ++ ++static void yaffs_deinit_raw_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ struct yaffs_obj_list *tmp; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ while (allocator->allocated_obj_list) { ++ tmp = allocator->allocated_obj_list->next; ++ kfree(allocator->allocated_obj_list->objects); ++ kfree(allocator->allocated_obj_list); ++ allocator->allocated_obj_list = tmp; ++ } ++ ++ INIT_LIST_HEAD(&allocator->free_objs); ++ allocator->n_free_objects = 0; ++ allocator->n_obj_created = 0; ++} ++ ++static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj) ++{ ++ struct yaffs_allocator *allocator = dev->allocator; ++ int i; ++ struct yaffs_obj *new_objs; ++ struct yaffs_obj_list *list; ++ ++ if (!allocator) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ if (n_obj < 1) ++ return YAFFS_OK; ++ ++ /* make these things */ ++ new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS); ++ list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS); ++ ++ if (!new_objs || !list) { ++ kfree(new_objs); ++ new_objs = NULL; ++ kfree(list); ++ list = NULL; ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, ++ "Could not allocate more objects"); ++ return YAFFS_FAIL; ++ } ++ ++ /* Hook them into the free list */ ++ for (i = 0; i < n_obj; i++) ++ list_add(&new_objs[i].siblings, &allocator->free_objs); ++ ++ allocator->n_free_objects += n_obj; ++ allocator->n_obj_created += n_obj; ++ ++ /* Now add this bunch of Objects to a list for freeing up. */ ++ ++ list->objects = new_objs; ++ list->next = allocator->allocated_obj_list; ++ allocator->allocated_obj_list = list; ++ ++ return YAFFS_OK; ++} ++ ++struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj = NULL; ++ struct list_head *lh; ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return obj; ++ } ++ ++ /* If there are none left make more */ ++ if (list_empty(&allocator->free_objs)) ++ yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS); ++ ++ if (!list_empty(&allocator->free_objs)) { ++ lh = allocator->free_objs.next; ++ obj = list_entry(lh, struct yaffs_obj, siblings); ++ list_del_init(lh); ++ allocator->n_free_objects--; ++ } ++ ++ return obj; ++} ++ ++void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj) ++{ ++ ++ struct yaffs_allocator *allocator = dev->allocator; ++ ++ if (!allocator) { ++ BUG(); ++ return; ++ } ++ ++ /* Link into the free list. */ ++ list_add(&obj->siblings, &allocator->free_objs); ++ allocator->n_free_objects++; ++} ++ ++void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ ++ if (!dev->allocator) { ++ BUG(); ++ return; ++ } ++ ++ yaffs_deinit_raw_tnodes(dev); ++ yaffs_deinit_raw_objs(dev); ++ kfree(dev->allocator); ++ dev->allocator = NULL; ++} ++ ++void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_allocator *allocator; ++ ++ if (dev->allocator) { ++ BUG(); ++ return; ++ } ++ ++ allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS); ++ if (allocator) { ++ dev->allocator = allocator; ++ yaffs_init_raw_tnodes(dev); ++ yaffs_init_raw_objs(dev); ++ } ++} ++ +diff --git a/fs/yaffs2/yaffs_allocator.h b/fs/yaffs2/yaffs_allocator.h +new file mode 100755 +index 00000000..a8cc3226 +--- /dev/null ++++ b/fs/yaffs2/yaffs_allocator.h +@@ -0,0 +1,30 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_ALLOCATOR_H__ ++#define __YAFFS_ALLOCATOR_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev); ++void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev); ++ ++struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev); ++void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn); ++ ++struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev); ++void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_attribs.c b/fs/yaffs2/yaffs_attribs.c +new file mode 100755 +index 00000000..3d778f22 +--- /dev/null ++++ b/fs/yaffs2/yaffs_attribs.c +@@ -0,0 +1,124 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_attribs.h" ++ ++void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh) ++{ ++ obj->yst_uid = oh->yst_uid; ++ obj->yst_gid = oh->yst_gid; ++ obj->yst_atime = oh->yst_atime; ++ obj->yst_mtime = oh->yst_mtime; ++ obj->yst_ctime = oh->yst_ctime; ++ obj->yst_rdev = oh->yst_rdev; ++} ++ ++void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj) ++{ ++ oh->yst_uid = obj->yst_uid; ++ oh->yst_gid = obj->yst_gid; ++ oh->yst_atime = obj->yst_atime; ++ oh->yst_mtime = obj->yst_mtime; ++ oh->yst_ctime = obj->yst_ctime; ++ oh->yst_rdev = obj->yst_rdev; ++ ++} ++ ++void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c) ++{ ++ obj->yst_mtime = Y_CURRENT_TIME; ++ if (do_a) ++ obj->yst_atime = obj->yst_mtime; ++ if (do_c) ++ obj->yst_ctime = obj->yst_mtime; ++} ++ ++void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev) ++{ ++ yaffs_load_current_time(obj, 1, 1); ++ obj->yst_rdev = rdev; ++ obj->yst_uid = uid; ++ obj->yst_gid = gid; ++} ++ ++static loff_t yaffs_get_file_size(struct yaffs_obj *obj) ++{ ++ YCHAR *alias = NULL; ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return obj->variant.file_variant.file_size; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ alias = obj->variant.symlink_variant.alias; ++ if (!alias) ++ return 0; ++ return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH); ++ default: ++ return 0; ++ } ++} ++ ++int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr) ++{ ++ unsigned int valid = attr->ia_valid; ++ ++ if (valid & ATTR_MODE) ++ obj->yst_mode = attr->ia_mode; ++ if (valid & ATTR_UID) ++ obj->yst_uid = attr->ia_uid; ++ if (valid & ATTR_GID) ++ obj->yst_gid = attr->ia_gid; ++ ++ if (valid & ATTR_ATIME) ++ obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); ++ if (valid & ATTR_CTIME) ++ obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); ++ if (valid & ATTR_MTIME) ++ obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); ++ ++ if (valid & ATTR_SIZE) ++ yaffs_resize_file(obj, attr->ia_size); ++ ++ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); ++ ++ return YAFFS_OK; ++ ++} ++ ++int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr) ++{ ++ unsigned int valid = 0; ++ ++ attr->ia_mode = obj->yst_mode; ++ valid |= ATTR_MODE; ++ attr->ia_uid = obj->yst_uid; ++ valid |= ATTR_UID; ++ attr->ia_gid = obj->yst_gid; ++ valid |= ATTR_GID; ++ ++ Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; ++ valid |= ATTR_ATIME; ++ Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; ++ valid |= ATTR_CTIME; ++ Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; ++ valid |= ATTR_MTIME; ++ ++ attr->ia_size = yaffs_get_file_size(obj); ++ valid |= ATTR_SIZE; ++ ++ attr->ia_valid = valid; ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_attribs.h b/fs/yaffs2/yaffs_attribs.h +new file mode 100755 +index 00000000..5b21b085 +--- /dev/null ++++ b/fs/yaffs2/yaffs_attribs.h +@@ -0,0 +1,28 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_ATTRIBS_H__ ++#define __YAFFS_ATTRIBS_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh); ++void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj); ++void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev); ++void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c); ++int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr); ++int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_bitmap.c b/fs/yaffs2/yaffs_bitmap.c +new file mode 100755 +index 00000000..4440e930 +--- /dev/null ++++ b/fs/yaffs2/yaffs_bitmap.c +@@ -0,0 +1,97 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_bitmap.h" ++#include "yaffs_trace.h" ++/* ++ * Chunk bitmap manipulations ++ */ ++ ++static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk) ++{ ++ if (blk < dev->internal_start_block || blk > dev->internal_end_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "BlockBits block %d is not valid", ++ blk); ++ BUG(); ++ } ++ return dev->chunk_bits + ++ (dev->chunk_bit_stride * (blk - dev->internal_start_block)); ++} ++ ++void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ if (blk < dev->internal_start_block || blk > dev->internal_end_block || ++ chunk < 0 || chunk >= dev->param.chunks_per_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Chunk Id (%d:%d) invalid", ++ blk, chunk); ++ BUG(); ++ } ++} ++ ++void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ memset(blk_bits, 0, dev->chunk_bit_stride); ++} ++ ++void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ blk_bits[chunk / 8] &= ~(1 << (chunk & 7)); ++} ++ ++void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ blk_bits[chunk / 8] |= (1 << (chunk & 7)); ++} ++ ++int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ ++ yaffs_verify_chunk_bit_id(dev, blk, chunk); ++ return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; ++} ++ ++int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ int i; ++ ++ for (i = 0; i < dev->chunk_bit_stride; i++) { ++ if (*blk_bits) ++ return 1; ++ blk_bits++; ++ } ++ return 0; ++} ++ ++int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk) ++{ ++ u8 *blk_bits = yaffs_block_bits(dev, blk); ++ int i; ++ int n = 0; ++ ++ for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++) ++ n += hweight8(*blk_bits); ++ ++ return n; ++} +diff --git a/fs/yaffs2/yaffs_bitmap.h b/fs/yaffs2/yaffs_bitmap.h +new file mode 100755 +index 00000000..e26b37d8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_bitmap.h +@@ -0,0 +1,33 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* ++ * Chunk bitmap manipulations ++ */ ++ ++#ifndef __YAFFS_BITMAP_H__ ++#define __YAFFS_BITMAP_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk); ++void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk); ++void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk); ++int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk); ++int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_checkptrw.c b/fs/yaffs2/yaffs_checkptrw.c +new file mode 100755 +index 00000000..e739fb4a +--- /dev/null ++++ b/fs/yaffs2/yaffs_checkptrw.c +@@ -0,0 +1,474 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_checkptrw.h" ++#include "yaffs_getblockinfo.h" ++ ++struct yaffs_checkpt_chunk_hdr { ++ int version; ++ int seq; ++ u32 sum; ++ u32 xor; ++} ; ++ ++ ++static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) ++{ ++ return chunk - dev->chunk_offset; ++} ++ ++static int apply_block_offset(struct yaffs_dev *dev, int block) ++{ ++ return block - dev->block_offset; ++} ++ ++static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_chunk_hdr hdr; ++ ++ hdr.version = YAFFS_CHECKPOINT_VERSION; ++ hdr.seq = dev->checkpt_page_seq; ++ hdr.sum = dev->checkpt_sum; ++ hdr.xor = dev->checkpt_xor; ++ ++ dev->checkpt_byte_offs = sizeof(hdr); ++ ++ memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr)); ++} ++ ++static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_chunk_hdr hdr; ++ ++ memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr)); ++ ++ dev->checkpt_byte_offs = sizeof(hdr); ++ ++ return hdr.version == YAFFS_CHECKPOINT_VERSION && ++ hdr.seq == dev->checkpt_page_seq && ++ hdr.sum == dev->checkpt_sum && ++ hdr.xor == dev->checkpt_xor; ++} ++ ++static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev) ++{ ++ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpt blocks_avail = %d", blocks_avail); ++ ++ return (blocks_avail <= 0) ? 0 : 1; ++} ++ ++static int yaffs_checkpt_erase(struct yaffs_dev *dev) ++{ ++ int i; ++ ++ if (!dev->drv.drv_erase_fn) ++ return 0; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checking blocks %d to %d", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i); ++ int offset_i = apply_block_offset(dev, i); ++ int result; ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "erasing checkpt block %d", i); ++ ++ dev->n_erasures++; ++ ++ result = dev->drv.drv_erase_fn(dev, offset_i); ++ if(result) { ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += ++ dev->param.chunks_per_block; ++ } else { ++ dev->drv.drv_mark_bad_fn(dev, offset_i); ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ } ++ } ++ } ++ ++ dev->blocks_in_checkpt = 0; ++ ++ return 1; ++} ++ ++static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev) ++{ ++ int i; ++ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "allocating checkpt block: erased %d reserved %d avail %d next %d ", ++ dev->n_erased_blocks, dev->param.n_reserved_blocks, ++ blocks_avail, dev->checkpt_next_block); ++ ++ if (dev->checkpt_next_block >= 0 && ++ dev->checkpt_next_block <= dev->internal_end_block && ++ blocks_avail > 0) { ++ ++ for (i = dev->checkpt_next_block; i <= dev->internal_end_block; ++ i++) { ++ struct yaffs_block_info *bi; ++ ++ bi = yaffs_get_block_info(dev, i); ++ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ dev->checkpt_next_block = i + 1; ++ dev->checkpt_cur_block = i; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "allocating checkpt block %d", i); ++ return; ++ } ++ } ++ } ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks"); ++ ++ dev->checkpt_next_block = -1; ++ dev->checkpt_cur_block = -1; ++} ++ ++static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) ++{ ++ int i; ++ struct yaffs_ext_tags tags; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "find next checkpt block: start: blocks %d next %d", ++ dev->blocks_in_checkpt, dev->checkpt_next_block); ++ ++ if (dev->blocks_in_checkpt < dev->checkpt_max_blocks) ++ for (i = dev->checkpt_next_block; i <= dev->internal_end_block; ++ i++) { ++ int chunk = i * dev->param.chunks_per_block; ++ enum yaffs_block_state state; ++ u32 seq; ++ ++ dev->tagger.read_chunk_tags_fn(dev, ++ apply_chunk_offset(dev, chunk), ++ NULL, &tags); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d", ++ i, (int) state, ++ tags.obj_id, tags.seq_number, ++ tags.ecc_result); ++ ++ if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) ++ continue; ++ ++ dev->tagger.query_block_fn(dev, ++ apply_block_offset(dev, i), ++ &state, &seq); ++ if (state == YAFFS_BLOCK_STATE_DEAD) ++ continue; ++ ++ /* Right kind of block */ ++ dev->checkpt_next_block = tags.obj_id; ++ dev->checkpt_cur_block = i; ++ dev->checkpt_block_list[dev->blocks_in_checkpt] = i; ++ dev->blocks_in_checkpt++; ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "found checkpt block %d", i); ++ return; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks"); ++ ++ dev->checkpt_next_block = -1; ++ dev->checkpt_cur_block = -1; ++} ++ ++int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) ++{ ++ int i; ++ ++ dev->checkpt_open_write = writing; ++ ++ /* Got the functions we need? */ ++ if (!dev->tagger.write_chunk_tags_fn || ++ !dev->tagger.read_chunk_tags_fn || ++ !dev->drv.drv_erase_fn || ++ !dev->drv.drv_mark_bad_fn) ++ return 0; ++ ++ if (writing && !yaffs2_checkpt_space_ok(dev)) ++ return 0; ++ ++ if (!dev->checkpt_buffer) ++ dev->checkpt_buffer = ++ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ dev->checkpt_page_seq = 0; ++ dev->checkpt_byte_count = 0; ++ dev->checkpt_sum = 0; ++ dev->checkpt_xor = 0; ++ dev->checkpt_cur_block = -1; ++ dev->checkpt_cur_chunk = -1; ++ dev->checkpt_next_block = dev->internal_start_block; ++ ++ if (writing) { ++ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk); ++ yaffs2_checkpt_init_chunk_hdr(dev); ++ return yaffs_checkpt_erase(dev); ++ } ++ ++ /* Opening for a read */ ++ /* Set to a value that will kick off a read */ ++ dev->checkpt_byte_offs = dev->data_bytes_per_chunk; ++ /* A checkpoint block list of 1 checkpoint block per 16 block is ++ * (hopefully) going to be way more than we need */ ++ dev->blocks_in_checkpt = 0; ++ dev->checkpt_max_blocks = ++ (dev->internal_end_block - dev->internal_start_block) / 16 + 2; ++ dev->checkpt_block_list = ++ kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS); ++ ++ if (!dev->checkpt_block_list) ++ return 0; ++ ++ for (i = 0; i < dev->checkpt_max_blocks; i++) ++ dev->checkpt_block_list[i] = -1; ++ ++ return 1; ++} ++ ++int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum) ++{ ++ u32 composite_sum; ++ ++ composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff); ++ *sum = composite_sum; ++ return 1; ++} ++ ++static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev) ++{ ++ int chunk; ++ int offset_chunk; ++ struct yaffs_ext_tags tags; ++ ++ if (dev->checkpt_cur_block < 0) { ++ yaffs2_checkpt_find_erased_block(dev); ++ dev->checkpt_cur_chunk = 0; ++ } ++ ++ if (dev->checkpt_cur_block < 0) ++ return 0; ++ ++ tags.is_deleted = 0; ++ tags.obj_id = dev->checkpt_next_block; /* Hint to next place to look */ ++ tags.chunk_id = dev->checkpt_page_seq + 1; ++ tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA; ++ tags.n_bytes = dev->data_bytes_per_chunk; ++ if (dev->checkpt_cur_chunk == 0) { ++ /* First chunk we write for the block? Set block state to ++ checkpoint */ ++ struct yaffs_block_info *bi = ++ yaffs_get_block_info(dev, dev->checkpt_cur_block); ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ dev->blocks_in_checkpt++; ++ } ++ ++ chunk = ++ dev->checkpt_cur_block * dev->param.chunks_per_block + ++ dev->checkpt_cur_chunk; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d", ++ chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk, ++ tags.obj_id, tags.chunk_id); ++ ++ offset_chunk = apply_chunk_offset(dev, chunk); ++ ++ dev->n_page_writes++; ++ ++ dev->tagger.write_chunk_tags_fn(dev, offset_chunk, ++ dev->checkpt_buffer, &tags); ++ dev->checkpt_page_seq++; ++ dev->checkpt_cur_chunk++; ++ if (dev->checkpt_cur_chunk >= dev->param.chunks_per_block) { ++ dev->checkpt_cur_chunk = 0; ++ dev->checkpt_cur_block = -1; ++ } ++ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk); ++ ++ yaffs2_checkpt_init_chunk_hdr(dev); ++ ++ ++ return 1; ++} ++ ++int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes) ++{ ++ int i = 0; ++ int ok = 1; ++ u8 *data_bytes = (u8 *) data; ++ ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ if (!dev->checkpt_open_write) ++ return -1; ++ ++ while (i < n_bytes && ok) { ++ dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes; ++ dev->checkpt_sum += *data_bytes; ++ dev->checkpt_xor ^= *data_bytes; ++ ++ dev->checkpt_byte_offs++; ++ i++; ++ data_bytes++; ++ dev->checkpt_byte_count++; ++ ++ if (dev->checkpt_byte_offs < 0 || ++ dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) ++ ok = yaffs2_checkpt_flush_buffer(dev); ++ } ++ ++ return i; ++} ++ ++int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) ++{ ++ int i = 0; ++ int ok = 1; ++ struct yaffs_ext_tags tags; ++ int chunk; ++ int offset_chunk; ++ u8 *data_bytes = (u8 *) data; ++ ++ if (!dev->checkpt_buffer) ++ return 0; ++ ++ if (dev->checkpt_open_write) ++ return -1; ++ ++ while (i < n_bytes && ok) { ++ ++ if (dev->checkpt_byte_offs < 0 || ++ dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) { ++ ++ if (dev->checkpt_cur_block < 0) { ++ yaffs2_checkpt_find_block(dev); ++ dev->checkpt_cur_chunk = 0; ++ } ++ ++ if (dev->checkpt_cur_block < 0) { ++ ok = 0; ++ break; ++ } ++ ++ chunk = dev->checkpt_cur_block * ++ dev->param.chunks_per_block + ++ dev->checkpt_cur_chunk; ++ ++ offset_chunk = apply_chunk_offset(dev, chunk); ++ dev->n_page_reads++; ++ ++ /* read in the next chunk */ ++ dev->tagger.read_chunk_tags_fn(dev, ++ offset_chunk, ++ dev->checkpt_buffer, ++ &tags); ++ ++ if (tags.chunk_id != (dev->checkpt_page_seq + 1) || ++ tags.ecc_result > YAFFS_ECC_RESULT_FIXED || ++ tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) { ++ ok = 0; ++ break; ++ } ++ if(!yaffs2_checkpt_check_chunk_hdr(dev)) { ++ ok = 0; ++ break; ++ } ++ ++ dev->checkpt_page_seq++; ++ dev->checkpt_cur_chunk++; ++ ++ if (dev->checkpt_cur_chunk >= ++ dev->param.chunks_per_block) ++ dev->checkpt_cur_block = -1; ++ ++ } ++ ++ *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs]; ++ dev->checkpt_sum += *data_bytes; ++ dev->checkpt_xor ^= *data_bytes; ++ dev->checkpt_byte_offs++; ++ i++; ++ data_bytes++; ++ dev->checkpt_byte_count++; ++ } ++ ++ return i; ++} ++ ++int yaffs_checkpt_close(struct yaffs_dev *dev) ++{ ++ int i; ++ ++ if (dev->checkpt_open_write) { ++ if (dev->checkpt_byte_offs != ++ sizeof(sizeof(struct yaffs_checkpt_chunk_hdr))) ++ yaffs2_checkpt_flush_buffer(dev); ++ } else if (dev->checkpt_block_list) { ++ for (i = 0; ++ i < dev->blocks_in_checkpt && ++ dev->checkpt_block_list[i] >= 0; i++) { ++ int blk = dev->checkpt_block_list[i]; ++ struct yaffs_block_info *bi = NULL; ++ ++ if (dev->internal_start_block <= blk && ++ blk <= dev->internal_end_block) ++ bi = yaffs_get_block_info(dev, blk); ++ if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY) ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ } ++ kfree(dev->checkpt_block_list); ++ dev->checkpt_block_list = NULL; ++ } ++ ++ dev->n_free_chunks -= ++ dev->blocks_in_checkpt * dev->param.chunks_per_block; ++ dev->n_erased_blocks -= dev->blocks_in_checkpt; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d", ++ dev->checkpt_byte_count); ++ ++ if (dev->checkpt_buffer) { ++ /* free the buffer */ ++ kfree(dev->checkpt_buffer); ++ dev->checkpt_buffer = NULL; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev) ++{ ++ /* Erase the checkpoint data */ ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "checkpoint invalidate of %d blocks", ++ dev->blocks_in_checkpt); ++ ++ return yaffs_checkpt_erase(dev); ++} +diff --git a/fs/yaffs2/yaffs_checkptrw.h b/fs/yaffs2/yaffs_checkptrw.h +new file mode 100755 +index 00000000..cdbaba71 +--- /dev/null ++++ b/fs/yaffs2/yaffs_checkptrw.h +@@ -0,0 +1,33 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_CHECKPTRW_H__ ++#define __YAFFS_CHECKPTRW_H__ ++ ++#include "yaffs_guts.h" ++ ++int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing); ++ ++int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes); ++ ++int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes); ++ ++int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum); ++ ++int yaffs_checkpt_close(struct yaffs_dev *dev); ++ ++int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_ecc.c b/fs/yaffs2/yaffs_ecc.c +new file mode 100755 +index 00000000..9294107c +--- /dev/null ++++ b/fs/yaffs2/yaffs_ecc.c +@@ -0,0 +1,281 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/* ++ * This code implements the ECC algorithm used in SmartMedia. ++ * ++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. ++ * The two unused bit are set to 1. ++ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two ++ * such ECC blocks are used on a 512-byte NAND page. ++ * ++ */ ++ ++#include "yportenv.h" ++ ++#include "yaffs_ecc.h" ++ ++/* Table generated by gen-ecc.c ++ * Using a table means we do not have to calculate p1..p4 and p1'..p4' ++ * for each byte of data. These are instead provided in a table in bits7..2. ++ * Bit 0 of each entry indicates whether the entry has an odd or even parity, ++ * and therefore this bytes influence on the line parity. ++ */ ++ ++static const unsigned char column_parity_table[] = { ++ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, ++ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, ++ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, ++ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, ++ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, ++ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, ++ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, ++ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, ++ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, ++ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, ++ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, ++ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, ++ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, ++ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, ++ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, ++ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, ++ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, ++ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, ++ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, ++ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, ++ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, ++ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, ++ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, ++ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, ++ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, ++ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, ++ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, ++ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, ++ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, ++ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, ++ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, ++ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, ++}; ++ ++ ++/* Calculate the ECC for a 256-byte block of data */ ++void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc) ++{ ++ unsigned int i; ++ unsigned char col_parity = 0; ++ unsigned char line_parity = 0; ++ unsigned char line_parity_prime = 0; ++ unsigned char t; ++ unsigned char b; ++ ++ for (i = 0; i < 256; i++) { ++ b = column_parity_table[*data++]; ++ col_parity ^= b; ++ ++ if (b & 0x01) { /* odd number of bits in the byte */ ++ line_parity ^= i; ++ line_parity_prime ^= ~i; ++ } ++ } ++ ++ ecc[2] = (~col_parity) | 0x03; ++ ++ t = 0; ++ if (line_parity & 0x80) ++ t |= 0x80; ++ if (line_parity_prime & 0x80) ++ t |= 0x40; ++ if (line_parity & 0x40) ++ t |= 0x20; ++ if (line_parity_prime & 0x40) ++ t |= 0x10; ++ if (line_parity & 0x20) ++ t |= 0x08; ++ if (line_parity_prime & 0x20) ++ t |= 0x04; ++ if (line_parity & 0x10) ++ t |= 0x02; ++ if (line_parity_prime & 0x10) ++ t |= 0x01; ++ ecc[1] = ~t; ++ ++ t = 0; ++ if (line_parity & 0x08) ++ t |= 0x80; ++ if (line_parity_prime & 0x08) ++ t |= 0x40; ++ if (line_parity & 0x04) ++ t |= 0x20; ++ if (line_parity_prime & 0x04) ++ t |= 0x10; ++ if (line_parity & 0x02) ++ t |= 0x08; ++ if (line_parity_prime & 0x02) ++ t |= 0x04; ++ if (line_parity & 0x01) ++ t |= 0x02; ++ if (line_parity_prime & 0x01) ++ t |= 0x01; ++ ecc[0] = ~t; ++ ++} ++ ++/* Correct the ECC on a 256 byte block of data */ ++ ++int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc, ++ const unsigned char *test_ecc) ++{ ++ unsigned char d0, d1, d2; /* deltas */ ++ ++ d0 = read_ecc[0] ^ test_ecc[0]; ++ d1 = read_ecc[1] ^ test_ecc[1]; ++ d2 = read_ecc[2] ^ test_ecc[2]; ++ ++ if ((d0 | d1 | d2) == 0) ++ return 0; /* no error */ ++ ++ if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && ++ ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 && ++ ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) { ++ /* Single bit (recoverable) error in data */ ++ ++ unsigned byte; ++ unsigned bit; ++ ++ bit = byte = 0; ++ ++ if (d1 & 0x80) ++ byte |= 0x80; ++ if (d1 & 0x20) ++ byte |= 0x40; ++ if (d1 & 0x08) ++ byte |= 0x20; ++ if (d1 & 0x02) ++ byte |= 0x10; ++ if (d0 & 0x80) ++ byte |= 0x08; ++ if (d0 & 0x20) ++ byte |= 0x04; ++ if (d0 & 0x08) ++ byte |= 0x02; ++ if (d0 & 0x02) ++ byte |= 0x01; ++ ++ if (d2 & 0x80) ++ bit |= 0x04; ++ if (d2 & 0x20) ++ bit |= 0x02; ++ if (d2 & 0x08) ++ bit |= 0x01; ++ ++ data[byte] ^= (1 << bit); ++ ++ return 1; /* Corrected the error */ ++ } ++ ++ if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) { ++ /* Reccoverable error in ecc */ ++ ++ read_ecc[0] = test_ecc[0]; ++ read_ecc[1] = test_ecc[1]; ++ read_ecc[2] = test_ecc[2]; ++ ++ return 1; /* Corrected the error */ ++ } ++ ++ /* Unrecoverable error */ ++ ++ return -1; ++ ++} ++ ++/* ++ * ECCxxxOther does ECC calcs on arbitrary n bytes of data ++ */ ++void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *ecc_other) ++{ ++ unsigned int i; ++ unsigned char col_parity = 0; ++ unsigned line_parity = 0; ++ unsigned line_parity_prime = 0; ++ unsigned char b; ++ ++ for (i = 0; i < n_bytes; i++) { ++ b = column_parity_table[*data++]; ++ col_parity ^= b; ++ ++ if (b & 0x01) { ++ /* odd number of bits in the byte */ ++ line_parity ^= i; ++ line_parity_prime ^= ~i; ++ } ++ ++ } ++ ++ ecc_other->col_parity = (col_parity >> 2) & 0x3f; ++ ecc_other->line_parity = line_parity; ++ ecc_other->line_parity_prime = line_parity_prime; ++} ++ ++int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *read_ecc, ++ const struct yaffs_ecc_other *test_ecc) ++{ ++ unsigned char delta_col; /* column parity delta */ ++ unsigned delta_line; /* line parity delta */ ++ unsigned delta_line_prime; /* line parity delta */ ++ unsigned bit; ++ ++ delta_col = read_ecc->col_parity ^ test_ecc->col_parity; ++ delta_line = read_ecc->line_parity ^ test_ecc->line_parity; ++ delta_line_prime = ++ read_ecc->line_parity_prime ^ test_ecc->line_parity_prime; ++ ++ if ((delta_col | delta_line | delta_line_prime) == 0) ++ return 0; /* no error */ ++ ++ if (delta_line == ~delta_line_prime && ++ (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) { ++ /* Single bit (recoverable) error in data */ ++ ++ bit = 0; ++ ++ if (delta_col & 0x20) ++ bit |= 0x04; ++ if (delta_col & 0x08) ++ bit |= 0x02; ++ if (delta_col & 0x02) ++ bit |= 0x01; ++ ++ if (delta_line >= n_bytes) ++ return -1; ++ ++ data[delta_line] ^= (1 << bit); ++ ++ return 1; /* corrected */ ++ } ++ ++ if ((hweight32(delta_line) + ++ hweight32(delta_line_prime) + ++ hweight8(delta_col)) == 1) { ++ /* Reccoverable error in ecc */ ++ ++ *read_ecc = *test_ecc; ++ return 1; /* corrected */ ++ } ++ ++ /* Unrecoverable error */ ++ ++ return -1; ++} +diff --git a/fs/yaffs2/yaffs_ecc.h b/fs/yaffs2/yaffs_ecc.h +new file mode 100755 +index 00000000..17d47bd8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_ecc.h +@@ -0,0 +1,44 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* ++ * This code implements the ECC algorithm used in SmartMedia. ++ * ++ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. ++ * The two unused bit are set to 1. ++ * The ECC can correct single bit errors in a 256-byte page of data. ++ * Thus, two such ECC blocks are used on a 512-byte NAND page. ++ * ++ */ ++ ++#ifndef __YAFFS_ECC_H__ ++#define __YAFFS_ECC_H__ ++ ++struct yaffs_ecc_other { ++ unsigned char col_parity; ++ unsigned line_parity; ++ unsigned line_parity_prime; ++}; ++ ++void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc); ++int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc, ++ const unsigned char *test_ecc); ++ ++void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *ecc); ++int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, ++ struct yaffs_ecc_other *read_ecc, ++ const struct yaffs_ecc_other *test_ecc); ++#endif +diff --git a/fs/yaffs2/yaffs_getblockinfo.h b/fs/yaffs2/yaffs_getblockinfo.h +new file mode 100755 +index 00000000..8fd0802b +--- /dev/null ++++ b/fs/yaffs2/yaffs_getblockinfo.h +@@ -0,0 +1,35 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_GETBLOCKINFO_H__ ++#define __YAFFS_GETBLOCKINFO_H__ ++ ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++ ++/* Function to manipulate block info */ ++static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev ++ *dev, int blk) ++{ ++ if (blk < dev->internal_start_block || blk > dev->internal_end_block) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs: get_block_info block %d is not valid", ++ blk); ++ BUG(); ++ } ++ return &dev->block_info[blk - dev->internal_start_block]; ++} ++ ++#endif +diff --git a/fs/yaffs2/yaffs_guts.c b/fs/yaffs2/yaffs_guts.c +new file mode 100755 +index 00000000..794bef80 +--- /dev/null ++++ b/fs/yaffs2/yaffs_guts.c +@@ -0,0 +1,5059 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yportenv.h" ++#include "yaffs_trace.h" ++ ++#include "yaffs_guts.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_tagscompat.h" ++#include "yaffs_tagsmarshall.h" ++#include "yaffs_nand.h" ++#include "yaffs_yaffs1.h" ++#include "yaffs_yaffs2.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_verify.h" ++#include "yaffs_nand.h" ++#include "yaffs_packedtags2.h" ++#include "yaffs_nameval.h" ++#include "yaffs_allocator.h" ++#include "yaffs_attribs.h" ++#include "yaffs_summary.h" ++ ++/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */ ++#define YAFFS_GC_GOOD_ENOUGH 2 ++#define YAFFS_GC_PASSIVE_THRESHOLD 4 ++ ++#include "yaffs_ecc.h" ++ ++/* Forward declarations */ ++ ++static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, ++ const u8 *buffer, int n_bytes, int use_reserve); ++ ++static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name, ++ int buffer_size); ++ ++/* Function to calculate chunk and offset */ ++ ++void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, ++ int *chunk_out, u32 *offset_out) ++{ ++ int chunk; ++ u32 offset; ++ ++ chunk = (u32) (addr >> dev->chunk_shift); ++ ++ if (dev->chunk_div == 1) { ++ /* easy power of 2 case */ ++ offset = (u32) (addr & dev->chunk_mask); ++ } else { ++ /* Non power-of-2 case */ ++ ++ loff_t chunk_base; ++ ++ chunk /= dev->chunk_div; ++ ++ chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk; ++ offset = (u32) (addr - chunk_base); ++ } ++ ++ *chunk_out = chunk; ++ *offset_out = offset; ++} ++ ++/* Function to return the number of shifts for a power of 2 greater than or ++ * equal to the given number ++ * Note we don't try to cater for all possible numbers and this does not have to ++ * be hellishly efficient. ++ */ ++ ++static inline u32 calc_shifts_ceiling(u32 x) ++{ ++ int extra_bits; ++ int shifts; ++ ++ shifts = extra_bits = 0; ++ ++ while (x > 1) { ++ if (x & 1) ++ extra_bits++; ++ x >>= 1; ++ shifts++; ++ } ++ ++ if (extra_bits) ++ shifts++; ++ ++ return shifts; ++} ++ ++/* Function to return the number of shifts to get a 1 in bit 0 ++ */ ++ ++static inline u32 calc_shifts(u32 x) ++{ ++ u32 shifts; ++ ++ shifts = 0; ++ ++ if (!x) ++ return 0; ++ ++ while (!(x & 1)) { ++ x >>= 1; ++ shifts++; ++ } ++ ++ return shifts; ++} ++ ++/* ++ * Temporary buffer manipulations. ++ */ ++ ++static int yaffs_init_tmp_buffers(struct yaffs_dev *dev) ++{ ++ int i; ++ u8 *buf = (u8 *) 1; ++ ++ memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer)); ++ ++ for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) { ++ dev->temp_buffer[i].in_use = 0; ++ buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ dev->temp_buffer[i].buffer = buf; ++ } ++ ++ return buf ? YAFFS_OK : YAFFS_FAIL; ++} ++ ++u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev) ++{ ++ int i; ++ ++ dev->temp_in_use++; ++ if (dev->temp_in_use > dev->max_temp) ++ dev->max_temp = dev->temp_in_use; ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { ++ if (dev->temp_buffer[i].in_use == 0) { ++ dev->temp_buffer[i].in_use = 1; ++ return dev->temp_buffer[i].buffer; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_BUFFERS, "Out of temp buffers"); ++ /* ++ * If we got here then we have to allocate an unmanaged one ++ * This is not good. ++ */ ++ ++ dev->unmanaged_buffer_allocs++; ++ return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS); ++ ++} ++ ++void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer) ++{ ++ int i; ++ ++ dev->temp_in_use--; ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { ++ if (dev->temp_buffer[i].buffer == buffer) { ++ dev->temp_buffer[i].in_use = 0; ++ return; ++ } ++ } ++ ++ if (buffer) { ++ /* assume it is an unmanaged one. */ ++ yaffs_trace(YAFFS_TRACE_BUFFERS, ++ "Releasing unmanaged temp buffer"); ++ kfree(buffer); ++ dev->unmanaged_buffer_deallocs++; ++ } ++ ++} ++ ++/* ++ * Functions for robustisizing TODO ++ * ++ */ ++ ++static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, ++ const struct yaffs_ext_tags *tags) ++{ ++ (void) dev; ++ (void) nand_chunk; ++ (void) data; ++ (void) tags; ++} ++ ++static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk, ++ const struct yaffs_ext_tags *tags) ++{ ++ (void) dev; ++ (void) nand_chunk; ++ (void) tags; ++} ++ ++void yaffs_handle_chunk_error(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi) ++{ ++ if (!bi->gc_prioritise) { ++ bi->gc_prioritise = 1; ++ dev->has_pending_prioritised_gc = 1; ++ bi->chunk_error_strikes++; ++ ++ if (bi->chunk_error_strikes > 3) { ++ bi->needs_retiring = 1; /* Too many stikes, so retire */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Block struck out"); ++ ++ } ++ } ++} ++ ++static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk, ++ int erased_ok) ++{ ++ int flash_block = nand_chunk / dev->param.chunks_per_block; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block); ++ ++ yaffs_handle_chunk_error(dev, bi); ++ ++ if (erased_ok) { ++ /* Was an actual write failure, ++ * so mark the block for retirement.*/ ++ bi->needs_retiring = 1; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Block %d needs retiring", flash_block); ++ } ++ ++ /* Delete the chunk */ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ yaffs_skip_rest_of_block(dev); ++} ++ ++/* ++ * Verification code ++ */ ++ ++/* ++ * Simple hash function. Needs to have a reasonable spread ++ */ ++ ++static inline int yaffs_hash_fn(int n) ++{ ++ if (n < 0) ++ n = -n; ++ return n % YAFFS_NOBJECT_BUCKETS; ++} ++ ++/* ++ * Access functions to useful fake objects. ++ * Note that root might have a presence in NAND if permissions are set. ++ */ ++ ++struct yaffs_obj *yaffs_root(struct yaffs_dev *dev) ++{ ++ return dev->root_dir; ++} ++ ++struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev) ++{ ++ return dev->lost_n_found; ++} ++ ++/* ++ * Erased NAND checking functions ++ */ ++ ++int yaffs_check_ff(u8 *buffer, int n_bytes) ++{ ++ /* Horrible, slow implementation */ ++ while (n_bytes--) { ++ if (*buffer != 0xff) ++ return 0; ++ buffer++; ++ } ++ return 1; ++} ++ ++static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk) ++{ ++ int retval = YAFFS_OK; ++ u8 *data = yaffs_get_temp_buffer(dev); ++ struct yaffs_ext_tags tags; ++ int result; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags); ++ ++ if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR) ++ retval = YAFFS_FAIL; ++ ++ if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) || ++ tags.chunk_used) { ++ yaffs_trace(YAFFS_TRACE_NANDACCESS, ++ "Chunk %d not erased", nand_chunk); ++ retval = YAFFS_FAIL; ++ } ++ ++ yaffs_release_temp_buffer(dev, data); ++ ++ return retval; ++ ++} ++ ++static int yaffs_verify_chunk_written(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, ++ struct yaffs_ext_tags *tags) ++{ ++ int retval = YAFFS_OK; ++ struct yaffs_ext_tags temp_tags; ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ int result; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags); ++ if (memcmp(buffer, data, dev->data_bytes_per_chunk) || ++ temp_tags.obj_id != tags->obj_id || ++ temp_tags.chunk_id != tags->chunk_id || ++ temp_tags.n_bytes != tags->n_bytes) ++ retval = YAFFS_FAIL; ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ return retval; ++} ++ ++ ++int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks) ++{ ++ int reserved_chunks; ++ int reserved_blocks = dev->param.n_reserved_blocks; ++ int checkpt_blocks; ++ ++ checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev); ++ ++ reserved_chunks = ++ (reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block; ++ ++ return (dev->n_free_chunks > (reserved_chunks + n_chunks)); ++} ++ ++static int yaffs_find_alloc_block(struct yaffs_dev *dev) ++{ ++ int i; ++ struct yaffs_block_info *bi; ++ ++ if (dev->n_erased_blocks < 1) { ++ /* Hoosterman we've got a problem. ++ * Can't get space to gc ++ */ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: no more erased blocks"); ++ ++ return -1; ++ } ++ ++ /* Find an empty block. */ ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ dev->alloc_block_finder++; ++ if (dev->alloc_block_finder < dev->internal_start_block ++ || dev->alloc_block_finder > dev->internal_end_block) { ++ dev->alloc_block_finder = dev->internal_start_block; ++ } ++ ++ bi = yaffs_get_block_info(dev, dev->alloc_block_finder); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->seq_number++; ++ bi->seq_number = dev->seq_number; ++ dev->n_erased_blocks--; ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, ++ "Allocated block %d, seq %d, %d left" , ++ dev->alloc_block_finder, dev->seq_number, ++ dev->n_erased_blocks); ++ return dev->alloc_block_finder; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs tragedy: no more erased blocks, but there should have been %d", ++ dev->n_erased_blocks); ++ ++ return -1; ++} ++ ++static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver, ++ struct yaffs_block_info **block_ptr) ++{ ++ int ret_val; ++ struct yaffs_block_info *bi; ++ ++ if (dev->alloc_block < 0) { ++ /* Get next block to allocate off */ ++ dev->alloc_block = yaffs_find_alloc_block(dev); ++ dev->alloc_page = 0; ++ } ++ ++ if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) { ++ /* No space unless we're allowed to use the reserve. */ ++ return -1; ++ } ++ ++ if (dev->n_erased_blocks < dev->param.n_reserved_blocks ++ && dev->alloc_page == 0) ++ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve"); ++ ++ /* Next page please.... */ ++ if (dev->alloc_block >= 0) { ++ bi = yaffs_get_block_info(dev, dev->alloc_block); ++ ++ ret_val = (dev->alloc_block * dev->param.chunks_per_block) + ++ dev->alloc_page; ++ bi->pages_in_use++; ++ yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page); ++ ++ dev->alloc_page++; ++ ++ dev->n_free_chunks--; ++ ++ /* If the block is full set the state to full */ ++ if (dev->alloc_page >= dev->param.chunks_per_block) { ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ ++ if (block_ptr) ++ *block_ptr = bi; ++ ++ return ret_val; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!"); ++ ++ return -1; ++} ++ ++static int yaffs_get_erased_chunks(struct yaffs_dev *dev) ++{ ++ int n; ++ ++ n = dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ if (dev->alloc_block > 0) ++ n += (dev->param.chunks_per_block - dev->alloc_page); ++ ++ return n; ++ ++} ++ ++/* ++ * yaffs_skip_rest_of_block() skips over the rest of the allocation block ++ * if we don't want to write to it. ++ */ ++void yaffs_skip_rest_of_block(struct yaffs_dev *dev) ++{ ++ struct yaffs_block_info *bi; ++ ++ if (dev->alloc_block > 0) { ++ bi = yaffs_get_block_info(dev, dev->alloc_block); ++ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ } ++} ++ ++static int yaffs_write_new_chunk(struct yaffs_dev *dev, ++ const u8 *data, ++ struct yaffs_ext_tags *tags, int use_reserver) ++{ ++ int attempts = 0; ++ int write_ok = 0; ++ int chunk; ++ ++ yaffs2_checkpt_invalidate(dev); ++ ++ do { ++ struct yaffs_block_info *bi = 0; ++ int erased_ok = 0; ++ ++ chunk = yaffs_alloc_chunk(dev, use_reserver, &bi); ++ if (chunk < 0) { ++ /* no space */ ++ break; ++ } ++ ++ /* First check this chunk is erased, if it needs ++ * checking. The checking policy (unless forced ++ * always on) is as follows: ++ * ++ * Check the first page we try to write in a block. ++ * If the check passes then we don't need to check any ++ * more. If the check fails, we check again... ++ * If the block has been erased, we don't need to check. ++ * ++ * However, if the block has been prioritised for gc, ++ * then we think there might be something odd about ++ * this block and stop using it. ++ * ++ * Rationale: We should only ever see chunks that have ++ * not been erased if there was a partially written ++ * chunk due to power loss. This checking policy should ++ * catch that case with very few checks and thus save a ++ * lot of checks that are most likely not needed. ++ * ++ * Mods to the above ++ * If an erase check fails or the write fails we skip the ++ * rest of the block. ++ */ ++ ++ /* let's give it a try */ ++ attempts++; ++ ++ if (dev->param.always_check_erased) ++ bi->skip_erased_check = 0; ++ ++ if (!bi->skip_erased_check) { ++ erased_ok = yaffs_check_chunk_erased(dev, chunk); ++ if (erased_ok != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs chunk %d was not erased", ++ chunk); ++ ++ /* If not erased, delete this one, ++ * skip rest of block and ++ * try another chunk */ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ yaffs_skip_rest_of_block(dev); ++ continue; ++ } ++ } ++ ++ write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags); ++ ++ if (!bi->skip_erased_check) ++ write_ok = ++ yaffs_verify_chunk_written(dev, chunk, data, tags); ++ ++ if (write_ok != YAFFS_OK) { ++ /* Clean up aborted write, skip to next block and ++ * try another chunk */ ++ yaffs_handle_chunk_wr_error(dev, chunk, erased_ok); ++ continue; ++ } ++ ++ bi->skip_erased_check = 1; ++ ++ /* Copy the data into the robustification buffer */ ++ yaffs_handle_chunk_wr_ok(dev, chunk, data, tags); ++ ++ } while (write_ok != YAFFS_OK && ++ (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts)); ++ ++ if (!write_ok) ++ chunk = -1; ++ ++ if (attempts > 1) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>> yaffs write required %d attempts", ++ attempts); ++ dev->n_retried_writes += (attempts - 1); ++ } ++ ++ return chunk; ++} ++ ++/* ++ * Block retiring for handling a broken block. ++ */ ++ ++static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block); ++ ++ yaffs2_checkpt_invalidate(dev); ++ ++ yaffs2_clear_oldest_dirty_seq(dev, bi); ++ ++ if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) { ++ if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Failed to mark bad and erase block %d", ++ flash_block); ++ } else { ++ struct yaffs_ext_tags tags; ++ int chunk_id = ++ flash_block * dev->param.chunks_per_block; ++ ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ memset(buffer, 0xff, dev->data_bytes_per_chunk); ++ memset(&tags, 0, sizeof(tags)); ++ tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK; ++ if (dev->tagger.write_chunk_tags_fn(dev, chunk_id - ++ dev->chunk_offset, ++ buffer, ++ &tags) != YAFFS_OK) ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Failed to write bad block marker to block %d", ++ flash_block); ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ } ++ ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ bi->gc_prioritise = 0; ++ bi->needs_retiring = 0; ++ ++ dev->n_retired_blocks++; ++} ++ ++/*---------------- Name handling functions ------------*/ ++ ++static u16 yaffs_calc_name_sum(const YCHAR *name) ++{ ++ u16 sum = 0; ++ u16 i = 1; ++ ++ if (!name) ++ return 0; ++ ++ while ((*name) && i < (YAFFS_MAX_NAME_LENGTH / 2)) { ++ ++ /* 0x1f mask is case insensitive */ ++ sum += ((*name) & 0x1f) * i; ++ i++; ++ name++; ++ } ++ return sum; ++} ++ ++ ++void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name) ++{ ++ memset(obj->short_name, 0, sizeof(obj->short_name)); ++ ++ if (name && !name[0]) { ++ yaffs_fix_null_name(obj, obj->short_name, ++ YAFFS_SHORT_NAME_LENGTH); ++ name = obj->short_name; ++ } else if (name && ++ strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <= ++ YAFFS_SHORT_NAME_LENGTH) { ++ strcpy(obj->short_name, name); ++ } ++ ++ obj->sum = yaffs_calc_name_sum(name); ++} ++ ++void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, ++ const struct yaffs_obj_hdr *oh) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1]; ++ memset(tmp_name, 0, sizeof(tmp_name)); ++ yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name, ++ YAFFS_MAX_NAME_LENGTH + 1); ++ yaffs_set_obj_name(obj, tmp_name); ++#else ++ yaffs_set_obj_name(obj, oh->name); ++#endif ++} ++ ++loff_t yaffs_max_file_size(struct yaffs_dev *dev) ++{ ++ if(sizeof(loff_t) < 8) ++ return YAFFS_MAX_FILE_SIZE_32; ++ else ++ return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk; ++} ++ ++/*-------------------- TNODES ------------------- ++ ++ * List of spare tnodes ++ * The list is hooked together using the first pointer ++ * in the tnode. ++ */ ++ ++struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev) ++{ ++ struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev); ++ ++ if (tn) { ++ memset(tn, 0, dev->tnode_size); ++ dev->n_tnodes++; ++ } ++ ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++ ++ return tn; ++} ++ ++/* FreeTnode frees up a tnode and puts it back on the free list */ ++static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) ++{ ++ yaffs_free_raw_tnode(dev, tn); ++ dev->n_tnodes--; ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ yaffs_deinit_raw_tnodes_and_objs(dev); ++ dev->n_obj = 0; ++ dev->n_tnodes = 0; ++} ++ ++static void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos, unsigned val) ++{ ++ u32 *map = (u32 *) tn; ++ u32 bit_in_map; ++ u32 bit_in_word; ++ u32 word_in_map; ++ u32 mask; ++ ++ pos &= YAFFS_TNODES_LEVEL0_MASK; ++ val >>= dev->chunk_grp_bits; ++ ++ bit_in_map = pos * dev->tnode_width; ++ word_in_map = bit_in_map / 32; ++ bit_in_word = bit_in_map & (32 - 1); ++ ++ mask = dev->tnode_mask << bit_in_word; ++ ++ map[word_in_map] &= ~mask; ++ map[word_in_map] |= (mask & (val << bit_in_word)); ++ ++ if (dev->tnode_width > (32 - bit_in_word)) { ++ bit_in_word = (32 - bit_in_word); ++ word_in_map++; ++ mask = ++ dev->tnode_mask >> bit_in_word; ++ map[word_in_map] &= ~mask; ++ map[word_in_map] |= (mask & (val >> bit_in_word)); ++ } ++} ++ ++u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos) ++{ ++ u32 *map = (u32 *) tn; ++ u32 bit_in_map; ++ u32 bit_in_word; ++ u32 word_in_map; ++ u32 val; ++ ++ pos &= YAFFS_TNODES_LEVEL0_MASK; ++ ++ bit_in_map = pos * dev->tnode_width; ++ word_in_map = bit_in_map / 32; ++ bit_in_word = bit_in_map & (32 - 1); ++ ++ val = map[word_in_map] >> bit_in_word; ++ ++ if (dev->tnode_width > (32 - bit_in_word)) { ++ bit_in_word = (32 - bit_in_word); ++ word_in_map++; ++ val |= (map[word_in_map] << bit_in_word); ++ } ++ ++ val &= dev->tnode_mask; ++ val <<= dev->chunk_grp_bits; ++ ++ return val; ++} ++ ++/* ------------------- End of individual tnode manipulation -----------------*/ ++ ++/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------ ++ * The look up tree is represented by the top tnode and the number of top_level ++ * in the tree. 0 means only the level 0 tnode is in the tree. ++ */ ++ ++/* FindLevel0Tnode finds the level 0 tnode, if one exists. */ ++struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id) ++{ ++ struct yaffs_tnode *tn = file_struct->top; ++ u32 i; ++ int required_depth; ++ int level = file_struct->top_level; ++ ++ (void) dev; ++ ++ /* Check sane level and chunk Id */ ++ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) ++ return NULL; ++ ++ if (chunk_id > YAFFS_MAX_CHUNK_ID) ++ return NULL; ++ ++ /* First check we're tall enough (ie enough top_level) */ ++ ++ i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (i) { ++ i >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ if (required_depth > file_struct->top_level) ++ return NULL; /* Not tall enough, so we can't find it */ ++ ++ /* Traverse down to level 0 */ ++ while (level > 0 && tn) { ++ tn = tn->internal[(chunk_id >> ++ (YAFFS_TNODES_LEVEL0_BITS + ++ (level - 1) * ++ YAFFS_TNODES_INTERNAL_BITS)) & ++ YAFFS_TNODES_INTERNAL_MASK]; ++ level--; ++ } ++ ++ return tn; ++} ++ ++/* add_find_tnode_0 finds the level 0 tnode if it exists, ++ * otherwise first expands the tree. ++ * This happens in two steps: ++ * 1. If the tree isn't tall enough, then make it taller. ++ * 2. Scan down the tree towards the level 0 tnode adding tnodes if required. ++ * ++ * Used when modifying the tree. ++ * ++ * If the tn argument is NULL, then a fresh tnode will be added otherwise the ++ * specified tn will be plugged into the ttree. ++ */ ++ ++struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id, ++ struct yaffs_tnode *passed_tn) ++{ ++ int required_depth; ++ int i; ++ int l; ++ struct yaffs_tnode *tn; ++ u32 x; ++ ++ /* Check sane level and page Id */ ++ if (file_struct->top_level < 0 || ++ file_struct->top_level > YAFFS_TNODES_MAX_LEVEL) ++ return NULL; ++ ++ if (chunk_id > YAFFS_MAX_CHUNK_ID) ++ return NULL; ++ ++ /* First check we're tall enough (ie enough top_level) */ ++ ++ x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (x) { ++ x >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ if (required_depth > file_struct->top_level) { ++ /* Not tall enough, gotta make the tree taller */ ++ for (i = file_struct->top_level; i < required_depth; i++) { ++ ++ tn = yaffs_get_tnode(dev); ++ ++ if (tn) { ++ tn->internal[0] = file_struct->top; ++ file_struct->top = tn; ++ file_struct->top_level++; ++ } else { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs: no more tnodes"); ++ return NULL; ++ } ++ } ++ } ++ ++ /* Traverse down to level 0, adding anything we need */ ++ ++ l = file_struct->top_level; ++ tn = file_struct->top; ++ ++ if (l > 0) { ++ while (l > 0 && tn) { ++ x = (chunk_id >> ++ (YAFFS_TNODES_LEVEL0_BITS + ++ (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) & ++ YAFFS_TNODES_INTERNAL_MASK; ++ ++ if ((l > 1) && !tn->internal[x]) { ++ /* Add missing non-level-zero tnode */ ++ tn->internal[x] = yaffs_get_tnode(dev); ++ if (!tn->internal[x]) ++ return NULL; ++ } else if (l == 1) { ++ /* Looking from level 1 at level 0 */ ++ if (passed_tn) { ++ /* If we already have one, release it */ ++ if (tn->internal[x]) ++ yaffs_free_tnode(dev, ++ tn->internal[x]); ++ tn->internal[x] = passed_tn; ++ ++ } else if (!tn->internal[x]) { ++ /* Don't have one, none passed in */ ++ tn->internal[x] = yaffs_get_tnode(dev); ++ if (!tn->internal[x]) ++ return NULL; ++ } ++ } ++ ++ tn = tn->internal[x]; ++ l--; ++ } ++ } else { ++ /* top is level 0 */ ++ if (passed_tn) { ++ memcpy(tn, passed_tn, ++ (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8); ++ yaffs_free_tnode(dev, passed_tn); ++ } ++ } ++ ++ return tn; ++} ++ ++static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id, ++ int chunk_obj) ++{ ++ return (tags->chunk_id == chunk_obj && ++ tags->obj_id == obj_id && ++ !tags->is_deleted) ? 1 : 0; ++ ++} ++ ++static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk, ++ struct yaffs_ext_tags *tags, int obj_id, ++ int inode_chunk) ++{ ++ int j; ++ ++ for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) { ++ if (yaffs_check_chunk_bit ++ (dev, the_chunk / dev->param.chunks_per_block, ++ the_chunk % dev->param.chunks_per_block)) { ++ ++ if (dev->chunk_grp_size == 1) ++ return the_chunk; ++ else { ++ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL, ++ tags); ++ if (yaffs_tags_match(tags, ++ obj_id, inode_chunk)) { ++ /* found it; */ ++ return the_chunk; ++ } ++ } ++ } ++ the_chunk++; ++ } ++ return -1; ++} ++ ++static int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ struct yaffs_ext_tags *tags) ++{ ++ /*Get the Tnode, then get the level 0 offset chunk offset */ ++ struct yaffs_tnode *tn; ++ int the_chunk = -1; ++ struct yaffs_ext_tags local_tags; ++ int ret_val = -1; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!tags) { ++ /* Passed a NULL, so use our own tags space */ ++ tags = &local_tags; ++ } ++ ++ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk); ++ ++ if (!tn) ++ return ret_val; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id, ++ inode_chunk); ++ return ret_val; ++} ++ ++static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk, ++ struct yaffs_ext_tags *tags) ++{ ++ /* Get the Tnode, then get the level 0 offset chunk offset */ ++ struct yaffs_tnode *tn; ++ int the_chunk = -1; ++ struct yaffs_ext_tags local_tags; ++ struct yaffs_dev *dev = in->my_dev; ++ int ret_val = -1; ++ ++ if (!tags) { ++ /* Passed a NULL, so use our own tags space */ ++ tags = &local_tags; ++ } ++ ++ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk); ++ ++ if (!tn) ++ return ret_val; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id, ++ inode_chunk); ++ ++ /* Delete the entry in the filestructure (if found) */ ++ if (ret_val != -1) ++ yaffs_load_tnode_0(dev, tn, inode_chunk, 0); ++ ++ return ret_val; ++} ++ ++int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ int nand_chunk, int in_scan) ++{ ++ /* NB in_scan is zero unless scanning. ++ * For forward scanning, in_scan is > 0; ++ * for backward scanning in_scan is < 0 ++ * ++ * nand_chunk = 0 is a dummy insert to make sure the tnodes are there. ++ */ ++ ++ struct yaffs_tnode *tn; ++ struct yaffs_dev *dev = in->my_dev; ++ int existing_cunk; ++ struct yaffs_ext_tags existing_tags; ++ struct yaffs_ext_tags new_tags; ++ unsigned existing_serial, new_serial; ++ ++ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) { ++ /* Just ignore an attempt at putting a chunk into a non-file ++ * during scanning. ++ * If it is not during Scanning then something went wrong! ++ */ ++ if (!in_scan) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy:attempt to put data chunk into a non-file" ++ ); ++ BUG(); ++ } ++ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ return YAFFS_OK; ++ } ++ ++ tn = yaffs_add_find_tnode_0(dev, ++ &in->variant.file_variant, ++ inode_chunk, NULL); ++ if (!tn) ++ return YAFFS_FAIL; ++ ++ if (!nand_chunk) ++ /* Dummy insert, bail now */ ++ return YAFFS_OK; ++ ++ existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk); ++ ++ if (in_scan != 0) { ++ /* If we're scanning then we need to test for duplicates ++ * NB This does not need to be efficient since it should only ++ * happen when the power fails during a write, then only one ++ * chunk should ever be affected. ++ * ++ * Correction for YAFFS2: This could happen quite a lot and we ++ * need to think about efficiency! TODO ++ * Update: For backward scanning we don't need to re-read tags ++ * so this is quite cheap. ++ */ ++ ++ if (existing_cunk > 0) { ++ /* NB Right now existing chunk will not be real ++ * chunk_id if the chunk group size > 1 ++ * thus we have to do a FindChunkInFile to get the ++ * real chunk id. ++ * ++ * We have a duplicate now we need to decide which ++ * one to use: ++ * ++ * Backwards scanning YAFFS2: The old one is what ++ * we use, dump the new one. ++ * YAFFS1: Get both sets of tags and compare serial ++ * numbers. ++ */ ++ ++ if (in_scan > 0) { ++ /* Only do this for forward scanning */ ++ yaffs_rd_chunk_tags_nand(dev, ++ nand_chunk, ++ NULL, &new_tags); ++ ++ /* Do a proper find */ ++ existing_cunk = ++ yaffs_find_chunk_in_file(in, inode_chunk, ++ &existing_tags); ++ } ++ ++ if (existing_cunk <= 0) { ++ /*Hoosterman - how did this happen? */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: existing chunk < 0 in scan" ++ ); ++ ++ } ++ ++ /* NB The deleted flags should be false, otherwise ++ * the chunks will not be loaded during a scan ++ */ ++ ++ if (in_scan > 0) { ++ new_serial = new_tags.serial_number; ++ existing_serial = existing_tags.serial_number; ++ } ++ ++ if ((in_scan > 0) && ++ (existing_cunk <= 0 || ++ ((existing_serial + 1) & 3) == new_serial)) { ++ /* Forward scanning. ++ * Use new ++ * Delete the old one and drop through to ++ * update the tnode ++ */ ++ yaffs_chunk_del(dev, existing_cunk, 1, ++ __LINE__); ++ } else { ++ /* Backward scanning or we want to use the ++ * existing one ++ * Delete the new one and return early so that ++ * the tnode isn't changed ++ */ ++ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__); ++ return YAFFS_OK; ++ } ++ } ++ ++ } ++ ++ if (existing_cunk == 0) ++ in->n_data_chunks++; ++ ++ yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk); ++ ++ return YAFFS_OK; ++} ++ ++static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk) ++{ ++ struct yaffs_block_info *the_block; ++ unsigned block_no; ++ ++ yaffs_trace(YAFFS_TRACE_DELETION, "soft delete chunk %d", chunk); ++ ++ block_no = chunk / dev->param.chunks_per_block; ++ the_block = yaffs_get_block_info(dev, block_no); ++ if (the_block) { ++ the_block->soft_del_pages++; ++ dev->n_free_chunks++; ++ yaffs2_update_oldest_dirty_seq(dev, block_no, the_block); ++ } ++} ++ ++/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all ++ * the chunks in the file. ++ * All soft deleting does is increment the block's softdelete count and pulls ++ * the chunk out of the tnode. ++ * Thus, essentially this is the same as DeleteWorker except that the chunks ++ * are soft deleted. ++ */ ++ ++static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn, ++ u32 level, int chunk_offset) ++{ ++ int i; ++ int the_chunk; ++ int all_done = 1; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!tn) ++ return 1; ++ ++ if (level > 0) { ++ for (i = YAFFS_NTNODES_INTERNAL - 1; ++ all_done && i >= 0; ++ i--) { ++ if (tn->internal[i]) { ++ all_done = ++ yaffs_soft_del_worker(in, ++ tn->internal[i], ++ level - 1, ++ (chunk_offset << ++ YAFFS_TNODES_INTERNAL_BITS) ++ + i); ++ if (all_done) { ++ yaffs_free_tnode(dev, ++ tn->internal[i]); ++ tn->internal[i] = NULL; ++ } else { ++ /* Can this happen? */ ++ } ++ } ++ } ++ return (all_done) ? 1 : 0; ++ } ++ ++ /* level 0 */ ++ for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { ++ the_chunk = yaffs_get_group_base(dev, tn, i); ++ if (the_chunk) { ++ yaffs_soft_del_chunk(dev, the_chunk); ++ yaffs_load_tnode_0(dev, tn, i, 0); ++ } ++ } ++ return 1; ++} ++ ++static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ struct yaffs_obj *parent; ++ ++ yaffs_verify_obj_in_dir(obj); ++ parent = obj->parent; ++ ++ yaffs_verify_dir(parent); ++ ++ if (dev && dev->param.remove_obj_fn) ++ dev->param.remove_obj_fn(obj); ++ ++ list_del_init(&obj->siblings); ++ obj->parent = NULL; ++ ++ yaffs_verify_dir(parent); ++} ++ ++void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj) ++{ ++ if (!directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: Trying to add an object to a null pointer directory" ++ ); ++ BUG(); ++ return; ++ } ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: Trying to add an object to a non-directory" ++ ); ++ BUG(); ++ } ++ ++ if (obj->siblings.prev == NULL) { ++ /* Not initialised */ ++ BUG(); ++ } ++ ++ yaffs_verify_dir(directory); ++ ++ yaffs_remove_obj_from_dir(obj); ++ ++ /* Now add it */ ++ list_add(&obj->siblings, &directory->variant.dir_variant.children); ++ obj->parent = directory; ++ ++ if (directory == obj->my_dev->unlinked_dir ++ || directory == obj->my_dev->del_dir) { ++ obj->unlinked = 1; ++ obj->my_dev->n_unlinked_files++; ++ obj->rename_allowed = 0; ++ } ++ ++ yaffs_verify_dir(directory); ++ yaffs_verify_obj_in_dir(obj); ++} ++ ++static int yaffs_change_obj_name(struct yaffs_obj *obj, ++ struct yaffs_obj *new_dir, ++ const YCHAR *new_name, int force, int shadows) ++{ ++ int unlink_op; ++ int del_op; ++ struct yaffs_obj *existing_target; ++ ++ if (new_dir == NULL) ++ new_dir = obj->parent; /* use the old directory */ ++ ++ if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_change_obj_name: new_dir is not a directory" ++ ); ++ BUG(); ++ } ++ ++ unlink_op = (new_dir == obj->my_dev->unlinked_dir); ++ del_op = (new_dir == obj->my_dev->del_dir); ++ ++ existing_target = yaffs_find_by_name(new_dir, new_name); ++ ++ /* If the object is a file going into the unlinked directory, ++ * then it is OK to just stuff it in since duplicate names are OK. ++ * else only proceed if the new name does not exist and we're putting ++ * it into a directory. ++ */ ++ if (!(unlink_op || del_op || force || ++ shadows > 0 || !existing_target) || ++ new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) ++ return YAFFS_FAIL; ++ ++ yaffs_set_obj_name(obj, new_name); ++ obj->dirty = 1; ++ yaffs_add_obj_to_dir(new_dir, obj); ++ ++ if (unlink_op) ++ obj->unlinked = 1; ++ ++ /* If it is a deletion then we mark it as a shrink for gc */ ++ if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >= 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++/*------------------------ Short Operations Cache ------------------------------ ++ * In many situations where there is no high level buffering a lot of ++ * reads might be short sequential reads, and a lot of writes may be short ++ * sequential writes. eg. scanning/writing a jpeg file. ++ * In these cases, a short read/write cache can provide a huge perfomance ++ * benefit with dumb-as-a-rock code. ++ * In Linux, the page cache provides read buffering and the short op cache ++ * provides write buffering. ++ * ++ * There are a small number (~10) of cache chunks per device so that we don't ++ * need a very intelligent search. ++ */ ++ ++static int yaffs_obj_cache_dirty(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ int i; ++ struct yaffs_cache *cache; ++ int n_caches = obj->my_dev->param.n_caches; ++ ++ for (i = 0; i < n_caches; i++) { ++ cache = &dev->cache[i]; ++ if (cache->object == obj && cache->dirty) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void yaffs_flush_file_cache(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ int lowest = -99; /* Stop compiler whining. */ ++ int i; ++ struct yaffs_cache *cache; ++ int chunk_written = 0; ++ int n_caches = obj->my_dev->param.n_caches; ++ ++ if (n_caches < 1) ++ return; ++ do { ++ cache = NULL; ++ ++ /* Find the lowest dirty chunk for this object */ ++ for (i = 0; i < n_caches; i++) { ++ if (dev->cache[i].object == obj && ++ dev->cache[i].dirty) { ++ if (!cache || ++ dev->cache[i].chunk_id < lowest) { ++ cache = &dev->cache[i]; ++ lowest = cache->chunk_id; ++ } ++ } ++ } ++ ++ if (cache && !cache->locked) { ++ /* Write it out and free it up */ ++ chunk_written = ++ yaffs_wr_data_obj(cache->object, ++ cache->chunk_id, ++ cache->data, ++ cache->n_bytes, 1); ++ cache->dirty = 0; ++ cache->object = NULL; ++ } ++ } while (cache && chunk_written > 0); ++ ++ if (cache) ++ /* Hoosterman, disk full while writing cache out. */ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: no space during cache write"); ++} ++ ++/*yaffs_flush_whole_cache(dev) ++ * ++ * ++ */ ++ ++void yaffs_flush_whole_cache(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ int n_caches = dev->param.n_caches; ++ int i; ++ ++ /* Find a dirty object in the cache and flush it... ++ * until there are no further dirty objects. ++ */ ++ do { ++ obj = NULL; ++ for (i = 0; i < n_caches && !obj; i++) { ++ if (dev->cache[i].object && dev->cache[i].dirty) ++ obj = dev->cache[i].object; ++ } ++ if (obj) ++ yaffs_flush_file_cache(obj); ++ } while (obj); ++ ++} ++ ++/* Grab us a cache chunk for use. ++ * First look for an empty one. ++ * Then look for the least recently used non-dirty one. ++ * Then look for the least recently used dirty one...., flush and look again. ++ */ ++static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev) ++{ ++ int i; ++ ++ if (dev->param.n_caches > 0) { ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (!dev->cache[i].object) ++ return &dev->cache[i]; ++ } ++ } ++ return NULL; ++} ++ ++static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev) ++{ ++ struct yaffs_cache *cache; ++ struct yaffs_obj *the_obj; ++ int usage; ++ int i; ++ int pushout; ++ ++ if (dev->param.n_caches < 1) ++ return NULL; ++ ++ /* Try find a non-dirty one... */ ++ ++ cache = yaffs_grab_chunk_worker(dev); ++ ++ if (!cache) { ++ /* They were all dirty, find the LRU object and flush ++ * its cache, then find again. ++ * NB what's here is not very accurate, ++ * we actually flush the object with the LRU chunk. ++ */ ++ ++ /* With locking we can't assume we can use entry zero, ++ * Set the_obj to a valid pointer for Coverity. */ ++ the_obj = dev->cache[0].object; ++ usage = -1; ++ cache = NULL; ++ pushout = -1; ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object && ++ !dev->cache[i].locked && ++ (dev->cache[i].last_use < usage || ++ !cache)) { ++ usage = dev->cache[i].last_use; ++ the_obj = dev->cache[i].object; ++ cache = &dev->cache[i]; ++ pushout = i; ++ } ++ } ++ ++ if (!cache || cache->dirty) { ++ /* Flush and try again */ ++ yaffs_flush_file_cache(the_obj); ++ cache = yaffs_grab_chunk_worker(dev); ++ } ++ } ++ return cache; ++} ++ ++/* Find a cached chunk */ ++static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj, ++ int chunk_id) ++{ ++ struct yaffs_dev *dev = obj->my_dev; ++ int i; ++ ++ if (dev->param.n_caches < 1) ++ return NULL; ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object == obj && ++ dev->cache[i].chunk_id == chunk_id) { ++ dev->cache_hits++; ++ ++ return &dev->cache[i]; ++ } ++ } ++ return NULL; ++} ++ ++/* Mark the chunk for the least recently used algorithym */ ++static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache, ++ int is_write) ++{ ++ int i; ++ ++ if (dev->param.n_caches < 1) ++ return; ++ ++ if (dev->cache_last_use < 0 || ++ dev->cache_last_use > 100000000) { ++ /* Reset the cache usages */ ++ for (i = 1; i < dev->param.n_caches; i++) ++ dev->cache[i].last_use = 0; ++ ++ dev->cache_last_use = 0; ++ } ++ dev->cache_last_use++; ++ cache->last_use = dev->cache_last_use; ++ ++ if (is_write) ++ cache->dirty = 1; ++} ++ ++/* Invalidate a single cache page. ++ * Do this when a whole page gets written, ++ * ie the short cache for this page is no longer valid. ++ */ ++static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id) ++{ ++ struct yaffs_cache *cache; ++ ++ if (object->my_dev->param.n_caches > 0) { ++ cache = yaffs_find_chunk_cache(object, chunk_id); ++ ++ if (cache) ++ cache->object = NULL; ++ } ++} ++ ++/* Invalidate all the cache pages associated with this object ++ * Do this whenever ther file is deleted or resized. ++ */ ++static void yaffs_invalidate_whole_cache(struct yaffs_obj *in) ++{ ++ int i; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (dev->param.n_caches > 0) { ++ /* Invalidate it. */ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].object == in) ++ dev->cache[i].object = NULL; ++ } ++ } ++} ++ ++static void yaffs_unhash_obj(struct yaffs_obj *obj) ++{ ++ int bucket; ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ /* If it is still linked into the bucket list, free from the list */ ++ if (!list_empty(&obj->hash_link)) { ++ list_del_init(&obj->hash_link); ++ bucket = yaffs_hash_fn(obj->obj_id); ++ dev->obj_bucket[bucket].count--; ++ } ++} ++ ++/* FreeObject frees up a Object and puts it back on the free list */ ++static void yaffs_free_obj(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ ++ if (!obj) { ++ BUG(); ++ return; ++ } ++ dev = obj->my_dev; ++ yaffs_trace(YAFFS_TRACE_OS, "FreeObject %p inode %p", ++ obj, obj->my_inode); ++ if (obj->parent) ++ BUG(); ++ if (!list_empty(&obj->siblings)) ++ BUG(); ++ ++ if (obj->my_inode) { ++ /* We're still hooked up to a cached inode. ++ * Don't delete now, but mark for later deletion ++ */ ++ obj->defered_free = 1; ++ return; ++ } ++ ++ yaffs_unhash_obj(obj); ++ ++ yaffs_free_raw_obj(dev, obj); ++ dev->n_obj--; ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++} ++ ++void yaffs_handle_defered_free(struct yaffs_obj *obj) ++{ ++ if (obj->defered_free) ++ yaffs_free_obj(obj); ++} ++ ++static int yaffs_generic_obj_del(struct yaffs_obj *in) ++{ ++ /* Iinvalidate the file's data in the cache, without flushing. */ ++ yaffs_invalidate_whole_cache(in); ++ ++ if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) { ++ /* Move to unlinked directory so we have a deletion record */ ++ yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0, ++ 0); ++ } ++ ++ yaffs_remove_obj_from_dir(in); ++ yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__); ++ in->hdr_chunk = 0; ++ ++ yaffs_free_obj(in); ++ return YAFFS_OK; ++ ++} ++ ++static void yaffs_soft_del_file(struct yaffs_obj *obj) ++{ ++ if (!obj->deleted || ++ obj->variant_type != YAFFS_OBJECT_TYPE_FILE || ++ obj->soft_del) ++ return; ++ ++ if (obj->n_data_chunks <= 0) { ++ /* Empty file with no duplicate object headers, ++ * just delete it immediately */ ++ yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top); ++ obj->variant.file_variant.top = NULL; ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: Deleting empty file %d", ++ obj->obj_id); ++ yaffs_generic_obj_del(obj); ++ } else { ++ yaffs_soft_del_worker(obj, ++ obj->variant.file_variant.top, ++ obj->variant. ++ file_variant.top_level, 0); ++ obj->soft_del = 1; ++ } ++} ++ ++/* Pruning removes any part of the file structure tree that is beyond the ++ * bounds of the file (ie that does not point to chunks). ++ * ++ * A file should only get pruned when its size is reduced. ++ * ++ * Before pruning, the chunks must be pulled from the tree and the ++ * level 0 tnode entries must be zeroed out. ++ * Could also use this for file deletion, but that's probably better handled ++ * by a special case. ++ * ++ * This function is recursive. For levels > 0 the function is called again on ++ * any sub-tree. For level == 0 we just check if the sub-tree has data. ++ * If there is no data in a subtree then it is pruned. ++ */ ++ ++static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev, ++ struct yaffs_tnode *tn, u32 level, ++ int del0) ++{ ++ int i; ++ int has_data; ++ ++ if (!tn) ++ return tn; ++ ++ has_data = 0; ++ ++ if (level > 0) { ++ for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) { ++ if (tn->internal[i]) { ++ tn->internal[i] = ++ yaffs_prune_worker(dev, ++ tn->internal[i], ++ level - 1, ++ (i == 0) ? del0 : 1); ++ } ++ ++ if (tn->internal[i]) ++ has_data++; ++ } ++ } else { ++ int tnode_size_u32 = dev->tnode_size / sizeof(u32); ++ u32 *map = (u32 *) tn; ++ ++ for (i = 0; !has_data && i < tnode_size_u32; i++) { ++ if (map[i]) ++ has_data++; ++ } ++ } ++ ++ if (has_data == 0 && del0) { ++ /* Free and return NULL */ ++ yaffs_free_tnode(dev, tn); ++ tn = NULL; ++ } ++ return tn; ++} ++ ++static int yaffs_prune_tree(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct) ++{ ++ int i; ++ int has_data; ++ int done = 0; ++ struct yaffs_tnode *tn; ++ ++ if (file_struct->top_level < 1) ++ return YAFFS_OK; ++ ++ file_struct->top = ++ yaffs_prune_worker(dev, file_struct->top, file_struct->top_level, 0); ++ ++ /* Now we have a tree with all the non-zero branches NULL but ++ * the height is the same as it was. ++ * Let's see if we can trim internal tnodes to shorten the tree. ++ * We can do this if only the 0th element in the tnode is in use ++ * (ie all the non-zero are NULL) ++ */ ++ ++ while (file_struct->top_level && !done) { ++ tn = file_struct->top; ++ ++ has_data = 0; ++ for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) { ++ if (tn->internal[i]) ++ has_data++; ++ } ++ ++ if (!has_data) { ++ file_struct->top = tn->internal[0]; ++ file_struct->top_level--; ++ yaffs_free_tnode(dev, tn); ++ } else { ++ done = 1; ++ } ++ } ++ ++ return YAFFS_OK; ++} ++ ++/*-------------------- End of File Structure functions.-------------------*/ ++ ++/* alloc_empty_obj gets us a clean Object.*/ ++static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev); ++ ++ if (!obj) ++ return obj; ++ ++ dev->n_obj++; ++ ++ /* Now sweeten it up... */ ++ ++ memset(obj, 0, sizeof(struct yaffs_obj)); ++ obj->being_created = 1; ++ ++ obj->my_dev = dev; ++ obj->hdr_chunk = 0; ++ obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN; ++ INIT_LIST_HEAD(&(obj->hard_links)); ++ INIT_LIST_HEAD(&(obj->hash_link)); ++ INIT_LIST_HEAD(&obj->siblings); ++ ++ /* Now make the directory sane */ ++ if (dev->root_dir) { ++ obj->parent = dev->root_dir; ++ list_add(&(obj->siblings), ++ &dev->root_dir->variant.dir_variant.children); ++ } ++ ++ /* Add it to the lost and found directory. ++ * NB Can't put root or lost-n-found in lost-n-found so ++ * check if lost-n-found exists first ++ */ ++ if (dev->lost_n_found) ++ yaffs_add_obj_to_dir(dev->lost_n_found, obj); ++ ++ obj->being_created = 0; ++ ++ dev->checkpoint_blocks_required = 0; /* force recalculation */ ++ ++ return obj; ++} ++ ++static int yaffs_find_nice_bucket(struct yaffs_dev *dev) ++{ ++ int i; ++ int l = 999; ++ int lowest = 999999; ++ ++ /* Search for the shortest list or one that ++ * isn't too long. ++ */ ++ ++ for (i = 0; i < 10 && lowest > 4; i++) { ++ dev->bucket_finder++; ++ dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS; ++ if (dev->obj_bucket[dev->bucket_finder].count < lowest) { ++ lowest = dev->obj_bucket[dev->bucket_finder].count; ++ l = dev->bucket_finder; ++ } ++ } ++ ++ return l; ++} ++ ++static int yaffs_new_obj_id(struct yaffs_dev *dev) ++{ ++ int bucket = yaffs_find_nice_bucket(dev); ++ int found = 0; ++ struct list_head *i; ++ u32 n = (u32) bucket; ++ ++ /* Now find an object value that has not already been taken ++ * by scanning the list. ++ */ ++ ++ while (!found) { ++ found = 1; ++ n += YAFFS_NOBJECT_BUCKETS; ++ if (1 || dev->obj_bucket[bucket].count > 0) { ++ list_for_each(i, &dev->obj_bucket[bucket].list) { ++ /* If there is already one in the list */ ++ if (i && list_entry(i, struct yaffs_obj, ++ hash_link)->obj_id == n) { ++ found = 0; ++ } ++ } ++ } ++ } ++ return n; ++} ++ ++static void yaffs_hash_obj(struct yaffs_obj *in) ++{ ++ int bucket = yaffs_hash_fn(in->obj_id); ++ struct yaffs_dev *dev = in->my_dev; ++ ++ list_add(&in->hash_link, &dev->obj_bucket[bucket].list); ++ dev->obj_bucket[bucket].count++; ++} ++ ++struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number) ++{ ++ int bucket = yaffs_hash_fn(number); ++ struct list_head *i; ++ struct yaffs_obj *in; ++ ++ list_for_each(i, &dev->obj_bucket[bucket].list) { ++ /* Look if it is in the list */ ++ in = list_entry(i, struct yaffs_obj, hash_link); ++ if (in->obj_id == number) { ++ /* Don't show if it is defered free */ ++ if (in->defered_free) ++ return NULL; ++ return in; ++ } ++ } ++ ++ return NULL; ++} ++ ++static struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number, ++ enum yaffs_obj_type type) ++{ ++ struct yaffs_obj *the_obj = NULL; ++ struct yaffs_tnode *tn = NULL; ++ ++ if (number < 0) ++ number = yaffs_new_obj_id(dev); ++ ++ if (type == YAFFS_OBJECT_TYPE_FILE) { ++ tn = yaffs_get_tnode(dev); ++ if (!tn) ++ return NULL; ++ } ++ ++ the_obj = yaffs_alloc_empty_obj(dev); ++ if (!the_obj) { ++ if (tn) ++ yaffs_free_tnode(dev, tn); ++ return NULL; ++ } ++ ++ the_obj->fake = 0; ++ the_obj->rename_allowed = 1; ++ the_obj->unlink_allowed = 1; ++ the_obj->obj_id = number; ++ yaffs_hash_obj(the_obj); ++ the_obj->variant_type = type; ++ yaffs_load_current_time(the_obj, 1, 1); ++ ++ switch (type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ the_obj->variant.file_variant.file_size = 0; ++ the_obj->variant.file_variant.scanned_size = 0; ++ the_obj->variant.file_variant.shrink_size = ++ yaffs_max_file_size(dev); ++ the_obj->variant.file_variant.top_level = 0; ++ the_obj->variant.file_variant.top = tn; ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ INIT_LIST_HEAD(&the_obj->variant.dir_variant.children); ++ INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* No action required */ ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* todo this should not happen */ ++ break; ++ } ++ return the_obj; ++} ++ ++static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev, ++ int number, u32 mode) ++{ ++ ++ struct yaffs_obj *obj = ++ yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY); ++ ++ if (!obj) ++ return NULL; ++ ++ obj->fake = 1; /* it is fake so it might not use NAND */ ++ obj->rename_allowed = 0; ++ obj->unlink_allowed = 0; ++ obj->deleted = 0; ++ obj->unlinked = 0; ++ obj->yst_mode = mode; ++ obj->my_dev = dev; ++ obj->hdr_chunk = 0; /* Not a valid chunk. */ ++ return obj; ++ ++} ++ ++ ++static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev) ++{ ++ int i; ++ ++ dev->n_obj = 0; ++ dev->n_tnodes = 0; ++ yaffs_init_raw_tnodes_and_objs(dev); ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ INIT_LIST_HEAD(&dev->obj_bucket[i].list); ++ dev->obj_bucket[i].count = 0; ++ } ++} ++ ++struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, ++ int number, ++ enum yaffs_obj_type type) ++{ ++ struct yaffs_obj *the_obj = NULL; ++ ++ if (number > 0) ++ the_obj = yaffs_find_by_number(dev, number); ++ ++ if (!the_obj) ++ the_obj = yaffs_new_obj(dev, number, type); ++ ++ return the_obj; ++ ++} ++ ++YCHAR *yaffs_clone_str(const YCHAR *str) ++{ ++ YCHAR *new_str = NULL; ++ int len; ++ ++ if (!str) ++ str = _Y(""); ++ ++ len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH); ++ new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS); ++ if (new_str) { ++ strncpy(new_str, str, len); ++ new_str[len] = 0; ++ } ++ return new_str; ++ ++} ++/* ++ *yaffs_update_parent() handles fixing a directories mtime and ctime when a new ++ * link (ie. name) is created or deleted in the directory. ++ * ++ * ie. ++ * create dir/a : update dir's mtime/ctime ++ * rm dir/a: update dir's mtime/ctime ++ * modify dir/a: don't update dir's mtimme/ctime ++ * ++ * This can be handled immediately or defered. Defering helps reduce the number ++ * of updates when many files in a directory are changed within a brief period. ++ * ++ * If the directory updating is defered then yaffs_update_dirty_dirs must be ++ * called periodically. ++ */ ++ ++static void yaffs_update_parent(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ ++ if (!obj) ++ return; ++ dev = obj->my_dev; ++ obj->dirty = 1; ++ yaffs_load_current_time(obj, 0, 1); ++ if (dev->param.defered_dir_update) { ++ struct list_head *link = &obj->variant.dir_variant.dirty; ++ ++ if (list_empty(link)) { ++ list_add(link, &dev->dirty_dirs); ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "Added object %d to dirty directories", ++ obj->obj_id); ++ } ++ ++ } else { ++ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); ++ } ++} ++ ++void yaffs_update_dirty_dirs(struct yaffs_dev *dev) ++{ ++ struct list_head *link; ++ struct yaffs_obj *obj; ++ struct yaffs_dir_var *d_s; ++ union yaffs_obj_var *o_v; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update dirty directories"); ++ ++ while (!list_empty(&dev->dirty_dirs)) { ++ link = dev->dirty_dirs.next; ++ list_del_init(link); ++ ++ d_s = list_entry(link, struct yaffs_dir_var, dirty); ++ o_v = list_entry(d_s, union yaffs_obj_var, dir_variant); ++ obj = list_entry(o_v, struct yaffs_obj, variant); ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update directory %d", ++ obj->obj_id); ++ ++ if (obj->dirty) ++ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); ++ } ++} ++ ++/* ++ * Mknod (create) a new object. ++ * equiv_obj only has meaning for a hard link; ++ * alias_str only has meaning for a symlink. ++ * rdev only has meaning for devices (a subset of special objects) ++ */ ++ ++static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type, ++ struct yaffs_obj *parent, ++ const YCHAR *name, ++ u32 mode, ++ u32 uid, ++ u32 gid, ++ struct yaffs_obj *equiv_obj, ++ const YCHAR *alias_str, u32 rdev) ++{ ++ struct yaffs_obj *in; ++ YCHAR *str = NULL; ++ struct yaffs_dev *dev = parent->my_dev; ++ ++ /* Check if the entry exists. ++ * If it does then fail the call since we don't want a dup. */ ++ if (yaffs_find_by_name(parent, name)) ++ return NULL; ++ ++ if (type == YAFFS_OBJECT_TYPE_SYMLINK) { ++ str = yaffs_clone_str(alias_str); ++ if (!str) ++ return NULL; ++ } ++ ++ in = yaffs_new_obj(dev, -1, type); ++ ++ if (!in) { ++ kfree(str); ++ return NULL; ++ } ++ ++ in->hdr_chunk = 0; ++ in->valid = 1; ++ in->variant_type = type; ++ ++ in->yst_mode = mode; ++ ++ yaffs_attribs_init(in, gid, uid, rdev); ++ ++ in->n_data_chunks = 0; ++ ++ yaffs_set_obj_name(in, name); ++ in->dirty = 1; ++ ++ yaffs_add_obj_to_dir(parent, in); ++ ++ in->my_dev = parent->my_dev; ++ ++ switch (type) { ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ in->variant.symlink_variant.alias = str; ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ in->variant.hardlink_variant.equiv_obj = equiv_obj; ++ in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id; ++ list_add(&in->hard_links, &equiv_obj->hard_links); ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* do nothing */ ++ break; ++ } ++ ++ if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) { ++ /* Could not create the object header, fail */ ++ yaffs_del_obj(in); ++ in = NULL; ++ } ++ ++ if (in) ++ yaffs_update_parent(parent); ++ ++ return in; ++} ++ ++struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode, ++ uid, gid, NULL, NULL, 0); ++} ++ ++struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, ++ u32 mode, u32 uid, u32 gid) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name, ++ mode, uid, gid, NULL, NULL, 0); ++} ++ ++struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, u32 rdev) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode, ++ uid, gid, NULL, NULL, rdev); ++} ++ ++struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, const YCHAR *alias) ++{ ++ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, ++ uid, gid, NULL, alias, 0); ++} ++ ++/* yaffs_link_obj returns the object id of the equivalent object.*/ ++struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name, ++ struct yaffs_obj *equiv_obj) ++{ ++ /* Get the real object in case we were fed a hard link obj */ ++ equiv_obj = yaffs_get_equivalent_obj(equiv_obj); ++ ++ if (yaffs_create_obj(YAFFS_OBJECT_TYPE_HARDLINK, ++ parent, name, 0, 0, 0, ++ equiv_obj, NULL, 0)) ++ return equiv_obj; ++ ++ return NULL; ++ ++} ++ ++ ++ ++/*---------------------- Block Management and Page Allocation -------------*/ ++ ++static void yaffs_deinit_blocks(struct yaffs_dev *dev) ++{ ++ if (dev->block_info_alt && dev->block_info) ++ vfree(dev->block_info); ++ else ++ kfree(dev->block_info); ++ ++ dev->block_info_alt = 0; ++ ++ dev->block_info = NULL; ++ ++ if (dev->chunk_bits_alt && dev->chunk_bits) ++ vfree(dev->chunk_bits); ++ else ++ kfree(dev->chunk_bits); ++ dev->chunk_bits_alt = 0; ++ dev->chunk_bits = NULL; ++} ++ ++static int yaffs_init_blocks(struct yaffs_dev *dev) ++{ ++ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ ++ dev->block_info = NULL; ++ dev->chunk_bits = NULL; ++ dev->alloc_block = -1; /* force it to get a new one */ ++ ++ /* If the first allocation strategy fails, thry the alternate one */ ++ dev->block_info = ++ kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS); ++ if (!dev->block_info) { ++ dev->block_info = ++ vmalloc(n_blocks * sizeof(struct yaffs_block_info)); ++ dev->block_info_alt = 1; ++ } else { ++ dev->block_info_alt = 0; ++ } ++ ++ if (!dev->block_info) ++ goto alloc_error; ++ ++ /* Set up dynamic blockinfo stuff. Round up bytes. */ ++ dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8; ++ dev->chunk_bits = ++ kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS); ++ if (!dev->chunk_bits) { ++ dev->chunk_bits = ++ vmalloc(dev->chunk_bit_stride * n_blocks); ++ dev->chunk_bits_alt = 1; ++ } else { ++ dev->chunk_bits_alt = 0; ++ } ++ if (!dev->chunk_bits) ++ goto alloc_error; ++ ++ ++ memset(dev->block_info, 0, n_blocks * sizeof(struct yaffs_block_info)); ++ memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks); ++ return YAFFS_OK; ++ ++alloc_error: ++ yaffs_deinit_blocks(dev); ++ return YAFFS_FAIL; ++} ++ ++ ++void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no); ++ int erased_ok = 0; ++ int i; ++ ++ /* If the block is still healthy erase it and mark as clean. ++ * If the block has had a data failure, then retire it. ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE, ++ "yaffs_block_became_dirty block %d state %d %s", ++ block_no, bi->block_state, ++ (bi->needs_retiring) ? "needs retiring" : ""); ++ ++ yaffs2_clear_oldest_dirty_seq(dev, bi); ++ ++ bi->block_state = YAFFS_BLOCK_STATE_DIRTY; ++ ++ /* If this is the block being garbage collected then stop gc'ing */ ++ if (block_no == dev->gc_block) ++ dev->gc_block = 0; ++ ++ /* If this block is currently the best candidate for gc ++ * then drop as a candidate */ ++ if (block_no == dev->gc_dirtiest) { ++ dev->gc_dirtiest = 0; ++ dev->gc_pages_in_use = 0; ++ } ++ ++ if (!bi->needs_retiring) { ++ yaffs2_checkpt_invalidate(dev); ++ erased_ok = yaffs_erase_block(dev, block_no); ++ if (!erased_ok) { ++ dev->n_erase_failures++; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Erasure failed %d", block_no); ++ } ++ } ++ ++ /* Verify erasure if needed */ ++ if (erased_ok && ++ ((yaffs_trace_mask & YAFFS_TRACE_ERASE) || ++ !yaffs_skip_verification(dev))) { ++ for (i = 0; i < dev->param.chunks_per_block; i++) { ++ if (!yaffs_check_chunk_erased(dev, ++ block_no * dev->param.chunks_per_block + i)) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ ">>Block %d erasure supposedly OK, but chunk %d not erased", ++ block_no, i); ++ } ++ } ++ } ++ ++ if (!erased_ok) { ++ /* We lost a block of free space */ ++ dev->n_free_chunks -= dev->param.chunks_per_block; ++ yaffs_retire_block(dev, block_no); ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>> Block %d retired", block_no); ++ return; ++ } ++ ++ /* Clean it up... */ ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ bi->seq_number = 0; ++ dev->n_erased_blocks++; ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ bi->has_shrink_hdr = 0; ++ bi->skip_erased_check = 1; /* Clean, so no need to check */ ++ bi->gc_prioritise = 0; ++ bi->has_summary = 0; ++ ++ yaffs_clear_chunk_bits(dev, block_no); ++ ++ yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no); ++} ++ ++static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, ++ int old_chunk, u8 *buffer) ++{ ++ int new_chunk; ++ int mark_flash = 1; ++ struct yaffs_ext_tags tags; ++ struct yaffs_obj *object; ++ int matching_chunk; ++ int ret_val = YAFFS_OK; ++ ++ memset(&tags, 0, sizeof(tags)); ++ yaffs_rd_chunk_tags_nand(dev, old_chunk, ++ buffer, &tags); ++ object = yaffs_find_by_number(dev, tags.obj_id); ++ ++ yaffs_trace(YAFFS_TRACE_GC_DETAIL, ++ "Collecting chunk in block %d, %d %d %d ", ++ dev->gc_chunk, tags.obj_id, ++ tags.chunk_id, tags.n_bytes); ++ ++ if (object && !yaffs_skip_verification(dev)) { ++ if (tags.chunk_id == 0) ++ matching_chunk = ++ object->hdr_chunk; ++ else if (object->soft_del) ++ /* Defeat the test */ ++ matching_chunk = old_chunk; ++ else ++ matching_chunk = ++ yaffs_find_chunk_in_file ++ (object, tags.chunk_id, ++ NULL); ++ ++ if (old_chunk != matching_chunk) ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "gc: page in gc mismatch: %d %d %d %d", ++ old_chunk, ++ matching_chunk, ++ tags.obj_id, ++ tags.chunk_id); ++ } ++ ++ if (!object) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "page %d in gc has no object: %d %d %d ", ++ old_chunk, ++ tags.obj_id, tags.chunk_id, ++ tags.n_bytes); ++ } ++ ++ if (object && ++ object->deleted && ++ object->soft_del && tags.chunk_id != 0) { ++ /* Data chunk in a soft deleted file, ++ * throw it away. ++ * It's a soft deleted data chunk, ++ * No need to copy this, just forget ++ * about it and fix up the object. ++ */ ++ ++ /* Free chunks already includes ++ * softdeleted chunks, how ever this ++ * chunk is going to soon be really ++ * deleted which will increment free ++ * chunks. We have to decrement free ++ * chunks so this works out properly. ++ */ ++ dev->n_free_chunks--; ++ bi->soft_del_pages--; ++ ++ object->n_data_chunks--; ++ if (object->n_data_chunks <= 0) { ++ /* remeber to clean up obj */ ++ dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id; ++ dev->n_clean_ups++; ++ } ++ mark_flash = 0; ++ } else if (object) { ++ /* It's either a data chunk in a live ++ * file or an ObjectHeader, so we're ++ * interested in it. ++ * NB Need to keep the ObjectHeaders of ++ * deleted files until the whole file ++ * has been deleted off ++ */ ++ tags.serial_number++; ++ dev->n_gc_copies++; ++ ++ if (tags.chunk_id == 0) { ++ /* It is an object Id, ++ * We need to nuke the ++ * shrinkheader flags since its ++ * work is done. ++ * Also need to clean up ++ * shadowing. ++ */ ++ struct yaffs_obj_hdr *oh; ++ oh = (struct yaffs_obj_hdr *) buffer; ++ ++ oh->is_shrink = 0; ++ tags.extra_is_shrink = 0; ++ oh->shadows_obj = 0; ++ oh->inband_shadowed_obj_id = 0; ++ tags.extra_shadows = 0; ++ ++ /* Update file size */ ++ if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) { ++ yaffs_oh_size_load(oh, ++ object->variant.file_variant.file_size); ++ tags.extra_file_size = ++ object->variant.file_variant.file_size; ++ } ++ ++ yaffs_verify_oh(object, oh, &tags, 1); ++ new_chunk = ++ yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1); ++ } else { ++ new_chunk = ++ yaffs_write_new_chunk(dev, buffer, &tags, 1); ++ } ++ ++ if (new_chunk < 0) { ++ ret_val = YAFFS_FAIL; ++ } else { ++ ++ /* Now fix up the Tnodes etc. */ ++ ++ if (tags.chunk_id == 0) { ++ /* It's a header */ ++ object->hdr_chunk = new_chunk; ++ object->serial = tags.serial_number; ++ } else { ++ /* It's a data chunk */ ++ yaffs_put_chunk_in_file(object, tags.chunk_id, ++ new_chunk, 0); ++ } ++ } ++ } ++ if (ret_val == YAFFS_OK) ++ yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__); ++ return ret_val; ++} ++ ++static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block) ++{ ++ int old_chunk; ++ int ret_val = YAFFS_OK; ++ int i; ++ int is_checkpt_block; ++ int max_copies; ++ int chunks_before = yaffs_get_erased_chunks(dev); ++ int chunks_after; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block); ++ ++ is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT); ++ ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "Collecting block %d, in use %d, shrink %d, whole_block %d", ++ block, bi->pages_in_use, bi->has_shrink_hdr, ++ whole_block); ++ ++ /*yaffs_verify_free_chunks(dev); */ ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL) ++ bi->block_state = YAFFS_BLOCK_STATE_COLLECTING; ++ ++ bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */ ++ ++ dev->gc_disable = 1; ++ ++ yaffs_summary_gc(dev, block); ++ ++ if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) { ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "Collecting block %d that has no chunks in use", ++ block); ++ yaffs_block_became_dirty(dev, block); ++ } else { ++ ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ yaffs_verify_blk(dev, bi, block); ++ ++ max_copies = (whole_block) ? dev->param.chunks_per_block : 5; ++ old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk; ++ ++ for (/* init already done */ ; ++ ret_val == YAFFS_OK && ++ dev->gc_chunk < dev->param.chunks_per_block && ++ (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) && ++ max_copies > 0; ++ dev->gc_chunk++, old_chunk++) { ++ if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) { ++ /* Page is in use and might need to be copied */ ++ max_copies--; ++ ret_val = yaffs_gc_process_chunk(dev, bi, ++ old_chunk, buffer); ++ } ++ } ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ ++ yaffs_verify_collected_blk(dev, bi, block); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) { ++ /* ++ * The gc did not complete. Set block state back to FULL ++ * because checkpointing does not restore gc. ++ */ ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ } else { ++ /* The gc completed. */ ++ /* Do any required cleanups */ ++ for (i = 0; i < dev->n_clean_ups; i++) { ++ /* Time to delete the file too */ ++ struct yaffs_obj *object = ++ yaffs_find_by_number(dev, dev->gc_cleanup_list[i]); ++ if (object) { ++ yaffs_free_tnode(dev, ++ object->variant.file_variant.top); ++ object->variant.file_variant.top = NULL; ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: About to finally delete object %d", ++ object->obj_id); ++ yaffs_generic_obj_del(object); ++ object->my_dev->n_deleted_files--; ++ } ++ ++ } ++ chunks_after = yaffs_get_erased_chunks(dev); ++ if (chunks_before >= chunks_after) ++ yaffs_trace(YAFFS_TRACE_GC, ++ "gc did not increase free chunks before %d after %d", ++ chunks_before, chunks_after); ++ dev->gc_block = 0; ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ ++ dev->gc_disable = 0; ++ ++ return ret_val; ++} ++ ++/* ++ * find_gc_block() selects the dirtiest block (or close enough) ++ * for garbage collection. ++ */ ++ ++static unsigned yaffs_find_gc_block(struct yaffs_dev *dev, ++ int aggressive, int background) ++{ ++ int i; ++ int iterations; ++ unsigned selected = 0; ++ int prioritised = 0; ++ int prioritised_exist = 0; ++ struct yaffs_block_info *bi; ++ int threshold; ++ ++ /* First let's see if we need to grab a prioritised block */ ++ if (dev->has_pending_prioritised_gc && !aggressive) { ++ dev->gc_dirtiest = 0; ++ bi = dev->block_info; ++ for (i = dev->internal_start_block; ++ i <= dev->internal_end_block && !selected; i++) { ++ ++ if (bi->gc_prioritise) { ++ prioritised_exist = 1; ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL && ++ yaffs_block_ok_for_gc(dev, bi)) { ++ selected = i; ++ prioritised = 1; ++ } ++ } ++ bi++; ++ } ++ ++ /* ++ * If there is a prioritised block and none was selected then ++ * this happened because there is at least one old dirty block ++ * gumming up the works. Let's gc the oldest dirty block. ++ */ ++ ++ if (prioritised_exist && ++ !selected && dev->oldest_dirty_block > 0) ++ selected = dev->oldest_dirty_block; ++ ++ if (!prioritised_exist) /* None found, so we can clear this */ ++ dev->has_pending_prioritised_gc = 0; ++ } ++ ++ /* If we're doing aggressive GC then we are happy to take a less-dirty ++ * block, and search harder. ++ * else (leasurely gc), then we only bother to do this if the ++ * block has only a few pages in use. ++ */ ++ ++ if (!selected) { ++ int pages_used; ++ int n_blocks = ++ dev->internal_end_block - dev->internal_start_block + 1; ++ if (aggressive) { ++ threshold = dev->param.chunks_per_block; ++ iterations = n_blocks; ++ } else { ++ int max_threshold; ++ ++ if (background) ++ max_threshold = dev->param.chunks_per_block / 2; ++ else ++ max_threshold = dev->param.chunks_per_block / 8; ++ ++ if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD) ++ max_threshold = YAFFS_GC_PASSIVE_THRESHOLD; ++ ++ threshold = background ? (dev->gc_not_done + 2) * 2 : 0; ++ if (threshold < YAFFS_GC_PASSIVE_THRESHOLD) ++ threshold = YAFFS_GC_PASSIVE_THRESHOLD; ++ if (threshold > max_threshold) ++ threshold = max_threshold; ++ ++ iterations = n_blocks / 16 + 1; ++ if (iterations > 100) ++ iterations = 100; ++ } ++ ++ for (i = 0; ++ i < iterations && ++ (dev->gc_dirtiest < 1 || ++ dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH); ++ i++) { ++ dev->gc_block_finder++; ++ if (dev->gc_block_finder < dev->internal_start_block || ++ dev->gc_block_finder > dev->internal_end_block) ++ dev->gc_block_finder = ++ dev->internal_start_block; ++ ++ bi = yaffs_get_block_info(dev, dev->gc_block_finder); ++ ++ pages_used = bi->pages_in_use - bi->soft_del_pages; ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL && ++ pages_used < dev->param.chunks_per_block && ++ (dev->gc_dirtiest < 1 || ++ pages_used < dev->gc_pages_in_use) && ++ yaffs_block_ok_for_gc(dev, bi)) { ++ dev->gc_dirtiest = dev->gc_block_finder; ++ dev->gc_pages_in_use = pages_used; ++ } ++ } ++ ++ if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold) ++ selected = dev->gc_dirtiest; ++ } ++ ++ /* ++ * If nothing has been selected for a while, try the oldest dirty ++ * because that's gumming up the works. ++ */ ++ ++ if (!selected && dev->param.is_yaffs2 && ++ dev->gc_not_done >= (background ? 10 : 20)) { ++ yaffs2_find_oldest_dirty_seq(dev); ++ if (dev->oldest_dirty_block > 0) { ++ selected = dev->oldest_dirty_block; ++ dev->gc_dirtiest = selected; ++ dev->oldest_dirty_gc_count++; ++ bi = yaffs_get_block_info(dev, selected); ++ dev->gc_pages_in_use = ++ bi->pages_in_use - bi->soft_del_pages; ++ } else { ++ dev->gc_not_done = 0; ++ } ++ } ++ ++ if (selected) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC Selected block %d with %d free, prioritised:%d", ++ selected, ++ dev->param.chunks_per_block - dev->gc_pages_in_use, ++ prioritised); ++ ++ dev->n_gc_blocks++; ++ if (background) ++ dev->bg_gcs++; ++ ++ dev->gc_dirtiest = 0; ++ dev->gc_pages_in_use = 0; ++ dev->gc_not_done = 0; ++ if (dev->refresh_skip > 0) ++ dev->refresh_skip--; ++ } else { ++ dev->gc_not_done++; ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s", ++ dev->gc_block_finder, dev->gc_not_done, threshold, ++ dev->gc_dirtiest, dev->gc_pages_in_use, ++ dev->oldest_dirty_block, background ? " bg" : ""); ++ } ++ ++ return selected; ++} ++ ++/* New garbage collector ++ * If we're very low on erased blocks then we do aggressive garbage collection ++ * otherwise we do "leasurely" garbage collection. ++ * Aggressive gc looks further (whole array) and will accept less dirty blocks. ++ * Passive gc only inspects smaller areas and only accepts more dirty blocks. ++ * ++ * The idea is to help clear out space in a more spread-out manner. ++ * Dunno if it really does anything useful. ++ */ ++static int yaffs_check_gc(struct yaffs_dev *dev, int background) ++{ ++ int aggressive = 0; ++ int gc_ok = YAFFS_OK; ++ int max_tries = 0; ++ int min_erased; ++ int erased_chunks; ++ int checkpt_block_adjust; ++ ++ if (dev->param.gc_control_fn && ++ (dev->param.gc_control_fn(dev) & 1) == 0) ++ return YAFFS_OK; ++ ++ if (dev->gc_disable) ++ /* Bail out so we don't get recursive gc */ ++ return YAFFS_OK; ++ ++ /* This loop should pass the first time. ++ * Only loops here if the collection does not increase space. ++ */ ++ ++ do { ++ max_tries++; ++ ++ checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev); ++ ++ min_erased = ++ dev->param.n_reserved_blocks + checkpt_block_adjust + 1; ++ erased_chunks = ++ dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ /* If we need a block soon then do aggressive gc. */ ++ if (dev->n_erased_blocks < min_erased) ++ aggressive = 1; ++ else { ++ if (!background ++ && erased_chunks > (dev->n_free_chunks / 4)) ++ break; ++ ++ if (dev->gc_skip > 20) ++ dev->gc_skip = 20; ++ if (erased_chunks < dev->n_free_chunks / 2 || ++ dev->gc_skip < 1 || background) ++ aggressive = 0; ++ else { ++ dev->gc_skip--; ++ break; ++ } ++ } ++ ++ dev->gc_skip = 5; ++ ++ /* If we don't already have a block being gc'd then see if we ++ * should start another */ ++ ++ if (dev->gc_block < 1 && !aggressive) { ++ dev->gc_block = yaffs2_find_refresh_block(dev); ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ if (dev->gc_block < 1) { ++ dev->gc_block = ++ yaffs_find_gc_block(dev, aggressive, background); ++ dev->gc_chunk = 0; ++ dev->n_clean_ups = 0; ++ } ++ ++ if (dev->gc_block > 0) { ++ dev->all_gcs++; ++ if (!aggressive) ++ dev->passive_gc_count++; ++ ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: GC n_erased_blocks %d aggressive %d", ++ dev->n_erased_blocks, aggressive); ++ ++ gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive); ++ } ++ ++ if (dev->n_erased_blocks < (dev->param.n_reserved_blocks) && ++ dev->gc_block > 0) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d", ++ dev->n_erased_blocks, max_tries, ++ dev->gc_block); ++ } ++ } while ((dev->n_erased_blocks < dev->param.n_reserved_blocks) && ++ (dev->gc_block > 0) && (max_tries < 2)); ++ ++ return aggressive ? gc_ok : YAFFS_OK; ++} ++ ++/* ++ * yaffs_bg_gc() ++ * Garbage collects. Intended to be called from a background thread. ++ * Returns non-zero if at least half the free chunks are erased. ++ */ ++int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency) ++{ ++ int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency); ++ ++ yaffs_check_gc(dev, 1); ++ return erased_chunks > dev->n_free_chunks / 2; ++} ++ ++/*-------------------- Data file manipulation -----------------*/ ++ ++static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer) ++{ ++ int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL); ++ ++ if (nand_chunk >= 0) ++ return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk, ++ buffer, NULL); ++ else { ++ yaffs_trace(YAFFS_TRACE_NANDACCESS, ++ "Chunk %d not found zero instead", ++ nand_chunk); ++ /* get sane (zero) data if you read a hole */ ++ memset(buffer, 0, in->my_dev->data_bytes_per_chunk); ++ return 0; ++ } ++ ++} ++ ++void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, ++ int lyn) ++{ ++ int block; ++ int page; ++ struct yaffs_ext_tags tags; ++ struct yaffs_block_info *bi; ++ ++ if (chunk_id <= 0) ++ return; ++ ++ dev->n_deletions++; ++ block = chunk_id / dev->param.chunks_per_block; ++ page = chunk_id % dev->param.chunks_per_block; ++ ++ if (!yaffs_check_chunk_bit(dev, block, page)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Deleting invalid chunk %d", chunk_id); ++ ++ bi = yaffs_get_block_info(dev, block); ++ ++ yaffs2_update_oldest_dirty_seq(dev, block, bi); ++ ++ yaffs_trace(YAFFS_TRACE_DELETION, ++ "line %d delete of chunk %d", ++ lyn, chunk_id); ++ ++ if (!dev->param.is_yaffs2 && mark_flash && ++ bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) { ++ ++ memset(&tags, 0, sizeof(tags)); ++ tags.is_deleted = 1; ++ yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags); ++ yaffs_handle_chunk_update(dev, chunk_id, &tags); ++ } else { ++ dev->n_unmarked_deletions++; ++ } ++ ++ /* Pull out of the management area. ++ * If the whole block became dirty, this will kick off an erasure. ++ */ ++ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING || ++ bi->block_state == YAFFS_BLOCK_STATE_FULL || ++ bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) { ++ dev->n_free_chunks++; ++ yaffs_clear_chunk_bit(dev, block, page); ++ bi->pages_in_use--; ++ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING && ++ bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ yaffs_block_became_dirty(dev, block); ++ } ++ } ++} ++ ++static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk, ++ const u8 *buffer, int n_bytes, int use_reserve) ++{ ++ /* Find old chunk Need to do this to get serial number ++ * Write new one and patch into tree. ++ * Invalidate old tags. ++ */ ++ ++ int prev_chunk_id; ++ struct yaffs_ext_tags prev_tags; ++ int new_chunk_id; ++ struct yaffs_ext_tags new_tags; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ yaffs_check_gc(dev, 0); ++ ++ /* Get the previous chunk at this location in the file if it exists. ++ * If it does not exist then put a zero into the tree. This creates ++ * the tnode now, rather than later when it is harder to clean up. ++ */ ++ prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags); ++ if (prev_chunk_id < 1 && ++ !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0)) ++ return 0; ++ ++ /* Set up new tags */ ++ memset(&new_tags, 0, sizeof(new_tags)); ++ ++ new_tags.chunk_id = inode_chunk; ++ new_tags.obj_id = in->obj_id; ++ new_tags.serial_number = ++ (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1; ++ new_tags.n_bytes = n_bytes; ++ ++ if (n_bytes < 1 || n_bytes > dev->param.total_bytes_per_chunk) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Writing %d bytes to chunk!!!!!!!!!", ++ n_bytes); ++ BUG(); ++ } ++ ++ new_chunk_id = ++ yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve); ++ ++ if (new_chunk_id > 0) { ++ yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0); ++ ++ if (prev_chunk_id > 0) ++ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__); ++ ++ yaffs_verify_file_sane(in); ++ } ++ return new_chunk_id; ++ ++} ++ ++ ++ ++static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set, ++ const YCHAR *name, const void *value, int size, ++ int flags) ++{ ++ struct yaffs_xattr_mod xmod; ++ int result; ++ ++ xmod.set = set; ++ xmod.name = name; ++ xmod.data = value; ++ xmod.size = size; ++ xmod.flags = flags; ++ xmod.result = -ENOSPC; ++ ++ result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod); ++ ++ if (result > 0) ++ return xmod.result; ++ else ++ return -ENOSPC; ++} ++ ++static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer, ++ struct yaffs_xattr_mod *xmod) ++{ ++ int retval = 0; ++ int x_offs = sizeof(struct yaffs_obj_hdr); ++ struct yaffs_dev *dev = obj->my_dev; ++ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr); ++ char *x_buffer = buffer + x_offs; ++ ++ if (xmod->set) ++ retval = ++ nval_set(x_buffer, x_size, xmod->name, xmod->data, ++ xmod->size, xmod->flags); ++ else ++ retval = nval_del(x_buffer, x_size, xmod->name); ++ ++ obj->has_xattr = nval_hasvalues(x_buffer, x_size); ++ obj->xattr_known = 1; ++ xmod->result = retval; ++ ++ return retval; ++} ++ ++static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR *name, ++ void *value, int size) ++{ ++ char *buffer = NULL; ++ int result; ++ struct yaffs_ext_tags tags; ++ struct yaffs_dev *dev = obj->my_dev; ++ int x_offs = sizeof(struct yaffs_obj_hdr); ++ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr); ++ char *x_buffer; ++ int retval = 0; ++ ++ if (obj->hdr_chunk < 1) ++ return -ENODATA; ++ ++ /* If we know that the object has no xattribs then don't do all the ++ * reading and parsing. ++ */ ++ if (obj->xattr_known && !obj->has_xattr) { ++ if (name) ++ return -ENODATA; ++ else ++ return 0; ++ } ++ ++ buffer = (char *)yaffs_get_temp_buffer(dev); ++ if (!buffer) ++ return -ENOMEM; ++ ++ result = ++ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags); ++ ++ if (result != YAFFS_OK) ++ retval = -ENOENT; ++ else { ++ x_buffer = buffer + x_offs; ++ ++ if (!obj->xattr_known) { ++ obj->has_xattr = nval_hasvalues(x_buffer, x_size); ++ obj->xattr_known = 1; ++ } ++ ++ if (name) ++ retval = nval_get(x_buffer, x_size, name, value, size); ++ else ++ retval = nval_list(x_buffer, x_size, value, size); ++ } ++ yaffs_release_temp_buffer(dev, (u8 *) buffer); ++ return retval; ++} ++ ++int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name, ++ const void *value, int size, int flags) ++{ ++ return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags); ++} ++ ++int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name) ++{ ++ return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0); ++} ++ ++int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value, ++ int size) ++{ ++ return yaffs_do_xattrib_fetch(obj, name, value, size); ++} ++ ++int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size) ++{ ++ return yaffs_do_xattrib_fetch(obj, NULL, buffer, size); ++} ++ ++static void yaffs_check_obj_details_loaded(struct yaffs_obj *in) ++{ ++ u8 *buf; ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_dev *dev; ++ struct yaffs_ext_tags tags; ++ int result; ++ int alloc_failed = 0; ++ ++ if (!in || !in->lazy_loaded || in->hdr_chunk < 1) ++ return; ++ ++ dev = in->my_dev; ++ in->lazy_loaded = 0; ++ buf = yaffs_get_temp_buffer(dev); ++ ++ result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags); ++ oh = (struct yaffs_obj_hdr *)buf; ++ ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ yaffs_set_obj_name_from_oh(in, oh); ++ ++ if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { ++ in->variant.symlink_variant.alias = ++ yaffs_clone_str(oh->alias); ++ if (!in->variant.symlink_variant.alias) ++ alloc_failed = 1; /* Not returned */ ++ } ++ yaffs_release_temp_buffer(dev, buf); ++} ++ ++static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name, ++ const YCHAR *oh_name, int buff_size) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ if (dev->param.auto_unicode) { ++ if (*oh_name) { ++ /* It is an ASCII name, do an ASCII to ++ * unicode conversion */ ++ const char *ascii_oh_name = (const char *)oh_name; ++ int n = buff_size - 1; ++ while (n > 0 && *ascii_oh_name) { ++ *name = *ascii_oh_name; ++ name++; ++ ascii_oh_name++; ++ n--; ++ } ++ } else { ++ strncpy(name, oh_name + 1, buff_size - 1); ++ } ++ } else { ++#else ++ (void) dev; ++ { ++#endif ++ strncpy(name, oh_name, buff_size - 1); ++ } ++} ++ ++static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name, ++ const YCHAR *name) ++{ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ ++ int is_ascii; ++ YCHAR *w; ++ ++ if (dev->param.auto_unicode) { ++ ++ is_ascii = 1; ++ w = name; ++ ++ /* Figure out if the name will fit in ascii character set */ ++ while (is_ascii && *w) { ++ if ((*w) & 0xff00) ++ is_ascii = 0; ++ w++; ++ } ++ ++ if (is_ascii) { ++ /* It is an ASCII name, so convert unicode to ascii */ ++ char *ascii_oh_name = (char *)oh_name; ++ int n = YAFFS_MAX_NAME_LENGTH - 1; ++ while (n > 0 && *name) { ++ *ascii_oh_name = *name; ++ name++; ++ ascii_oh_name++; ++ n--; ++ } ++ } else { ++ /* Unicode name, so save starting at the second YCHAR */ ++ *oh_name = 0; ++ strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2); ++ } ++ } else { ++#else ++ dev = dev; ++ { ++#endif ++ strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1); ++ } ++} ++ ++/* UpdateObjectHeader updates the header on NAND for an object. ++ * If name is not NULL, then that new name is used. ++ */ ++int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, ++ int is_shrink, int shadows, struct yaffs_xattr_mod *xmod) ++{ ++ ++ struct yaffs_block_info *bi; ++ struct yaffs_dev *dev = in->my_dev; ++ int prev_chunk_id; ++ int ret_val = 0; ++ int result = 0; ++ int new_chunk_id; ++ struct yaffs_ext_tags new_tags; ++ struct yaffs_ext_tags old_tags; ++ const YCHAR *alias = NULL; ++ u8 *buffer = NULL; ++ YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1]; ++ struct yaffs_obj_hdr *oh = NULL; ++ loff_t file_size = 0; ++ ++ strcpy(old_name, _Y("silly old name")); ++ ++ if (in->fake && in != dev->root_dir && !force && !xmod) ++ return ret_val; ++ ++ yaffs_check_gc(dev, 0); ++ yaffs_check_obj_details_loaded(in); ++ ++ buffer = yaffs_get_temp_buffer(in->my_dev); ++ oh = (struct yaffs_obj_hdr *)buffer; ++ ++ prev_chunk_id = in->hdr_chunk; ++ ++ if (prev_chunk_id > 0) { ++ result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id, ++ buffer, &old_tags); ++ ++ yaffs_verify_oh(in, oh, &old_tags, 0); ++ memcpy(old_name, oh->name, sizeof(oh->name)); ++ memset(buffer, 0xff, sizeof(struct yaffs_obj_hdr)); ++ } else { ++ memset(buffer, 0xff, dev->data_bytes_per_chunk); ++ } ++ ++ oh->type = in->variant_type; ++ oh->yst_mode = in->yst_mode; ++ oh->shadows_obj = oh->inband_shadowed_obj_id = shadows; ++ ++ yaffs_load_attribs_oh(oh, in); ++ ++ if (in->parent) ++ oh->parent_obj_id = in->parent->obj_id; ++ else ++ oh->parent_obj_id = 0; ++ ++ if (name && *name) { ++ memset(oh->name, 0, sizeof(oh->name)); ++ yaffs_load_oh_from_name(dev, oh->name, name); ++ } else if (prev_chunk_id > 0) { ++ memcpy(oh->name, old_name, sizeof(oh->name)); ++ } else { ++ memset(oh->name, 0, sizeof(oh->name)); ++ } ++ ++ oh->is_shrink = is_shrink; ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Should not happen */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED && ++ oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED) ++ file_size = in->variant.file_variant.file_size; ++ yaffs_oh_size_load(oh, file_size); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ oh->equiv_id = in->variant.hardlink_variant.equiv_id; ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ alias = in->variant.symlink_variant.alias; ++ if (!alias) ++ alias = _Y("no alias"); ++ strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH); ++ oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; ++ break; ++ } ++ ++ /* process any xattrib modifications */ ++ if (xmod) ++ yaffs_apply_xattrib_mod(in, (char *)buffer, xmod); ++ ++ /* Tags */ ++ memset(&new_tags, 0, sizeof(new_tags)); ++ in->serial++; ++ new_tags.chunk_id = 0; ++ new_tags.obj_id = in->obj_id; ++ new_tags.serial_number = in->serial; ++ ++ /* Add extra info for file header */ ++ new_tags.extra_available = 1; ++ new_tags.extra_parent_id = oh->parent_obj_id; ++ new_tags.extra_file_size = file_size; ++ new_tags.extra_is_shrink = oh->is_shrink; ++ new_tags.extra_equiv_id = oh->equiv_id; ++ new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0; ++ new_tags.extra_obj_type = in->variant_type; ++ yaffs_verify_oh(in, oh, &new_tags, 1); ++ ++ /* Create new chunk in NAND */ ++ new_chunk_id = ++ yaffs_write_new_chunk(dev, buffer, &new_tags, ++ (prev_chunk_id > 0) ? 1 : 0); ++ ++ if (buffer) ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ if (new_chunk_id < 0) ++ return new_chunk_id; ++ ++ in->hdr_chunk = new_chunk_id; ++ ++ if (prev_chunk_id > 0) ++ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__); ++ ++ if (!yaffs_obj_cache_dirty(in)) ++ in->dirty = 0; ++ ++ /* If this was a shrink, then mark the block ++ * that the chunk lives on */ ++ if (is_shrink) { ++ bi = yaffs_get_block_info(in->my_dev, ++ new_chunk_id / ++ in->my_dev->param.chunks_per_block); ++ bi->has_shrink_hdr = 1; ++ } ++ ++ ++ return new_chunk_id; ++} ++ ++/*--------------------- File read/write ------------------------ ++ * Read and write have very similar structures. ++ * In general the read/write has three parts to it ++ * An incomplete chunk to start with (if the read/write is not chunk-aligned) ++ * Some complete chunks ++ * An incomplete chunk to end off with ++ * ++ * Curve-balls: the first chunk might also be the last chunk. ++ */ ++ ++int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes) ++{ ++ int chunk; ++ u32 start; ++ int n_copy; ++ int n = n_bytes; ++ int n_done = 0; ++ struct yaffs_cache *cache; ++ struct yaffs_dev *dev; ++ ++ dev = in->my_dev; ++ ++ while (n > 0) { ++ yaffs_addr_to_chunk(dev, offset, &chunk, &start); ++ chunk++; ++ ++ /* OK now check for the curveball where the start and end are in ++ * the same chunk. ++ */ ++ if ((start + n) < dev->data_bytes_per_chunk) ++ n_copy = n; ++ else ++ n_copy = dev->data_bytes_per_chunk - start; ++ ++ cache = yaffs_find_chunk_cache(in, chunk); ++ ++ /* If the chunk is already in the cache or it is less than ++ * a whole chunk or we're using inband tags then use the cache ++ * (if there is caching) else bypass the cache. ++ */ ++ if (cache || n_copy != dev->data_bytes_per_chunk || ++ dev->param.inband_tags) { ++ if (dev->param.n_caches > 0) { ++ ++ /* If we can't find the data in the cache, ++ * then load it up. */ ++ ++ if (!cache) { ++ cache = ++ yaffs_grab_chunk_cache(in->my_dev); ++ cache->object = in; ++ cache->chunk_id = chunk; ++ cache->dirty = 0; ++ cache->locked = 0; ++ yaffs_rd_data_obj(in, chunk, ++ cache->data); ++ cache->n_bytes = 0; ++ } ++ ++ yaffs_use_cache(dev, cache, 0); ++ ++ cache->locked = 1; ++ ++ memcpy(buffer, &cache->data[start], n_copy); ++ ++ cache->locked = 0; ++ } else { ++ /* Read into the local buffer then copy.. */ ++ ++ u8 *local_buffer = ++ yaffs_get_temp_buffer(dev); ++ yaffs_rd_data_obj(in, chunk, local_buffer); ++ ++ memcpy(buffer, &local_buffer[start], n_copy); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ } else { ++ /* A full chunk. Read directly into the buffer. */ ++ yaffs_rd_data_obj(in, chunk, buffer); ++ } ++ n -= n_copy; ++ offset += n_copy; ++ buffer += n_copy; ++ n_done += n_copy; ++ } ++ return n_done; ++} ++ ++int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_through) ++{ ++ ++ int chunk; ++ u32 start; ++ int n_copy; ++ int n = n_bytes; ++ int n_done = 0; ++ int n_writeback; ++ loff_t start_write = offset; ++ int chunk_written = 0; ++ u32 n_bytes_read; ++ loff_t chunk_start; ++ struct yaffs_dev *dev; ++ ++ dev = in->my_dev; ++ ++ while (n > 0 && chunk_written >= 0) { ++ yaffs_addr_to_chunk(dev, offset, &chunk, &start); ++ ++ if (((loff_t)chunk) * ++ dev->data_bytes_per_chunk + start != offset || ++ start >= dev->data_bytes_per_chunk) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "AddrToChunk of offset %lld gives chunk %d start %d", ++ offset, chunk, start); ++ } ++ chunk++; /* File pos to chunk in file offset */ ++ ++ /* OK now check for the curveball where the start and end are in ++ * the same chunk. ++ */ ++ ++ if ((start + n) < dev->data_bytes_per_chunk) { ++ n_copy = n; ++ ++ /* Now calculate how many bytes to write back.... ++ * If we're overwriting and not writing to then end of ++ * file then we need to write back as much as was there ++ * before. ++ */ ++ ++ chunk_start = (((loff_t)(chunk - 1)) * ++ dev->data_bytes_per_chunk); ++ ++ if (chunk_start > in->variant.file_variant.file_size) ++ n_bytes_read = 0; /* Past end of file */ ++ else ++ n_bytes_read = ++ in->variant.file_variant.file_size - ++ chunk_start; ++ ++ if (n_bytes_read > dev->data_bytes_per_chunk) ++ n_bytes_read = dev->data_bytes_per_chunk; ++ ++ n_writeback = ++ (n_bytes_read > ++ (start + n)) ? n_bytes_read : (start + n); ++ ++ if (n_writeback < 0 || ++ n_writeback > dev->data_bytes_per_chunk) ++ BUG(); ++ ++ } else { ++ n_copy = dev->data_bytes_per_chunk - start; ++ n_writeback = dev->data_bytes_per_chunk; ++ } ++ ++ if (n_copy != dev->data_bytes_per_chunk || ++ !dev->param.cache_bypass_aligned || ++ dev->param.inband_tags) { ++ /* An incomplete start or end chunk (or maybe both ++ * start and end chunk), or we're using inband tags, ++ * or we're forcing writes through the cache, ++ * so we want to use the cache buffers. ++ */ ++ if (dev->param.n_caches > 0) { ++ struct yaffs_cache *cache; ++ ++ /* If we can't find the data in the cache, then ++ * load the cache */ ++ cache = yaffs_find_chunk_cache(in, chunk); ++ ++ if (!cache && ++ yaffs_check_alloc_available(dev, 1)) { ++ cache = yaffs_grab_chunk_cache(dev); ++ cache->object = in; ++ cache->chunk_id = chunk; ++ cache->dirty = 0; ++ cache->locked = 0; ++ yaffs_rd_data_obj(in, chunk, ++ cache->data); ++ } else if (cache && ++ !cache->dirty && ++ !yaffs_check_alloc_available(dev, ++ 1)) { ++ /* Drop the cache if it was a read cache ++ * item and no space check has been made ++ * for it. ++ */ ++ cache = NULL; ++ } ++ ++ if (cache) { ++ yaffs_use_cache(dev, cache, 1); ++ cache->locked = 1; ++ ++ memcpy(&cache->data[start], buffer, ++ n_copy); ++ ++ cache->locked = 0; ++ cache->n_bytes = n_writeback; ++ ++ if (write_through) { ++ chunk_written = ++ yaffs_wr_data_obj ++ (cache->object, ++ cache->chunk_id, ++ cache->data, ++ cache->n_bytes, 1); ++ cache->dirty = 0; ++ } ++ } else { ++ chunk_written = -1; /* fail write */ ++ } ++ } else { ++ /* An incomplete start or end chunk (or maybe ++ * both start and end chunk). Read into the ++ * local buffer then copy over and write back. ++ */ ++ ++ u8 *local_buffer = yaffs_get_temp_buffer(dev); ++ ++ yaffs_rd_data_obj(in, chunk, local_buffer); ++ memcpy(&local_buffer[start], buffer, n_copy); ++ ++ chunk_written = ++ yaffs_wr_data_obj(in, chunk, ++ local_buffer, ++ n_writeback, 0); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ } else { ++ /* A full chunk. Write directly from the buffer. */ ++ ++ chunk_written = ++ yaffs_wr_data_obj(in, chunk, buffer, ++ dev->data_bytes_per_chunk, 0); ++ ++ /* Since we've overwritten the cached data, ++ * we better invalidate it. */ ++ yaffs_invalidate_chunk_cache(in, chunk); ++ } ++ ++ if (chunk_written >= 0) { ++ n -= n_copy; ++ offset += n_copy; ++ buffer += n_copy; ++ n_done += n_copy; ++ } ++ } ++ ++ /* Update file object */ ++ ++ if ((start_write + n_done) > in->variant.file_variant.file_size) ++ in->variant.file_variant.file_size = (start_write + n_done); ++ ++ in->dirty = 1; ++ return n_done; ++} ++ ++int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_through) ++{ ++ yaffs2_handle_hole(in, offset); ++ return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through); ++} ++ ++/* ---------------------- File resizing stuff ------------------ */ ++ ++static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size) ++{ ++ ++ struct yaffs_dev *dev = in->my_dev; ++ loff_t old_size = in->variant.file_variant.file_size; ++ int i; ++ int chunk_id; ++ u32 dummy; ++ int last_del; ++ int start_del; ++ ++ if (old_size > 0) ++ yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy); ++ else ++ last_del = 0; ++ ++ yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1, ++ &start_del, &dummy); ++ last_del++; ++ start_del++; ++ ++ /* Delete backwards so that we don't end up with holes if ++ * power is lost part-way through the operation. ++ */ ++ for (i = last_del; i >= start_del; i--) { ++ /* NB this could be optimised somewhat, ++ * eg. could retrieve the tags and write them without ++ * using yaffs_chunk_del ++ */ ++ ++ chunk_id = yaffs_find_del_file_chunk(in, i, NULL); ++ ++ if (chunk_id < 1) ++ continue; ++ ++ if (chunk_id < ++ (dev->internal_start_block * dev->param.chunks_per_block) || ++ chunk_id >= ++ ((dev->internal_end_block + 1) * ++ dev->param.chunks_per_block)) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Found daft chunk_id %d for %d", ++ chunk_id, i); ++ } else { ++ in->n_data_chunks--; ++ yaffs_chunk_del(dev, chunk_id, 1, __LINE__); ++ } ++ } ++} ++ ++void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size) ++{ ++ int new_full; ++ u32 new_partial; ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ yaffs_addr_to_chunk(dev, new_size, &new_full, &new_partial); ++ ++ yaffs_prune_chunks(obj, new_size); ++ ++ if (new_partial != 0) { ++ int last_chunk = 1 + new_full; ++ u8 *local_buffer = yaffs_get_temp_buffer(dev); ++ ++ /* Rewrite the last chunk with its new size and zero pad */ ++ yaffs_rd_data_obj(obj, last_chunk, local_buffer); ++ memset(local_buffer + new_partial, 0, ++ dev->data_bytes_per_chunk - new_partial); ++ ++ yaffs_wr_data_obj(obj, last_chunk, local_buffer, ++ new_partial, 1); ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ } ++ ++ obj->variant.file_variant.file_size = new_size; ++ ++ yaffs_prune_tree(dev, &obj->variant.file_variant); ++} ++ ++int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) ++{ ++ struct yaffs_dev *dev = in->my_dev; ++ loff_t old_size = in->variant.file_variant.file_size; ++ ++ yaffs_flush_file_cache(in); ++ yaffs_invalidate_whole_cache(in); ++ ++ yaffs_check_gc(dev, 0); ++ ++ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return YAFFS_FAIL; ++ ++ if (new_size == old_size) ++ return YAFFS_OK; ++ ++ if (new_size > old_size) { ++ yaffs2_handle_hole(in, new_size); ++ in->variant.file_variant.file_size = new_size; ++ } else { ++ /* new_size < old_size */ ++ yaffs_resize_file_down(in, new_size); ++ } ++ ++ /* Write a new object header to reflect the resize. ++ * show we've shrunk the file, if need be ++ * Do this only if the file is not in the deleted directories ++ * and is not shadowed. ++ */ ++ if (in->parent && ++ !in->is_shadowed && ++ in->parent->obj_id != YAFFS_OBJECTID_UNLINKED && ++ in->parent->obj_id != YAFFS_OBJECTID_DELETED) ++ yaffs_update_oh(in, NULL, 0, 0, 0, NULL); ++ ++ return YAFFS_OK; ++} ++ ++int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync) ++{ ++ if (!in->dirty) ++ return YAFFS_OK; ++ ++ yaffs_flush_file_cache(in); ++ ++ if (data_sync) ++ return YAFFS_OK; ++ ++ if (update_time) ++ yaffs_load_current_time(in, 0, 0); ++ ++ return (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ? ++ YAFFS_OK : YAFFS_FAIL; ++} ++ ++ ++/* yaffs_del_file deletes the whole file data ++ * and the inode associated with the file. ++ * It does not delete the links associated with the file. ++ */ ++static int yaffs_unlink_file_if_needed(struct yaffs_obj *in) ++{ ++ int ret_val; ++ int del_now = 0; ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (!in->my_inode) ++ del_now = 1; ++ ++ if (del_now) { ++ ret_val = ++ yaffs_change_obj_name(in, in->my_dev->del_dir, ++ _Y("deleted"), 0, 0); ++ yaffs_trace(YAFFS_TRACE_TRACING, ++ "yaffs: immediate deletion of file %d", ++ in->obj_id); ++ in->deleted = 1; ++ in->my_dev->n_deleted_files++; ++ if (dev->param.disable_soft_del || dev->param.is_yaffs2) ++ yaffs_resize_file(in, 0); ++ yaffs_soft_del_file(in); ++ } else { ++ ret_val = ++ yaffs_change_obj_name(in, in->my_dev->unlinked_dir, ++ _Y("unlinked"), 0, 0); ++ } ++ return ret_val; ++} ++ ++static int yaffs_del_file(struct yaffs_obj *in) ++{ ++ int ret_val = YAFFS_OK; ++ int deleted; /* Need to cache value on stack if in is freed */ ++ struct yaffs_dev *dev = in->my_dev; ++ ++ if (dev->param.disable_soft_del || dev->param.is_yaffs2) ++ yaffs_resize_file(in, 0); ++ ++ if (in->n_data_chunks > 0) { ++ /* Use soft deletion if there is data in the file. ++ * That won't be the case if it has been resized to zero. ++ */ ++ if (!in->unlinked) ++ ret_val = yaffs_unlink_file_if_needed(in); ++ ++ deleted = in->deleted; ++ ++ if (ret_val == YAFFS_OK && in->unlinked && !in->deleted) { ++ in->deleted = 1; ++ deleted = 1; ++ in->my_dev->n_deleted_files++; ++ yaffs_soft_del_file(in); ++ } ++ return deleted ? YAFFS_OK : YAFFS_FAIL; ++ } else { ++ /* The file has no data chunks so we toss it immediately */ ++ yaffs_free_tnode(in->my_dev, in->variant.file_variant.top); ++ in->variant.file_variant.top = NULL; ++ yaffs_generic_obj_del(in); ++ ++ return YAFFS_OK; ++ } ++} ++ ++int yaffs_is_non_empty_dir(struct yaffs_obj *obj) ++{ ++ return (obj && ++ obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) && ++ !(list_empty(&obj->variant.dir_variant.children)); ++} ++ ++static int yaffs_del_dir(struct yaffs_obj *obj) ++{ ++ /* First check that the directory is empty. */ ++ if (yaffs_is_non_empty_dir(obj)) ++ return YAFFS_FAIL; ++ ++ return yaffs_generic_obj_del(obj); ++} ++ ++static int yaffs_del_symlink(struct yaffs_obj *in) ++{ ++ kfree(in->variant.symlink_variant.alias); ++ in->variant.symlink_variant.alias = NULL; ++ ++ return yaffs_generic_obj_del(in); ++} ++ ++static int yaffs_del_link(struct yaffs_obj *in) ++{ ++ /* remove this hardlink from the list associated with the equivalent ++ * object ++ */ ++ list_del_init(&in->hard_links); ++ return yaffs_generic_obj_del(in); ++} ++ ++int yaffs_del_obj(struct yaffs_obj *obj) ++{ ++ int ret_val = -1; ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ ret_val = yaffs_del_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ if (!list_empty(&obj->variant.dir_variant.dirty)) { ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "Remove object %d from dirty directories", ++ obj->obj_id); ++ list_del_init(&obj->variant.dir_variant.dirty); ++ } ++ return yaffs_del_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ ret_val = yaffs_del_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ ret_val = yaffs_del_link(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ ret_val = yaffs_generic_obj_del(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ ret_val = 0; ++ break; /* should not happen. */ ++ } ++ return ret_val; ++} ++ ++static int yaffs_unlink_worker(struct yaffs_obj *obj) ++{ ++ int del_now = 0; ++ ++ if (!obj) ++ return YAFFS_FAIL; ++ ++ if (!obj->my_inode) ++ del_now = 1; ++ ++ yaffs_update_parent(obj->parent); ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { ++ return yaffs_del_link(obj); ++ } else if (!list_empty(&obj->hard_links)) { ++ /* Curve ball: We're unlinking an object that has a hardlink. ++ * ++ * This problem arises because we are not strictly following ++ * The Linux link/inode model. ++ * ++ * We can't really delete the object. ++ * Instead, we do the following: ++ * - Select a hardlink. ++ * - Unhook it from the hard links ++ * - Move it from its parent directory so that the rename works. ++ * - Rename the object to the hardlink's name. ++ * - Delete the hardlink ++ */ ++ ++ struct yaffs_obj *hl; ++ struct yaffs_obj *parent; ++ int ret_val; ++ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ hl = list_entry(obj->hard_links.next, struct yaffs_obj, ++ hard_links); ++ ++ yaffs_get_obj_name(hl, name, YAFFS_MAX_NAME_LENGTH + 1); ++ parent = hl->parent; ++ ++ list_del_init(&hl->hard_links); ++ ++ yaffs_add_obj_to_dir(obj->my_dev->unlinked_dir, hl); ++ ++ ret_val = yaffs_change_obj_name(obj, parent, name, 0, 0); ++ ++ if (ret_val == YAFFS_OK) ++ ret_val = yaffs_generic_obj_del(hl); ++ ++ return ret_val; ++ ++ } else if (del_now) { ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return yaffs_del_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ list_del_init(&obj->variant.dir_variant.dirty); ++ return yaffs_del_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ return yaffs_del_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ return yaffs_generic_obj_del(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ default: ++ return YAFFS_FAIL; ++ } ++ } else if (yaffs_is_non_empty_dir(obj)) { ++ return YAFFS_FAIL; ++ } else { ++ return yaffs_change_obj_name(obj, obj->my_dev->unlinked_dir, ++ _Y("unlinked"), 0, 0); ++ } ++} ++ ++static int yaffs_unlink_obj(struct yaffs_obj *obj) ++{ ++ if (obj && obj->unlink_allowed) ++ return yaffs_unlink_worker(obj); ++ ++ return YAFFS_FAIL; ++} ++ ++int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR *name) ++{ ++ struct yaffs_obj *obj; ++ ++ obj = yaffs_find_by_name(dir, name); ++ return yaffs_unlink_obj(obj); ++} ++ ++/* Note: ++ * If old_name is NULL then we take old_dir as the object to be renamed. ++ */ ++int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name, ++ struct yaffs_obj *new_dir, const YCHAR *new_name) ++{ ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_obj *existing_target = NULL; ++ int force = 0; ++ int result; ++ struct yaffs_dev *dev; ++ ++ if (!old_dir || old_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ if (!new_dir || new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ dev = old_dir->my_dev; ++ ++#ifdef CONFIG_YAFFS_CASE_INSENSITIVE ++ /* Special case for case insemsitive systems. ++ * While look-up is case insensitive, the name isn't. ++ * Therefore we might want to change x.txt to X.txt ++ */ ++ if (old_dir == new_dir && ++ old_name && new_name && ++ strcmp(old_name, new_name) == 0) ++ force = 1; ++#endif ++ ++ if (strnlen(new_name, YAFFS_MAX_NAME_LENGTH + 1) > ++ YAFFS_MAX_NAME_LENGTH) ++ /* ENAMETOOLONG */ ++ return YAFFS_FAIL; ++ ++ if (old_name) ++ obj = yaffs_find_by_name(old_dir, old_name); ++ else{ ++ obj = old_dir; ++ old_dir = obj->parent; ++ } ++ ++ if (obj && obj->rename_allowed) { ++ /* Now handle an existing target, if there is one */ ++ existing_target = yaffs_find_by_name(new_dir, new_name); ++ if (yaffs_is_non_empty_dir(existing_target)) { ++ return YAFFS_FAIL; /* ENOTEMPTY */ ++ } else if (existing_target && existing_target != obj) { ++ /* Nuke the target first, using shadowing, ++ * but only if it isn't the same object. ++ * ++ * Note we must disable gc here otherwise it can mess ++ * up the shadowing. ++ * ++ */ ++ dev->gc_disable = 1; ++ yaffs_change_obj_name(obj, new_dir, new_name, force, ++ existing_target->obj_id); ++ existing_target->is_shadowed = 1; ++ yaffs_unlink_obj(existing_target); ++ dev->gc_disable = 0; ++ } ++ ++ result = yaffs_change_obj_name(obj, new_dir, new_name, 1, 0); ++ ++ yaffs_update_parent(old_dir); ++ if (new_dir != old_dir) ++ yaffs_update_parent(new_dir); ++ ++ return result; ++ } ++ return YAFFS_FAIL; ++} ++ ++/*----------------------- Initialisation Scanning ---------------------- */ ++ ++void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, ++ int backward_scanning) ++{ ++ struct yaffs_obj *obj; ++ ++ if (backward_scanning) { ++ /* Handle YAFFS2 case (backward scanning) ++ * If the shadowed object exists then ignore. ++ */ ++ obj = yaffs_find_by_number(dev, obj_id); ++ if (obj) ++ return; ++ } ++ ++ /* Let's create it (if it does not exist) assuming it is a file so that ++ * it can do shrinking etc. ++ * We put it in unlinked dir to be cleaned up after the scanning ++ */ ++ obj = ++ yaffs_find_or_create_by_number(dev, obj_id, YAFFS_OBJECT_TYPE_FILE); ++ if (!obj) ++ return; ++ obj->is_shadowed = 1; ++ yaffs_add_obj_to_dir(dev->unlinked_dir, obj); ++ obj->variant.file_variant.shrink_size = 0; ++ obj->valid = 1; /* So that we don't read any other info. */ ++} ++ ++void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list) ++{ ++ struct list_head *lh; ++ struct list_head *save; ++ struct yaffs_obj *hl; ++ struct yaffs_obj *in; ++ ++ list_for_each_safe(lh, save, hard_list) { ++ hl = list_entry(lh, struct yaffs_obj, hard_links); ++ in = yaffs_find_by_number(dev, ++ hl->variant.hardlink_variant.equiv_id); ++ ++ if (in) { ++ /* Add the hardlink pointers */ ++ hl->variant.hardlink_variant.equiv_obj = in; ++ list_add(&hl->hard_links, &in->hard_links); ++ } else { ++ /* Todo Need to report/handle this better. ++ * Got a problem... hardlink to a non-existant object ++ */ ++ hl->variant.hardlink_variant.equiv_obj = NULL; ++ INIT_LIST_HEAD(&hl->hard_links); ++ } ++ } ++} ++ ++static void yaffs_strip_deleted_objs(struct yaffs_dev *dev) ++{ ++ /* ++ * Sort out state of unlinked and deleted objects after scanning. ++ */ ++ struct list_head *i; ++ struct list_head *n; ++ struct yaffs_obj *l; ++ ++ if (dev->read_only) ++ return; ++ ++ /* Soft delete all the unlinked files */ ++ list_for_each_safe(i, n, ++ &dev->unlinked_dir->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ yaffs_del_obj(l); ++ } ++ ++ list_for_each_safe(i, n, &dev->del_dir->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ yaffs_del_obj(l); ++ } ++} ++ ++/* ++ * This code iterates through all the objects making sure that they are rooted. ++ * Any unrooted objects are re-rooted in lost+found. ++ * An object needs to be in one of: ++ * - Directly under deleted, unlinked ++ * - Directly or indirectly under root. ++ * ++ * Note: ++ * This code assumes that we don't ever change the current relationships ++ * between directories: ++ * root_dir->parent == unlinked_dir->parent == del_dir->parent == NULL ++ * lost-n-found->parent == root_dir ++ * ++ * This fixes the problem where directories might have inadvertently been ++ * deleted leaving the object "hanging" without being rooted in the ++ * directory tree. ++ */ ++ ++static int yaffs_has_null_parent(struct yaffs_dev *dev, struct yaffs_obj *obj) ++{ ++ return (obj == dev->del_dir || ++ obj == dev->unlinked_dir || obj == dev->root_dir); ++} ++ ++static void yaffs_fix_hanging_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_obj *parent; ++ int i; ++ struct list_head *lh; ++ struct list_head *n; ++ int depth_limit; ++ int hanging; ++ ++ if (dev->read_only) ++ return; ++ ++ /* Iterate through the objects in each hash entry, ++ * looking at each object. ++ * Make sure it is rooted. ++ */ ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each_safe(lh, n, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ parent = obj->parent; ++ ++ if (yaffs_has_null_parent(dev, obj)) { ++ /* These directories are not hanging */ ++ hanging = 0; ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ hanging = 1; ++ } else if (yaffs_has_null_parent(dev, parent)) { ++ hanging = 0; ++ } else { ++ /* ++ * Need to follow the parent chain to ++ * see if it is hanging. ++ */ ++ hanging = 0; ++ depth_limit = 100; ++ ++ while (parent != dev->root_dir && ++ parent->parent && ++ parent->parent->variant_type == ++ YAFFS_OBJECT_TYPE_DIRECTORY && ++ depth_limit > 0) { ++ parent = parent->parent; ++ depth_limit--; ++ } ++ if (parent != dev->root_dir) ++ hanging = 1; ++ } ++ if (hanging) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Hanging object %d moved to lost and found", ++ obj->obj_id); ++ yaffs_add_obj_to_dir(dev->lost_n_found, obj); ++ } ++ } ++ } ++} ++ ++/* ++ * Delete directory contents for cleaning up lost and found. ++ */ ++static void yaffs_del_dir_contents(struct yaffs_obj *dir) ++{ ++ struct yaffs_obj *obj; ++ struct list_head *lh; ++ struct list_head *n; ++ ++ if (dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) ++ BUG(); ++ ++ list_for_each_safe(lh, n, &dir->variant.dir_variant.children) { ++ obj = list_entry(lh, struct yaffs_obj, siblings); ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) ++ yaffs_del_dir_contents(obj); ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Deleting lost_found object %d", ++ obj->obj_id); ++ yaffs_unlink_obj(obj); ++ } ++} ++ ++static void yaffs_empty_l_n_f(struct yaffs_dev *dev) ++{ ++ yaffs_del_dir_contents(dev->lost_n_found); ++} ++ ++ ++struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory, ++ const YCHAR *name) ++{ ++ int sum; ++ struct list_head *i; ++ YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1]; ++ struct yaffs_obj *l; ++ ++ if (!name) ++ return NULL; ++ ++ if (!directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_find_by_name: null pointer directory" ++ ); ++ BUG(); ++ return NULL; ++ } ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "tragedy: yaffs_find_by_name: non-directory" ++ ); ++ BUG(); ++ } ++ ++ sum = yaffs_calc_name_sum(name); ++ ++ list_for_each(i, &directory->variant.dir_variant.children) { ++ l = list_entry(i, struct yaffs_obj, siblings); ++ ++ if (l->parent != directory) ++ BUG(); ++ ++ yaffs_check_obj_details_loaded(l); ++ ++ /* Special case for lost-n-found */ ++ if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) { ++ if (!strcmp(name, YAFFS_LOSTNFOUND_NAME)) ++ return l; ++ } else if (l->sum == sum || l->hdr_chunk <= 0) { ++ /* LostnFound chunk called Objxxx ++ * Do a real check ++ */ ++ yaffs_get_obj_name(l, buffer, ++ YAFFS_MAX_NAME_LENGTH + 1); ++ if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH)) ++ return l; ++ } ++ } ++ return NULL; ++} ++ ++/* GetEquivalentObject dereferences any hard links to get to the ++ * actual object. ++ */ ++ ++struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj) ++{ ++ if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) { ++ obj = obj->variant.hardlink_variant.equiv_obj; ++ yaffs_check_obj_details_loaded(obj); ++ } ++ return obj; ++} ++ ++/* ++ * A note or two on object names. ++ * * If the object name is missing, we then make one up in the form objnnn ++ * ++ * * ASCII names are stored in the object header's name field from byte zero ++ * * Unicode names are historically stored starting from byte zero. ++ * ++ * Then there are automatic Unicode names... ++ * The purpose of these is to save names in a way that can be read as ++ * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII ++ * system to share files. ++ * ++ * These automatic unicode are stored slightly differently... ++ * - If the name can fit in the ASCII character space then they are saved as ++ * ascii names as per above. ++ * - If the name needs Unicode then the name is saved in Unicode ++ * starting at oh->name[1]. ++ ++ */ ++static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name, ++ int buffer_size) ++{ ++ /* Create an object name if we could not find one. */ ++ if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) { ++ YCHAR local_name[20]; ++ YCHAR num_string[20]; ++ YCHAR *x = &num_string[19]; ++ unsigned v = obj->obj_id; ++ num_string[19] = 0; ++ while (v > 0) { ++ x--; ++ *x = '0' + (v % 10); ++ v /= 10; ++ } ++ /* make up a name */ ++ strcpy(local_name, YAFFS_LOSTNFOUND_PREFIX); ++ strcat(local_name, x); ++ strncpy(name, local_name, buffer_size - 1); ++ } ++} ++ ++int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size) ++{ ++ memset(name, 0, buffer_size * sizeof(YCHAR)); ++ yaffs_check_obj_details_loaded(obj); ++ if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) { ++ strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1); ++ } else if (obj->short_name[0]) { ++ strcpy(name, obj->short_name); ++ } else if (obj->hdr_chunk > 0) { ++ int result; ++ u8 *buffer = yaffs_get_temp_buffer(obj->my_dev); ++ ++ struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer; ++ ++ memset(buffer, 0, obj->my_dev->data_bytes_per_chunk); ++ ++ if (obj->hdr_chunk > 0) { ++ result = yaffs_rd_chunk_tags_nand(obj->my_dev, ++ obj->hdr_chunk, ++ buffer, NULL); ++ } ++ yaffs_load_name_from_oh(obj->my_dev, name, oh->name, ++ buffer_size); ++ ++ yaffs_release_temp_buffer(obj->my_dev, buffer); ++ } ++ ++ yaffs_fix_null_name(obj, name, buffer_size); ++ ++ return strnlen(name, YAFFS_MAX_NAME_LENGTH); ++} ++ ++loff_t yaffs_get_obj_length(struct yaffs_obj *obj) ++{ ++ /* Dereference any hard linking */ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) ++ return obj->variant.file_variant.file_size; ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { ++ if (!obj->variant.symlink_variant.alias) ++ return 0; ++ return strnlen(obj->variant.symlink_variant.alias, ++ YAFFS_MAX_ALIAS_LENGTH); ++ } else { ++ /* Only a directory should drop through to here */ ++ return obj->my_dev->data_bytes_per_chunk; ++ } ++} ++ ++int yaffs_get_obj_link_count(struct yaffs_obj *obj) ++{ ++ int count = 0; ++ struct list_head *i; ++ ++ if (!obj->unlinked) ++ count++; /* the object itself */ ++ ++ list_for_each(i, &obj->hard_links) ++ count++; /* add the hard links; */ ++ ++ return count; ++} ++ ++int yaffs_get_obj_inode(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ return obj->obj_id; ++} ++ ++unsigned yaffs_get_obj_type(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ return DT_REG; ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ return DT_DIR; ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ return DT_LNK; ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ return DT_REG; ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ if (S_ISFIFO(obj->yst_mode)) ++ return DT_FIFO; ++ if (S_ISCHR(obj->yst_mode)) ++ return DT_CHR; ++ if (S_ISBLK(obj->yst_mode)) ++ return DT_BLK; ++ if (S_ISSOCK(obj->yst_mode)) ++ return DT_SOCK; ++ return DT_REG; ++ break; ++ default: ++ return DT_REG; ++ break; ++ } ++} ++ ++YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj) ++{ ++ obj = yaffs_get_equivalent_obj(obj); ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) ++ return yaffs_clone_str(obj->variant.symlink_variant.alias); ++ else ++ return yaffs_clone_str(_Y("")); ++} ++ ++/*--------------------------- Initialisation code -------------------------- */ ++ ++static int yaffs_check_dev_fns(struct yaffs_dev *dev) ++{ ++ struct yaffs_driver *drv = &dev->drv; ++ struct yaffs_tags_handler *tagger = &dev->tagger; ++ ++ /* Common functions, gotta have */ ++ if (!drv->drv_read_chunk_fn || ++ !drv->drv_write_chunk_fn || ++ !drv->drv_erase_fn) ++ return 0; ++ ++ if (dev->param.is_yaffs2 && ++ (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn)) ++ return 0; ++ ++ /* Install the default tags marshalling functions if needed. */ ++ yaffs_tags_compat_install(dev); ++ yaffs_tags_marshall_install(dev); ++ ++ /* Check we now have the marshalling functions required. */ ++ if (!tagger->write_chunk_tags_fn || ++ !tagger->read_chunk_tags_fn || ++ !tagger->query_block_fn || ++ !tagger->mark_bad_fn) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs_create_initial_dir(struct yaffs_dev *dev) ++{ ++ /* Initialise the unlinked, deleted, root and lost+found directories */ ++ dev->lost_n_found = dev->root_dir = NULL; ++ dev->unlinked_dir = dev->del_dir = NULL; ++ dev->unlinked_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR); ++ dev->del_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_DELETED, S_IFDIR); ++ dev->root_dir = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_ROOT, ++ YAFFS_ROOT_MODE | S_IFDIR); ++ dev->lost_n_found = ++ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_LOSTNFOUND, ++ YAFFS_LOSTNFOUND_MODE | S_IFDIR); ++ ++ if (dev->lost_n_found && dev->root_dir && dev->unlinked_dir ++ && dev->del_dir) { ++ yaffs_add_obj_to_dir(dev->root_dir, dev->lost_n_found); ++ return YAFFS_OK; ++ } ++ return YAFFS_FAIL; ++} ++ ++int yaffs_guts_initialise(struct yaffs_dev *dev) ++{ ++ int init_failed = 0; ++ unsigned x; ++ int bits; ++ ++ yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_guts_initialise()"); ++ ++ /* Check stuff that must be set */ ++ ++ if (!dev) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Need a device" ++ ); ++ return YAFFS_FAIL; ++ } ++ ++ if (dev->is_mounted) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted"); ++ return YAFFS_FAIL; ++ } ++ ++ dev->internal_start_block = dev->param.start_block; ++ dev->internal_end_block = dev->param.end_block; ++ dev->block_offset = 0; ++ dev->chunk_offset = 0; ++ dev->n_free_chunks = 0; ++ ++ dev->gc_block = 0; ++ ++ if (dev->param.start_block == 0) { ++ dev->internal_start_block = dev->param.start_block + 1; ++ dev->internal_end_block = dev->param.end_block + 1; ++ dev->block_offset = 1; ++ dev->chunk_offset = dev->param.chunks_per_block; ++ } ++ ++ /* Check geometry parameters. */ ++ ++ if ((!dev->param.inband_tags && dev->param.is_yaffs2 && ++ dev->param.total_bytes_per_chunk < 1024) || ++ (!dev->param.is_yaffs2 && ++ dev->param.total_bytes_per_chunk < 512) || ++ (dev->param.inband_tags && !dev->param.is_yaffs2) || ++ dev->param.chunks_per_block < 2 || ++ dev->param.n_reserved_blocks < 2 || ++ dev->internal_start_block <= 0 || ++ dev->internal_end_block <= 0 || ++ dev->internal_end_block <= ++ (dev->internal_start_block + dev->param.n_reserved_blocks + 2) ++ ) { ++ /* otherwise it is too small */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "NAND geometry problems: chunk size %d, type is yaffs%s, inband_tags %d ", ++ dev->param.total_bytes_per_chunk, ++ dev->param.is_yaffs2 ? "2" : "", ++ dev->param.inband_tags); ++ return YAFFS_FAIL; ++ } ++ ++ if (yaffs_init_nand(dev) != YAFFS_OK) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed"); ++ return YAFFS_FAIL; ++ } ++ ++ /* Sort out space for inband tags, if required */ ++ if (dev->param.inband_tags) ++ dev->data_bytes_per_chunk = ++ dev->param.total_bytes_per_chunk - ++ sizeof(struct yaffs_packed_tags2_tags_only); ++ else ++ dev->data_bytes_per_chunk = dev->param.total_bytes_per_chunk; ++ ++ /* Got the right mix of functions? */ ++ if (!yaffs_check_dev_fns(dev)) { ++ /* Function missing */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "device function(s) missing or wrong"); ++ ++ return YAFFS_FAIL; ++ } ++ ++ /* Finished with most checks. Further checks happen later on too. */ ++ ++ dev->is_mounted = 1; ++ ++ /* OK now calculate a few things for the device */ ++ ++ /* ++ * Calculate all the chunk size manipulation numbers: ++ */ ++ x = dev->data_bytes_per_chunk; ++ /* We always use dev->chunk_shift and dev->chunk_div */ ++ dev->chunk_shift = calc_shifts(x); ++ x >>= dev->chunk_shift; ++ dev->chunk_div = x; ++ /* We only use chunk mask if chunk_div is 1 */ ++ dev->chunk_mask = (1 << dev->chunk_shift) - 1; ++ ++ /* ++ * Calculate chunk_grp_bits. ++ * We need to find the next power of 2 > than internal_end_block ++ */ ++ ++ x = dev->param.chunks_per_block * (dev->internal_end_block + 1); ++ ++ bits = calc_shifts_ceiling(x); ++ ++ /* Set up tnode width if wide tnodes are enabled. */ ++ if (!dev->param.wide_tnodes_disabled) { ++ /* bits must be even so that we end up with 32-bit words */ ++ if (bits & 1) ++ bits++; ++ if (bits < 16) ++ dev->tnode_width = 16; ++ else ++ dev->tnode_width = bits; ++ } else { ++ dev->tnode_width = 16; ++ } ++ ++ dev->tnode_mask = (1 << dev->tnode_width) - 1; ++ ++ /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled), ++ * so if the bitwidth of the ++ * chunk range we're using is greater than 16 we need ++ * to figure out chunk shift and chunk_grp_size ++ */ ++ ++ if (bits <= dev->tnode_width) ++ dev->chunk_grp_bits = 0; ++ else ++ dev->chunk_grp_bits = bits - dev->tnode_width; ++ ++ dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8; ++ if (dev->tnode_size < sizeof(struct yaffs_tnode)) ++ dev->tnode_size = sizeof(struct yaffs_tnode); ++ ++ dev->chunk_grp_size = 1 << dev->chunk_grp_bits; ++ ++ if (dev->param.chunks_per_block < dev->chunk_grp_size) { ++ /* We have a problem because the soft delete won't work if ++ * the chunk group size > chunks per block. ++ * This can be remedied by using larger "virtual blocks". ++ */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "chunk group too large"); ++ ++ return YAFFS_FAIL; ++ } ++ ++ /* Finished verifying the device, continue with initialisation */ ++ ++ /* More device initialisation */ ++ dev->all_gcs = 0; ++ dev->passive_gc_count = 0; ++ dev->oldest_dirty_gc_count = 0; ++ dev->bg_gcs = 0; ++ dev->gc_block_finder = 0; ++ dev->buffered_block = -1; ++ dev->doing_buffered_block_rewrite = 0; ++ dev->n_deleted_files = 0; ++ dev->n_bg_deletions = 0; ++ dev->n_unlinked_files = 0; ++ dev->n_ecc_fixed = 0; ++ dev->n_ecc_unfixed = 0; ++ dev->n_tags_ecc_fixed = 0; ++ dev->n_tags_ecc_unfixed = 0; ++ dev->n_erase_failures = 0; ++ dev->n_erased_blocks = 0; ++ dev->gc_disable = 0; ++ dev->has_pending_prioritised_gc = 1; ++ /* Assume the worst for now, will get fixed on first GC */ ++ INIT_LIST_HEAD(&dev->dirty_dirs); ++ dev->oldest_dirty_seq = 0; ++ dev->oldest_dirty_block = 0; ++ ++ /* Initialise temporary buffers and caches. */ ++ if (!yaffs_init_tmp_buffers(dev)) ++ init_failed = 1; ++ ++ dev->cache = NULL; ++ dev->gc_cleanup_list = NULL; ++ ++ if (!init_failed && dev->param.n_caches > 0) { ++ int i; ++ void *buf; ++ int cache_bytes = ++ dev->param.n_caches * sizeof(struct yaffs_cache); ++ ++ if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES) ++ dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES; ++ ++ dev->cache = kmalloc(cache_bytes, GFP_NOFS); ++ ++ buf = (u8 *) dev->cache; ++ ++ if (dev->cache) ++ memset(dev->cache, 0, cache_bytes); ++ ++ for (i = 0; i < dev->param.n_caches && buf; i++) { ++ dev->cache[i].object = NULL; ++ dev->cache[i].last_use = 0; ++ dev->cache[i].dirty = 0; ++ dev->cache[i].data = buf = ++ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); ++ } ++ if (!buf) ++ init_failed = 1; ++ ++ dev->cache_last_use = 0; ++ } ++ ++ dev->cache_hits = 0; ++ ++ if (!init_failed) { ++ dev->gc_cleanup_list = ++ kmalloc(dev->param.chunks_per_block * sizeof(u32), ++ GFP_NOFS); ++ if (!dev->gc_cleanup_list) ++ init_failed = 1; ++ } ++ ++ if (dev->param.is_yaffs2) ++ dev->param.use_header_file_size = 1; ++ ++ if (!init_failed && !yaffs_init_blocks(dev)) ++ init_failed = 1; ++ ++ yaffs_init_tnodes_and_objs(dev); ++ ++ if (!init_failed && !yaffs_create_initial_dir(dev)) ++ init_failed = 1; ++ ++ if (!init_failed && dev->param.is_yaffs2 && ++ !dev->param.disable_summary && ++ !yaffs_summary_init(dev)) ++ init_failed = 1; ++ ++ if (!init_failed) { ++ /* Now scan the flash. */ ++ if (dev->param.is_yaffs2) { ++ if (yaffs2_checkpt_restore(dev)) { ++ yaffs_check_obj_details_loaded(dev->root_dir); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT | ++ YAFFS_TRACE_MOUNT, ++ "yaffs: restored from checkpoint" ++ ); ++ } else { ++ ++ /* Clean up the mess caused by an aborted ++ * checkpoint load then scan backwards. ++ */ ++ yaffs_deinit_blocks(dev); ++ ++ yaffs_deinit_tnodes_and_objs(dev); ++ ++ dev->n_erased_blocks = 0; ++ dev->n_free_chunks = 0; ++ dev->alloc_block = -1; ++ dev->alloc_page = -1; ++ dev->n_deleted_files = 0; ++ dev->n_unlinked_files = 0; ++ dev->n_bg_deletions = 0; ++ ++ if (!init_failed && !yaffs_init_blocks(dev)) ++ init_failed = 1; ++ ++ yaffs_init_tnodes_and_objs(dev); ++ ++ if (!init_failed ++ && !yaffs_create_initial_dir(dev)) ++ init_failed = 1; ++ ++ if (!init_failed && !yaffs2_scan_backwards(dev)) ++ init_failed = 1; ++ } ++ } else if (!yaffs1_scan(dev)) { ++ init_failed = 1; ++ } ++ ++ yaffs_strip_deleted_objs(dev); ++ yaffs_fix_hanging_objs(dev); ++ if (dev->param.empty_lost_n_found) ++ yaffs_empty_l_n_f(dev); ++ } ++ ++ if (init_failed) { ++ /* Clean up the mess */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: yaffs_guts_initialise() aborted."); ++ ++ yaffs_deinitialise(dev); ++ return YAFFS_FAIL; ++ } ++ ++ /* Zero out stats */ ++ dev->n_page_reads = 0; ++ dev->n_page_writes = 0; ++ dev->n_erasures = 0; ++ dev->n_gc_copies = 0; ++ dev->n_retried_writes = 0; ++ ++ dev->n_retired_blocks = 0; ++ ++ yaffs_verify_free_chunks(dev); ++ yaffs_verify_blocks(dev); ++ ++ /* Clean up any aborted checkpoint data */ ++ if (!dev->is_checkpointed && dev->blocks_in_checkpt > 0) ++ yaffs2_checkpt_invalidate(dev); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: yaffs_guts_initialise() done."); ++ return YAFFS_OK; ++} ++ ++void yaffs_deinitialise(struct yaffs_dev *dev) ++{ ++ if (dev->is_mounted) { ++ int i; ++ ++ yaffs_deinit_blocks(dev); ++ yaffs_deinit_tnodes_and_objs(dev); ++ yaffs_summary_deinit(dev); ++ ++ if (dev->param.n_caches > 0 && dev->cache) { ++ ++ for (i = 0; i < dev->param.n_caches; i++) { ++ kfree(dev->cache[i].data); ++ dev->cache[i].data = NULL; ++ } ++ ++ kfree(dev->cache); ++ dev->cache = NULL; ++ } ++ ++ kfree(dev->gc_cleanup_list); ++ ++ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) ++ kfree(dev->temp_buffer[i].buffer); ++ ++ dev->is_mounted = 0; ++ ++ yaffs_deinit_nand(dev); ++ } ++} ++ ++int yaffs_count_free_chunks(struct yaffs_dev *dev) ++{ ++ int n_free = 0; ++ int b; ++ struct yaffs_block_info *blk; ++ ++ blk = dev->block_info; ++ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) { ++ switch (blk->block_state) { ++ case YAFFS_BLOCK_STATE_EMPTY: ++ case YAFFS_BLOCK_STATE_ALLOCATING: ++ case YAFFS_BLOCK_STATE_COLLECTING: ++ case YAFFS_BLOCK_STATE_FULL: ++ n_free += ++ (dev->param.chunks_per_block - blk->pages_in_use + ++ blk->soft_del_pages); ++ break; ++ default: ++ break; ++ } ++ blk++; ++ } ++ return n_free; ++} ++ ++int yaffs_get_n_free_chunks(struct yaffs_dev *dev) ++{ ++ /* This is what we report to the outside world */ ++ int n_free; ++ int n_dirty_caches; ++ int blocks_for_checkpt; ++ int i; ++ ++ n_free = dev->n_free_chunks; ++ n_free += dev->n_deleted_files; ++ ++ /* Now count and subtract the number of dirty chunks in the cache. */ ++ ++ for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) { ++ if (dev->cache[i].dirty) ++ n_dirty_caches++; ++ } ++ ++ n_free -= n_dirty_caches; ++ ++ n_free -= ++ ((dev->param.n_reserved_blocks + 1) * dev->param.chunks_per_block); ++ ++ /* Now figure checkpoint space and report that... */ ++ blocks_for_checkpt = yaffs_calc_checkpt_blocks_required(dev); ++ ++ n_free -= (blocks_for_checkpt * dev->param.chunks_per_block); ++ ++ if (n_free < 0) ++ n_free = 0; ++ ++ return n_free; ++} ++ ++ ++int yaffs_format_dev(struct yaffs_dev *dev) ++{ ++ int i; ++ enum yaffs_block_state state; ++ u32 dummy; ++ ++ if(dev->is_mounted) ++ return YAFFS_FAIL; ++ ++ /* ++ * The runtime variables might not have been set up, ++ * so set up what we need. ++ */ ++ dev->internal_start_block = dev->param.start_block; ++ dev->internal_end_block = dev->param.end_block; ++ dev->block_offset = 0; ++ dev->chunk_offset = 0; ++ ++ if (dev->param.start_block == 0) { ++ dev->internal_start_block = dev->param.start_block + 1; ++ dev->internal_end_block = dev->param.end_block + 1; ++ dev->block_offset = 1; ++ dev->chunk_offset = dev->param.chunks_per_block; ++ } ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ yaffs_query_init_block_state(dev, i, &state, &dummy); ++ if (state != YAFFS_BLOCK_STATE_DEAD) ++ yaffs_erase_block(dev, i); ++ } ++ ++ return YAFFS_OK; ++} ++ ++ ++/* ++ * Marshalling functions to get loff_t file sizes into and out of ++ * object headers. ++ */ ++void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize) ++{ ++ oh->file_size_low = (fsize & 0xFFFFFFFF); ++ oh->file_size_high = ((fsize >> 32) & 0xFFFFFFFF); ++} ++ ++loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh) ++{ ++ loff_t retval; ++ ++ if (sizeof(loff_t) >= 8 && ~(oh->file_size_high)) ++ retval = (((loff_t) oh->file_size_high) << 32) | ++ (((loff_t) oh->file_size_low) & 0xFFFFFFFF); ++ else ++ retval = (loff_t) oh->file_size_low; ++ ++ return retval; ++} +diff --git a/fs/yaffs2/yaffs_guts.h b/fs/yaffs2/yaffs_guts.h +new file mode 100755 +index 00000000..64929ed3 +--- /dev/null ++++ b/fs/yaffs2/yaffs_guts.h +@@ -0,0 +1,990 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_GUTS_H__ ++#define __YAFFS_GUTS_H__ ++ ++#include "yportenv.h" ++ ++#define YAFFS_OK 1 ++#define YAFFS_FAIL 0 ++ ++/* Give us a Y=0x59, ++ * Give us an A=0x41, ++ * Give us an FF=0xff ++ * Give us an S=0x53 ++ * And what have we got... ++ */ ++#define YAFFS_MAGIC 0x5941ff53 ++ ++/* ++ * Tnodes form a tree with the tnodes in "levels" ++ * Levels greater than 0 hold 8 slots which point to other tnodes. ++ * Those at level 0 hold 16 slots which point to chunks in NAND. ++ * ++ * A maximum level of 8 thust supports files of size up to: ++ * ++ * 2^(3*MAX_LEVEL+4) ++ * ++ * Thus a max level of 8 supports files with up to 2^^28 chunks which gives ++ * a maximum file size of around 512Gbytees with 2k chunks. ++ */ ++#define YAFFS_NTNODES_LEVEL0 16 ++#define YAFFS_TNODES_LEVEL0_BITS 4 ++#define YAFFS_TNODES_LEVEL0_MASK 0xf ++ ++#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) ++#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) ++#define YAFFS_TNODES_INTERNAL_MASK 0x7 ++#define YAFFS_TNODES_MAX_LEVEL 8 ++#define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \ ++ YAFFS_TNODES_INTERNAL_BITS * \ ++ YAFFS_TNODES_MAX_LEVEL) ++#define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1) ++ ++#define YAFFS_MAX_FILE_SIZE_32 0x7fffffff ++ ++/* Constants for YAFFS1 mode */ ++#define YAFFS_BYTES_PER_SPARE 16 ++#define YAFFS_BYTES_PER_CHUNK 512 ++#define YAFFS_CHUNK_SIZE_SHIFT 9 ++#define YAFFS_CHUNKS_PER_BLOCK 32 ++#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) ++ ++#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024 ++#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 ++ ++ ++ ++#define YAFFS_ALLOCATION_NOBJECTS 100 ++#define YAFFS_ALLOCATION_NTNODES 100 ++#define YAFFS_ALLOCATION_NLINKS 100 ++ ++#define YAFFS_NOBJECT_BUCKETS 256 ++ ++#define YAFFS_OBJECT_SPACE 0x40000 ++#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1) ++ ++/* Binary data version stamps */ ++#define YAFFS_SUMMARY_VERSION 1 ++#define YAFFS_CHECKPOINT_VERSION 7 ++ ++#ifdef CONFIG_YAFFS_UNICODE ++#define YAFFS_MAX_NAME_LENGTH 127 ++#define YAFFS_MAX_ALIAS_LENGTH 79 ++#else ++#define YAFFS_MAX_NAME_LENGTH 255 ++#define YAFFS_MAX_ALIAS_LENGTH 159 ++#endif ++ ++#define YAFFS_SHORT_NAME_LENGTH 15 ++ ++/* Some special object ids for pseudo objects */ ++#define YAFFS_OBJECTID_ROOT 1 ++#define YAFFS_OBJECTID_LOSTNFOUND 2 ++#define YAFFS_OBJECTID_UNLINKED 3 ++#define YAFFS_OBJECTID_DELETED 4 ++ ++/* Fake object Id for summary data */ ++#define YAFFS_OBJECTID_SUMMARY 0x10 ++ ++/* Pseudo object ids for checkpointing */ ++#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20 ++#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21 ++ ++#define YAFFS_MAX_SHORT_OP_CACHES 20 ++ ++#define YAFFS_N_TEMP_BUFFERS 6 ++ ++/* We limit the number attempts at sucessfully saving a chunk of data. ++ * Small-page devices have 32 pages per block; large-page devices have 64. ++ * Default to something in the order of 5 to 10 blocks worth of chunks. ++ */ ++#define YAFFS_WR_ATTEMPTS (5*64) ++ ++/* Sequence numbers are used in YAFFS2 to determine block allocation order. ++ * The range is limited slightly to help distinguish bad numbers from good. ++ * This also allows us to perhaps in the future use special numbers for ++ * special purposes. ++ * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years, ++ * and is a larger number than the lifetime of a 2GB device. ++ */ ++#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 ++#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00 ++ ++/* Special sequence number for bad block that failed to be marked bad */ ++#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000 ++ ++/* ChunkCache is used for short read/write operations.*/ ++struct yaffs_cache { ++ struct yaffs_obj *object; ++ int chunk_id; ++ int last_use; ++ int dirty; ++ int n_bytes; /* Only valid if the cache is dirty */ ++ int locked; /* Can't push out or flush while locked. */ ++ u8 *data; ++}; ++ ++/* yaffs1 tags structures in RAM ++ * NB This uses bitfield. Bitfields should not straddle a u32 boundary ++ * otherwise the structure size will get blown out. ++ */ ++ ++struct yaffs_tags { ++ unsigned chunk_id:20; ++ unsigned serial_number:2; ++ unsigned n_bytes_lsb:10; ++ unsigned obj_id:18; ++ unsigned ecc:12; ++ unsigned n_bytes_msb:2; ++}; ++ ++union yaffs_tags_union { ++ struct yaffs_tags as_tags; ++ u8 as_bytes[8]; ++}; ++ ++ ++/* Stuff used for extended tags in YAFFS2 */ ++ ++enum yaffs_ecc_result { ++ YAFFS_ECC_RESULT_UNKNOWN, ++ YAFFS_ECC_RESULT_NO_ERROR, ++ YAFFS_ECC_RESULT_FIXED, ++ YAFFS_ECC_RESULT_UNFIXED ++}; ++ ++enum yaffs_obj_type { ++ YAFFS_OBJECT_TYPE_UNKNOWN, ++ YAFFS_OBJECT_TYPE_FILE, ++ YAFFS_OBJECT_TYPE_SYMLINK, ++ YAFFS_OBJECT_TYPE_DIRECTORY, ++ YAFFS_OBJECT_TYPE_HARDLINK, ++ YAFFS_OBJECT_TYPE_SPECIAL ++}; ++ ++#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL ++ ++struct yaffs_ext_tags { ++ unsigned chunk_used; /* Status of the chunk: used or unused */ ++ unsigned obj_id; /* If 0 this is not used */ ++ unsigned chunk_id; /* If 0 this is a header, else a data chunk */ ++ unsigned n_bytes; /* Only valid for data chunks */ ++ ++ /* The following stuff only has meaning when we read */ ++ enum yaffs_ecc_result ecc_result; ++ unsigned block_bad; ++ ++ /* YAFFS 1 stuff */ ++ unsigned is_deleted; /* The chunk is marked deleted */ ++ unsigned serial_number; /* Yaffs1 2-bit serial number */ ++ ++ /* YAFFS2 stuff */ ++ unsigned seq_number; /* The sequence number of this block */ ++ ++ /* Extra info if this is an object header (YAFFS2 only) */ ++ ++ unsigned extra_available; /* Extra info available if not zero */ ++ unsigned extra_parent_id; /* The parent object */ ++ unsigned extra_is_shrink; /* Is it a shrink header? */ ++ unsigned extra_shadows; /* Does this shadow another object? */ ++ ++ enum yaffs_obj_type extra_obj_type; /* What object type? */ ++ ++ loff_t extra_file_size; /* Length if it is a file */ ++ unsigned extra_equiv_id; /* Equivalent object for a hard link */ ++}; ++ ++/* Spare structure for YAFFS1 */ ++struct yaffs_spare { ++ u8 tb0; ++ u8 tb1; ++ u8 tb2; ++ u8 tb3; ++ u8 page_status; /* set to 0 to delete the chunk */ ++ u8 block_status; ++ u8 tb4; ++ u8 tb5; ++ u8 ecc1[3]; ++ u8 tb6; ++ u8 tb7; ++ u8 ecc2[3]; ++}; ++ ++/*Special structure for passing through to mtd */ ++struct yaffs_nand_spare { ++ struct yaffs_spare spare; ++ int eccres1; ++ int eccres2; ++}; ++ ++/* Block data in RAM */ ++ ++enum yaffs_block_state { ++ YAFFS_BLOCK_STATE_UNKNOWN = 0, ++ ++ YAFFS_BLOCK_STATE_SCANNING, ++ /* Being scanned */ ++ ++ YAFFS_BLOCK_STATE_NEEDS_SCAN, ++ /* The block might have something on it (ie it is allocating or full, ++ * perhaps empty) but it needs to be scanned to determine its true ++ * state. ++ * This state is only valid during scanning. ++ * NB We tolerate empty because the pre-scanner might be incapable of ++ * deciding ++ * However, if this state is returned on a YAFFS2 device, ++ * then we expect a sequence number ++ */ ++ ++ YAFFS_BLOCK_STATE_EMPTY, ++ /* This block is empty */ ++ ++ YAFFS_BLOCK_STATE_ALLOCATING, ++ /* This block is partially allocated. ++ * At least one page holds valid data. ++ * This is the one currently being used for page ++ * allocation. Should never be more than one of these. ++ * If a block is only partially allocated at mount it is treated as ++ * full. ++ */ ++ ++ YAFFS_BLOCK_STATE_FULL, ++ /* All the pages in this block have been allocated. ++ * If a block was only partially allocated when mounted we treat ++ * it as fully allocated. ++ */ ++ ++ YAFFS_BLOCK_STATE_DIRTY, ++ /* The block was full and now all chunks have been deleted. ++ * Erase me, reuse me. ++ */ ++ ++ YAFFS_BLOCK_STATE_CHECKPOINT, ++ /* This block is assigned to holding checkpoint data. */ ++ ++ YAFFS_BLOCK_STATE_COLLECTING, ++ /* This block is being garbage collected */ ++ ++ YAFFS_BLOCK_STATE_DEAD ++ /* This block has failed and is not in use */ ++}; ++ ++#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) ++ ++struct yaffs_block_info { ++ ++ int soft_del_pages:10; /* number of soft deleted pages */ ++ int pages_in_use:10; /* number of pages in use */ ++ unsigned block_state:4; /* One of the above block states. */ ++ /* NB use unsigned because enum is sometimes ++ * an int */ ++ u32 needs_retiring:1; /* Data has failed on this block, */ ++ /*need to get valid data off and retire*/ ++ u32 skip_erased_check:1;/* Skip the erased check on this block */ ++ u32 gc_prioritise:1; /* An ECC check or blank check has failed. ++ Block should be prioritised for GC */ ++ u32 chunk_error_strikes:3; /* How many times we've had ecc etc ++ failures on this block and tried to reuse it */ ++ u32 has_summary:1; /* The block has a summary */ ++ ++ u32 has_shrink_hdr:1; /* This block has at least one shrink header */ ++ u32 seq_number; /* block sequence number for yaffs2 */ ++ ++}; ++ ++/* -------------------------- Object structure -------------------------------*/ ++/* This is the object structure as stored on NAND */ ++ ++struct yaffs_obj_hdr { ++ enum yaffs_obj_type type; ++ ++ /* Apply to everything */ ++ int parent_obj_id; ++ u16 sum_no_longer_used; /* checksum of name. No longer used */ ++ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ /* The following apply to all object types except for hard links */ ++ u32 yst_mode; /* protection */ ++ ++ u32 yst_uid; ++ u32 yst_gid; ++ u32 yst_atime; ++ u32 yst_mtime; ++ u32 yst_ctime; ++ ++ /* File size applies to files only */ ++ u32 file_size_low; ++ ++ /* Equivalent object id applies to hard links only. */ ++ int equiv_id; ++ ++ /* Alias is for symlinks only. */ ++ YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; ++ ++ u32 yst_rdev; /* stuff for block and char devices (major/min) */ ++ ++ u32 win_ctime[2]; ++ u32 win_atime[2]; ++ u32 win_mtime[2]; ++ ++ u32 inband_shadowed_obj_id; ++ u32 inband_is_shrink; ++ ++ u32 file_size_high; ++ u32 reserved[1]; ++ int shadows_obj; /* This object header shadows the ++ specified object if > 0 */ ++ ++ /* is_shrink applies to object headers written when wemake a hole. */ ++ u32 is_shrink; ++ ++}; ++ ++/*--------------------------- Tnode -------------------------- */ ++ ++struct yaffs_tnode { ++ struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL]; ++}; ++ ++/*------------------------ Object -----------------------------*/ ++/* An object can be one of: ++ * - a directory (no data, has children links ++ * - a regular file (data.... not prunes :->). ++ * - a symlink [symbolic link] (the alias). ++ * - a hard link ++ */ ++ ++struct yaffs_file_var { ++ loff_t file_size; ++ loff_t scanned_size; ++ loff_t shrink_size; ++ int top_level; ++ struct yaffs_tnode *top; ++}; ++ ++struct yaffs_dir_var { ++ struct list_head children; /* list of child links */ ++ struct list_head dirty; /* Entry for list of dirty directories */ ++}; ++ ++struct yaffs_symlink_var { ++ YCHAR *alias; ++}; ++ ++struct yaffs_hardlink_var { ++ struct yaffs_obj *equiv_obj; ++ u32 equiv_id; ++}; ++ ++union yaffs_obj_var { ++ struct yaffs_file_var file_variant; ++ struct yaffs_dir_var dir_variant; ++ struct yaffs_symlink_var symlink_variant; ++ struct yaffs_hardlink_var hardlink_variant; ++}; ++ ++struct yaffs_obj { ++ u8 deleted:1; /* This should only apply to unlinked files. */ ++ u8 soft_del:1; /* it has also been soft deleted */ ++ u8 unlinked:1; /* An unlinked file.*/ ++ u8 fake:1; /* A fake object has no presence on NAND. */ ++ u8 rename_allowed:1; /* Some objects cannot be renamed. */ ++ u8 unlink_allowed:1; ++ u8 dirty:1; /* the object needs to be written to flash */ ++ u8 valid:1; /* When the file system is being loaded up, this ++ * object might be created before the data ++ * is available ++ * ie. file data chunks encountered before ++ * the header. ++ */ ++ u8 lazy_loaded:1; /* This object has been lazy loaded and ++ * is missing some detail */ ++ ++ u8 defered_free:1; /* Object is removed from NAND, but is ++ * still in the inode cache. ++ * Free of object is defered. ++ * until the inode is released. ++ */ ++ u8 being_created:1; /* This object is still being created ++ * so skip some verification checks. */ ++ u8 is_shadowed:1; /* This object is shadowed on the way ++ * to being renamed. */ ++ ++ u8 xattr_known:1; /* We know if this has object has xattribs ++ * or not. */ ++ u8 has_xattr:1; /* This object has xattribs. ++ * Only valid if xattr_known. */ ++ ++ u8 serial; /* serial number of chunk in NAND.*/ ++ u16 sum; /* sum of the name to speed searching */ ++ ++ struct yaffs_dev *my_dev; /* The device I'm on */ ++ ++ struct list_head hash_link; /* list of objects in hash bucket */ ++ ++ struct list_head hard_links; /* hard linked object chain*/ ++ ++ /* directory structure stuff */ ++ /* also used for linking up the free list */ ++ struct yaffs_obj *parent; ++ struct list_head siblings; ++ ++ /* Where's my object header in NAND? */ ++ int hdr_chunk; ++ ++ int n_data_chunks; /* Number of data chunks for this file. */ ++ ++ u32 obj_id; /* the object id value */ ++ ++ u32 yst_mode; ++ ++ YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1]; ++ ++#ifdef CONFIG_YAFFS_WINCE ++ u32 win_ctime[2]; ++ u32 win_mtime[2]; ++ u32 win_atime[2]; ++#else ++ u32 yst_uid; ++ u32 yst_gid; ++ u32 yst_atime; ++ u32 yst_mtime; ++ u32 yst_ctime; ++#endif ++ ++ u32 yst_rdev; ++ ++ void *my_inode; ++ ++ enum yaffs_obj_type variant_type; ++ ++ union yaffs_obj_var variant; ++ ++}; ++ ++struct yaffs_obj_bucket { ++ struct list_head list; ++ int count; ++}; ++ ++/* yaffs_checkpt_obj holds the definition of an object as dumped ++ * by checkpointing. ++ */ ++ ++struct yaffs_checkpt_obj { ++ int struct_type; ++ u32 obj_id; ++ u32 parent_id; ++ int hdr_chunk; ++ enum yaffs_obj_type variant_type:3; ++ u8 deleted:1; ++ u8 soft_del:1; ++ u8 unlinked:1; ++ u8 fake:1; ++ u8 rename_allowed:1; ++ u8 unlink_allowed:1; ++ u8 serial; ++ int n_data_chunks; ++ loff_t size_or_equiv_obj; ++}; ++ ++/*--------------------- Temporary buffers ---------------- ++ * ++ * These are chunk-sized working buffers. Each device has a few. ++ */ ++ ++struct yaffs_buffer { ++ u8 *buffer; ++ int in_use; ++}; ++ ++/*----------------- Device ---------------------------------*/ ++ ++struct yaffs_param { ++ const YCHAR *name; ++ ++ /* ++ * Entry parameters set up way early. Yaffs sets up the rest. ++ * The structure should be zeroed out before use so that unused ++ * and default values are zero. ++ */ ++ ++ int inband_tags; /* Use unband tags */ ++ u32 total_bytes_per_chunk; /* Should be >= 512, does not need to ++ be a power of 2 */ ++ int chunks_per_block; /* does not need to be a power of 2 */ ++ int spare_bytes_per_chunk; /* spare area size */ ++ int start_block; /* Start block we're allowed to use */ ++ int end_block; /* End block we're allowed to use */ ++ int n_reserved_blocks; /* Tuneable so that we can reduce ++ * reserved blocks on NOR and RAM. */ ++ ++ int n_caches; /* If <= 0, then short op caching is disabled, ++ * else the number of short op caches. ++ */ ++ int cache_bypass_aligned; /* If non-zero then bypass the cache for ++ * aligned writes. ++ */ ++ ++ int use_nand_ecc; /* Flag to decide whether or not to use ++ * NAND driver ECC on data (yaffs1) */ ++ int tags_9bytes; /* Use 9 byte tags */ ++ int no_tags_ecc; /* Flag to decide whether or not to do ECC ++ * on packed tags (yaffs2) */ ++ ++ int is_yaffs2; /* Use yaffs2 mode on this device */ ++ ++ int empty_lost_n_found; /* Auto-empty lost+found directory on mount */ ++ ++ int refresh_period; /* How often to check for a block refresh */ ++ ++ /* Checkpoint control. Can be set before or after initialisation */ ++ u8 skip_checkpt_rd; ++ u8 skip_checkpt_wr; ++ ++ int enable_xattr; /* Enable xattribs */ ++ ++ int max_objects; /* ++ * Set to limit the number of objects created. ++ * 0 = no limit. ++ */ ++ ++ /* The remove_obj_fn function must be supplied by OS flavours that ++ * need it. ++ * yaffs direct uses it to implement the faster readdir. ++ * Linux uses it to protect the directory during unlocking. ++ */ ++ void (*remove_obj_fn) (struct yaffs_obj *obj); ++ ++ /* Callback to mark the superblock dirty */ ++ void (*sb_dirty_fn) (struct yaffs_dev *dev); ++ ++ /* Callback to control garbage collection. */ ++ unsigned (*gc_control_fn) (struct yaffs_dev *dev); ++ ++ /* Debug control flags. Don't use unless you know what you're doing */ ++ int use_header_file_size; /* Flag to determine if we should use ++ * file sizes from the header */ ++ int disable_lazy_load; /* Disable lazy loading on this device */ ++ int wide_tnodes_disabled; /* Set to disable wide tnodes */ ++ int disable_soft_del; /* yaffs 1 only: Set to disable the use of ++ * softdeletion. */ ++ ++ int defered_dir_update; /* Set to defer directory updates */ ++ ++#ifdef CONFIG_YAFFS_AUTO_UNICODE ++ int auto_unicode; ++#endif ++ int always_check_erased; /* Force chunk erased check always on */ ++ ++ int disable_summary; ++ ++}; ++ ++struct yaffs_driver { ++ int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, int data_len, ++ const u8 *oob, int oob_len); ++ int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, ++ u8 *data, int data_len, ++ u8 *oob, int oob_len, ++ enum yaffs_ecc_result *ecc_result); ++ int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no); ++ int (*drv_initialise_fn) (struct yaffs_dev *dev); ++ int (*drv_deinitialise_fn) (struct yaffs_dev *dev); ++}; ++ ++struct yaffs_tags_handler { ++ int (*write_chunk_tags_fn) (struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ const struct yaffs_ext_tags *tags); ++ int (*read_chunk_tags_fn) (struct yaffs_dev *dev, ++ int nand_chunk, u8 *data, ++ struct yaffs_ext_tags *tags); ++ ++ int (*query_block_fn) (struct yaffs_dev *dev, int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number); ++ int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no); ++}; ++ ++struct yaffs_dev { ++ struct yaffs_param param; ++ struct yaffs_driver drv; ++ struct yaffs_tags_handler tagger; ++ ++ /* Context storage. Holds extra OS specific data for this device */ ++ ++ void *os_context; ++ void *driver_context; ++ ++ struct list_head dev_list; ++ ++ /* Runtime parameters. Set up by YAFFS. */ ++ int data_bytes_per_chunk; ++ ++ /* Non-wide tnode stuff */ ++ u16 chunk_grp_bits; /* Number of bits that need to be resolved if ++ * the tnodes are not wide enough. ++ */ ++ u16 chunk_grp_size; /* == 2^^chunk_grp_bits */ ++ ++ /* Stuff to support wide tnodes */ ++ u32 tnode_width; ++ u32 tnode_mask; ++ u32 tnode_size; ++ ++ /* Stuff for figuring out file offset to chunk conversions */ ++ u32 chunk_shift; /* Shift value */ ++ u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */ ++ u32 chunk_mask; /* Mask to use for power-of-2 case */ ++ ++ int is_mounted; ++ int read_only; ++ int is_checkpointed; ++ ++ /* Stuff to support block offsetting to support start block zero */ ++ int internal_start_block; ++ int internal_end_block; ++ int block_offset; ++ int chunk_offset; ++ ++ /* Runtime checkpointing stuff */ ++ int checkpt_page_seq; /* running sequence number of checkpt pages */ ++ int checkpt_byte_count; ++ int checkpt_byte_offs; ++ u8 *checkpt_buffer; ++ int checkpt_open_write; ++ int blocks_in_checkpt; ++ int checkpt_cur_chunk; ++ int checkpt_cur_block; ++ int checkpt_next_block; ++ int *checkpt_block_list; ++ int checkpt_max_blocks; ++ u32 checkpt_sum; ++ u32 checkpt_xor; ++ ++ int checkpoint_blocks_required; /* Number of blocks needed to store ++ * current checkpoint set */ ++ ++ /* Block Info */ ++ struct yaffs_block_info *block_info; ++ u8 *chunk_bits; /* bitmap of chunks in use */ ++ unsigned block_info_alt:1; /* allocated using alternative alloc */ ++ unsigned chunk_bits_alt:1; /* allocated using alternative alloc */ ++ int chunk_bit_stride; /* Number of bytes of chunk_bits per block. ++ * Must be consistent with chunks_per_block. ++ */ ++ ++ int n_erased_blocks; ++ int alloc_block; /* Current block being allocated off */ ++ u32 alloc_page; ++ int alloc_block_finder; /* Used to search for next allocation block */ ++ ++ /* Object and Tnode memory management */ ++ void *allocator; ++ int n_obj; ++ int n_tnodes; ++ ++ int n_hardlinks; ++ ++ struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS]; ++ u32 bucket_finder; ++ ++ int n_free_chunks; ++ ++ /* Garbage collection control */ ++ u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */ ++ u32 n_clean_ups; ++ ++ unsigned has_pending_prioritised_gc; /* We think this device might ++ have pending prioritised gcs */ ++ unsigned gc_disable; ++ unsigned gc_block_finder; ++ unsigned gc_dirtiest; ++ unsigned gc_pages_in_use; ++ unsigned gc_not_done; ++ unsigned gc_block; ++ unsigned gc_chunk; ++ unsigned gc_skip; ++ struct yaffs_summary_tags *gc_sum_tags; ++ ++ /* Special directories */ ++ struct yaffs_obj *root_dir; ++ struct yaffs_obj *lost_n_found; ++ ++ int buffered_block; /* Which block is buffered here? */ ++ int doing_buffered_block_rewrite; ++ ++ struct yaffs_cache *cache; ++ int cache_last_use; ++ ++ /* Stuff for background deletion and unlinked files. */ ++ struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted ++ files live. */ ++ struct yaffs_obj *del_dir; /* Directory where deleted objects are ++ sent to disappear. */ ++ struct yaffs_obj *unlinked_deletion; /* Current file being ++ background deleted. */ ++ int n_deleted_files; /* Count of files awaiting deletion; */ ++ int n_unlinked_files; /* Count of unlinked files. */ ++ int n_bg_deletions; /* Count of background deletions. */ ++ ++ /* Temporary buffer management */ ++ struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS]; ++ int max_temp; ++ int temp_in_use; ++ int unmanaged_buffer_allocs; ++ int unmanaged_buffer_deallocs; ++ ++ /* yaffs2 runtime stuff */ ++ unsigned seq_number; /* Sequence number of currently ++ allocating block */ ++ unsigned oldest_dirty_seq; ++ unsigned oldest_dirty_block; ++ ++ /* Block refreshing */ ++ int refresh_skip; /* A skip down counter. ++ * Refresh happens when this gets to zero. */ ++ ++ /* Dirty directory handling */ ++ struct list_head dirty_dirs; /* List of dirty directories */ ++ ++ /* Summary */ ++ int chunks_per_summary; ++ struct yaffs_summary_tags *sum_tags; ++ ++ /* Statistics */ ++ u32 n_page_writes; ++ u32 n_page_reads; ++ u32 n_erasures; ++ u32 n_bad_markings; ++ u32 n_erase_failures; ++ u32 n_gc_copies; ++ u32 all_gcs; ++ u32 passive_gc_count; ++ u32 oldest_dirty_gc_count; ++ u32 n_gc_blocks; ++ u32 bg_gcs; ++ u32 n_retried_writes; ++ u32 n_retired_blocks; ++ u32 n_ecc_fixed; ++ u32 n_ecc_unfixed; ++ u32 n_tags_ecc_fixed; ++ u32 n_tags_ecc_unfixed; ++ u32 n_deletions; ++ u32 n_unmarked_deletions; ++ u32 refresh_count; ++ u32 cache_hits; ++ u32 tags_used; ++ u32 summary_used; ++ ++}; ++ ++/* The CheckpointDevice structure holds the device information that changes ++ *at runtime and must be preserved over unmount/mount cycles. ++ */ ++struct yaffs_checkpt_dev { ++ int struct_type; ++ int n_erased_blocks; ++ int alloc_block; /* Current block being allocated off */ ++ u32 alloc_page; ++ int n_free_chunks; ++ ++ int n_deleted_files; /* Count of files awaiting deletion; */ ++ int n_unlinked_files; /* Count of unlinked files. */ ++ int n_bg_deletions; /* Count of background deletions. */ ++ ++ /* yaffs2 runtime stuff */ ++ unsigned seq_number; /* Sequence number of currently ++ * allocating block */ ++ ++}; ++ ++struct yaffs_checkpt_validity { ++ int struct_type; ++ u32 magic; ++ u32 version; ++ u32 head; ++}; ++ ++struct yaffs_shadow_fixer { ++ int obj_id; ++ int shadowed_id; ++ struct yaffs_shadow_fixer *next; ++}; ++ ++/* Structure for doing xattr modifications */ ++struct yaffs_xattr_mod { ++ int set; /* If 0 then this is a deletion */ ++ const YCHAR *name; ++ const void *data; ++ int size; ++ int flags; ++ int result; ++}; ++ ++/*----------------------- YAFFS Functions -----------------------*/ ++ ++int yaffs_guts_initialise(struct yaffs_dev *dev); ++void yaffs_deinitialise(struct yaffs_dev *dev); ++ ++int yaffs_get_n_free_chunks(struct yaffs_dev *dev); ++ ++int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name, ++ struct yaffs_obj *new_dir, const YCHAR * new_name); ++ ++int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name); ++int yaffs_del_obj(struct yaffs_obj *obj); ++ ++int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size); ++loff_t yaffs_get_obj_length(struct yaffs_obj *obj); ++int yaffs_get_obj_inode(struct yaffs_obj *obj); ++unsigned yaffs_get_obj_type(struct yaffs_obj *obj); ++int yaffs_get_obj_link_count(struct yaffs_obj *obj); ++ ++/* File operations */ ++int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset, ++ int n_bytes); ++int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset, ++ int n_bytes, int write_trhrough); ++int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size); ++ ++struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid); ++ ++int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync); ++ ++/* Flushing and checkpointing */ ++void yaffs_flush_whole_cache(struct yaffs_dev *dev); ++ ++int yaffs_checkpoint_save(struct yaffs_dev *dev); ++int yaffs_checkpoint_restore(struct yaffs_dev *dev); ++ ++/* Directory operations */ ++struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, ++ u32 mode, u32 uid, u32 gid); ++struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir, ++ const YCHAR *name); ++struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number); ++ ++/* Link operations */ ++struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name, ++ struct yaffs_obj *equiv_obj); ++ ++struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj); ++ ++/* Symlink operations */ ++struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, const YCHAR *alias); ++YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj); ++ ++/* Special inodes (fifos, sockets and devices) */ ++struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, ++ const YCHAR *name, u32 mode, u32 uid, ++ u32 gid, u32 rdev); ++ ++int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name, ++ const void *value, int size, int flags); ++int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value, ++ int size); ++int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size); ++int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name); ++ ++/* Special directories */ ++struct yaffs_obj *yaffs_root(struct yaffs_dev *dev); ++struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev); ++ ++void yaffs_handle_defered_free(struct yaffs_obj *obj); ++ ++void yaffs_update_dirty_dirs(struct yaffs_dev *dev); ++ ++int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency); ++ ++/* Debug dump */ ++int yaffs_dump_obj(struct yaffs_obj *obj); ++ ++void yaffs_guts_test(struct yaffs_dev *dev); ++ ++/* A few useful functions to be used within the core files*/ ++void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, ++ int lyn); ++int yaffs_check_ff(u8 *buffer, int n_bytes); ++void yaffs_handle_chunk_error(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi); ++ ++u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev); ++void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer); ++ ++struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, ++ int number, ++ enum yaffs_obj_type type); ++int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, ++ int nand_chunk, int in_scan); ++void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name); ++void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, ++ const struct yaffs_obj_hdr *oh); ++void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj); ++YCHAR *yaffs_clone_str(const YCHAR *str); ++void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list); ++void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no); ++int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, ++ int force, int is_shrink, int shadows, ++ struct yaffs_xattr_mod *xop); ++void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, ++ int backward_scanning); ++int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks); ++struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev); ++struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id, ++ struct yaffs_tnode *passed_tn); ++ ++int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, ++ int n_bytes, int write_trhrough); ++void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size); ++void yaffs_skip_rest_of_block(struct yaffs_dev *dev); ++ ++int yaffs_count_free_chunks(struct yaffs_dev *dev); ++ ++struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, ++ struct yaffs_file_var *file_struct, ++ u32 chunk_id); ++ ++u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, ++ unsigned pos); ++ ++int yaffs_is_non_empty_dir(struct yaffs_obj *obj); ++ ++int yaffs_format_dev(struct yaffs_dev *dev); ++ ++void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, ++ int *chunk_out, u32 *offset_out); ++/* ++ * Marshalling functions to get loff_t file sizes into aand out of ++ * object headers. ++ */ ++void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize); ++loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh); ++loff_t yaffs_max_file_size(struct yaffs_dev *dev); ++ ++ ++#endif +diff --git a/fs/yaffs2/yaffs_linux.h b/fs/yaffs2/yaffs_linux.h +new file mode 100755 +index 00000000..c20ab14b +--- /dev/null ++++ b/fs/yaffs2/yaffs_linux.h +@@ -0,0 +1,48 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_LINUX_H__ ++#define __YAFFS_LINUX_H__ ++ ++#include "yportenv.h" ++ ++struct yaffs_linux_context { ++ struct list_head context_list; /* List of these we have mounted */ ++ struct yaffs_dev *dev; ++ struct super_block *super; ++ struct task_struct *bg_thread; /* Background thread for this device */ ++ int bg_running; ++ struct mutex gross_lock; /* Gross locking mutex*/ ++ u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size ++ * at compile time so we have to allocate it. ++ */ ++ struct list_head search_contexts; ++ struct task_struct *readdir_process; ++ unsigned mount_id; ++ int dirty; ++}; ++ ++#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context)) ++#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context)) ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++#define WRITE_SIZE_STR "writesize" ++#define WRITE_SIZE(mtd) ((mtd)->writesize) ++#else ++#define WRITE_SIZE_STR "oobblock" ++#define WRITE_SIZE(mtd) ((mtd)->oobblock) ++#endif ++ ++#endif +diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c +new file mode 100755 +index 00000000..bd63855a +--- /dev/null ++++ b/fs/yaffs2/yaffs_mtdif.c +@@ -0,0 +1,294 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yportenv.h" ++ ++#include "yaffs_mtdif.h" ++ ++#include "linux/mtd/mtd.h" ++#include "linux/types.h" ++#include "linux/time.h" ++#include "linux/mtd/nand.h" ++#include "linux/kernel.h" ++#include "linux/version.h" ++#include "linux/types.h" ++ ++#include "yaffs_trace.h" ++#include "yaffs_guts.h" ++#include "yaffs_linux.h" ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) ++#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++#define mtd_erase(m, ei) (m)->erase(m, ei) ++#define mtd_write_oob(m, addr, pops) (m)->write_oob(m, addr, pops) ++#define mtd_read_oob(m, addr, pops) (m)->read_oob(m, addr, pops) ++#define mtd_block_isbad(m, offs) (m)->block_isbad(m, offs) ++#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs) ++#endif ++ ++ ++ ++int nandmtd_erase_block(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ u32 addr = ++ ((loff_t) block_no) * dev->param.total_bytes_per_chunk * ++ dev->param.chunks_per_block; ++ struct erase_info ei; ++ int retval = 0; ++ ++ ei.mtd = mtd; ++ ei.addr = addr; ++ ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block; ++ ei.time = 1000; ++ ei.retries = 2; ++ ei.callback = NULL; ++ ei.priv = (u_long) dev; ++ ++ retval = mtd_erase(mtd, &ei); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++ ++static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk, ++ const u8 *data, int data_len, ++ const u8 *oob, int oob_len) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ loff_t addr; ++ struct mtd_oob_ops ops; ++ int retval; ++ ++ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; ++ memset(&ops, 0, sizeof(ops)); ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ops.len = (data) ? data_len : 0; ++ ops.ooblen = oob_len; ++ ops.datbuf = (u8 *)data; ++ ops.oobbuf = (u8 *)oob; ++ ++ retval = mtd_write_oob(mtd, addr, &ops); ++ if (retval) { ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "write_oob failed, chunk %d, mtd error %d", ++ nand_chunk, retval); ++ } ++ return retval ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk, ++ u8 *data, int data_len, ++ u8 *oob, int oob_len, ++ enum yaffs_ecc_result *ecc_result) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ loff_t addr; ++ struct mtd_oob_ops ops; ++ int retval; ++ ++ addr = ((loff_t) nand_chunk) * dev->data_bytes_per_chunk; ++ memset(&ops, 0, sizeof(ops)); ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ops.len = (data) ? data_len : 0; ++ ops.ooblen = oob_len; ++ ops.datbuf = data; ++ ops.oobbuf = oob; ++ ++#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) ++ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; ++ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. ++ */ ++ ops.len = (ops.datbuf) ? ops.len : ops.ooblen; ++#endif ++ /* Read page and oob using MTD. ++ * Check status and determine ECC result. ++ */ ++ retval = mtd_read_oob(mtd, addr, &ops); ++ if (retval) ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "read_oob failed, chunk %d, mtd error %d", ++ nand_chunk, retval); ++ ++ switch (retval) { ++ case 0: ++ /* no error */ ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ break; ++ ++ case -EUCLEAN: ++ /* MTD's ECC fixed the data */ ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_FIXED; ++ dev->n_ecc_fixed++; ++ break; ++ ++ case -EBADMSG: ++ default: ++ /* MTD's ECC could not fix the data */ ++ dev->n_ecc_unfixed++; ++ if(ecc_result) ++ *ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ return YAFFS_FAIL; ++ } ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ ++ loff_t addr; ++ struct erase_info ei; ++ int retval = 0; ++ u32 block_size; ++ ++ block_size = dev->param.total_bytes_per_chunk * ++ dev->param.chunks_per_block; ++ addr = ((loff_t) block_no) * block_size; ++ ++ ei.mtd = mtd; ++ ei.addr = addr; ++ ei.len = block_size; ++ ei.time = 1000; ++ ei.retries = 2; ++ ei.callback = NULL; ++ ei.priv = (u_long) dev; ++ ++ retval = mtd_erase(mtd, &ei); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no); ++ ++ retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no); ++ return (retval) ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no) ++{ ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "checking block %d bad", block_no); ++ ++ retval = mtd_block_isbad(mtd, (loff_t) blocksize * block_no); ++ return (retval) ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++static int yaffs_mtd_initialise(struct yaffs_dev *dev) ++{ ++ return YAFFS_OK; ++} ++ ++static int yaffs_mtd_deinitialise(struct yaffs_dev *dev) ++{ ++ return YAFFS_OK; ++} ++ ++ ++void yaffs_mtd_drv_install(struct yaffs_dev *dev) ++{ ++ struct yaffs_driver *drv = &dev->drv; ++ ++ drv->drv_write_chunk_fn = yaffs_mtd_write; ++ drv->drv_read_chunk_fn = yaffs_mtd_read; ++ drv->drv_erase_fn = yaffs_mtd_erase; ++ drv->drv_mark_bad_fn = yaffs_mtd_mark_bad; ++ drv->drv_check_bad_fn = yaffs_mtd_check_bad; ++ drv->drv_initialise_fn = yaffs_mtd_initialise; ++ drv->drv_deinitialise_fn = yaffs_mtd_deinitialise; ++} ++ ++ ++struct mtd_info * yaffs_get_mtd_device(dev_t sdev) ++{ ++ struct mtd_info *mtd; ++ ++ mtd = yaffs_get_mtd_device(sdev); ++ ++ /* Check it's an mtd device..... */ ++ if (MAJOR(sdev) != MTD_BLOCK_MAJOR) ++ return NULL; /* This isn't an mtd device */ ++ ++ /* Check it's NAND */ ++ if (mtd->type != MTD_NANDFLASH) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: MTD device is not NAND it's type %d", ++ mtd->type); ++ return NULL; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd)); ++ yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize); ++ yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++ yaffs_trace(YAFFS_TRACE_OS, " size %u", mtd->size); ++#else ++ yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size); ++#endif ++ ++ return mtd; ++} ++ ++int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags) ++{ ++ if (yaffs_version == 2) { ++ if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || ++ mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && ++ !inband_tags) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device does not have the right page sizes" ++ ); ++ return -1; ++ } ++ } else { ++ if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK || ++ mtd->oobsize != YAFFS_BYTES_PER_SPARE) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "MTD device does not support have the right page sizes" ++ ); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++void yaffs_put_mtd_device(struct mtd_info *mtd) ++{ ++ if(mtd) ++ put_mtd_device(mtd); ++} +diff --git a/fs/yaffs2/yaffs_mtdif.h b/fs/yaffs2/yaffs_mtdif.h +new file mode 100755 +index 00000000..9cff224c +--- /dev/null ++++ b/fs/yaffs2/yaffs_mtdif.h +@@ -0,0 +1,25 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_MTDIF_H__ ++#define __YAFFS_MTDIF_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_mtd_drv_install(struct yaffs_dev *dev); ++struct mtd_info * yaffs_get_mtd_device(dev_t sdev); ++void yaffs_put_mtd_device(struct mtd_info *mtd); ++int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags); ++#endif +diff --git a/fs/yaffs2/yaffs_nameval.c b/fs/yaffs2/yaffs_nameval.c +new file mode 100755 +index 00000000..4bdf4ed7 +--- /dev/null ++++ b/fs/yaffs2/yaffs_nameval.c +@@ -0,0 +1,208 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/* ++ * This simple implementation of a name-value store assumes a small number of ++* values and fits into a small finite buffer. ++ * ++ * Each attribute is stored as a record: ++ * sizeof(int) bytes record size. ++ * strnlen+1 bytes name null terminated. ++ * nbytes value. ++ * ---------- ++ * total size stored in record size ++ * ++ * This code has not been tested with unicode yet. ++ */ ++ ++#include "yaffs_nameval.h" ++ ++#include "yportenv.h" ++ ++static int nval_find(const char *xb, int xb_size, const YCHAR *name, ++ int *exist_size) ++{ ++ int pos = 0; ++ int size; ++ ++ memcpy(&size, xb, sizeof(int)); ++ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { ++ if (!strncmp((YCHAR *) (xb + pos + sizeof(int)), ++ name, size)) { ++ if (exist_size) ++ *exist_size = size; ++ return pos; ++ } ++ pos += size; ++ if (pos < xb_size - sizeof(int)) ++ memcpy(&size, xb + pos, sizeof(int)); ++ else ++ size = 0; ++ } ++ if (exist_size) ++ *exist_size = 0; ++ return -ENODATA; ++} ++ ++static int nval_used(const char *xb, int xb_size) ++{ ++ int pos = 0; ++ int size; ++ ++ memcpy(&size, xb + pos, sizeof(int)); ++ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { ++ pos += size; ++ if (pos < xb_size - sizeof(int)) ++ memcpy(&size, xb + pos, sizeof(int)); ++ else ++ size = 0; ++ } ++ return pos; ++} ++ ++int nval_del(char *xb, int xb_size, const YCHAR *name) ++{ ++ int pos = nval_find(xb, xb_size, name, NULL); ++ int size; ++ ++ if (pos < 0 || pos >= xb_size) ++ return -ENODATA; ++ ++ /* Find size, shift rest over this record, ++ * then zero out the rest of buffer */ ++ memcpy(&size, xb + pos, sizeof(int)); ++ memcpy(xb + pos, xb + pos + size, xb_size - (pos + size)); ++ memset(xb + (xb_size - size), 0, size); ++ return 0; ++} ++ ++int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, ++ int bsize, int flags) ++{ ++ int pos; ++ int namelen = strnlen(name, xb_size); ++ int reclen; ++ int size_exist = 0; ++ int space; ++ int start; ++ ++ pos = nval_find(xb, xb_size, name, &size_exist); ++ ++ if (flags & XATTR_CREATE && pos >= 0) ++ return -EEXIST; ++ if (flags & XATTR_REPLACE && pos < 0) ++ return -ENODATA; ++ ++ start = nval_used(xb, xb_size); ++ space = xb_size - start + size_exist; ++ ++ reclen = (sizeof(int) + namelen + 1 + bsize); ++ ++ if (reclen > space) ++ return -ENOSPC; ++ ++ if (pos >= 0) { ++ nval_del(xb, xb_size, name); ++ start = nval_used(xb, xb_size); ++ } ++ ++ pos = start; ++ ++ memcpy(xb + pos, &reclen, sizeof(int)); ++ pos += sizeof(int); ++ strncpy((YCHAR *) (xb + pos), name, reclen); ++ pos += (namelen + 1); ++ memcpy(xb + pos, buf, bsize); ++ return 0; ++} ++ ++int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf, ++ int bsize) ++{ ++ int pos = nval_find(xb, xb_size, name, NULL); ++ int size; ++ ++ if (pos >= 0 && pos < xb_size) { ++ ++ memcpy(&size, xb + pos, sizeof(int)); ++ pos += sizeof(int); /* advance past record length */ ++ size -= sizeof(int); ++ ++ /* Advance over name string */ ++ while (xb[pos] && size > 0 && pos < xb_size) { ++ pos++; ++ size--; ++ } ++ /*Advance over NUL */ ++ pos++; ++ size--; ++ ++ /* If bsize is zero then this is a size query. ++ * Return the size, but don't copy. ++ */ ++ if (!bsize) ++ return size; ++ ++ if (size <= bsize) { ++ memcpy(buf, xb + pos, size); ++ return size; ++ } ++ } ++ if (pos >= 0) ++ return -ERANGE; ++ ++ return -ENODATA; ++} ++ ++int nval_list(const char *xb, int xb_size, char *buf, int bsize) ++{ ++ int pos = 0; ++ int size; ++ int name_len; ++ int ncopied = 0; ++ int filled = 0; ++ ++ memcpy(&size, xb + pos, sizeof(int)); ++ while (size > sizeof(int) && ++ size <= xb_size && ++ (pos + size) < xb_size && ++ !filled) { ++ pos += sizeof(int); ++ size -= sizeof(int); ++ name_len = strnlen((YCHAR *) (xb + pos), size); ++ if (ncopied + name_len + 1 < bsize) { ++ memcpy(buf, xb + pos, name_len * sizeof(YCHAR)); ++ buf += name_len; ++ *buf = '\0'; ++ buf++; ++ if (sizeof(YCHAR) > 1) { ++ *buf = '\0'; ++ buf++; ++ } ++ ncopied += (name_len + 1); ++ } else { ++ filled = 1; ++ } ++ pos += size; ++ if (pos < xb_size - sizeof(int)) ++ memcpy(&size, xb + pos, sizeof(int)); ++ else ++ size = 0; ++ } ++ return ncopied; ++} ++ ++int nval_hasvalues(const char *xb, int xb_size) ++{ ++ return nval_used(xb, xb_size) > 0; ++} +diff --git a/fs/yaffs2/yaffs_nameval.h b/fs/yaffs2/yaffs_nameval.h +new file mode 100755 +index 00000000..951e64f8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_nameval.h +@@ -0,0 +1,28 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __NAMEVAL_H__ ++#define __NAMEVAL_H__ ++ ++#include "yportenv.h" ++ ++int nval_del(char *xb, int xb_size, const YCHAR * name); ++int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf, ++ int bsize, int flags); ++int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf, ++ int bsize); ++int nval_list(const char *xb, int xb_size, char *buf, int bsize); ++int nval_hasvalues(const char *xb, int xb_size); ++#endif +diff --git a/fs/yaffs2/yaffs_nand.c b/fs/yaffs2/yaffs_nand.c +new file mode 100755 +index 00000000..9afd5ec8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_nand.c +@@ -0,0 +1,118 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_nand.h" ++#include "yaffs_tagscompat.h" ++ ++#include "yaffs_getblockinfo.h" ++#include "yaffs_summary.h" ++ ++static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) ++{ ++ return chunk - dev->chunk_offset; ++} ++ ++int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, ++ u8 *buffer, struct yaffs_ext_tags *tags) ++{ ++ int result; ++ struct yaffs_ext_tags local_tags; ++ int flash_chunk = apply_chunk_offset(dev, nand_chunk); ++ ++ dev->n_page_reads++; ++ ++ /* If there are no tags provided use local tags. */ ++ if (!tags) ++ tags = &local_tags; ++ ++ result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags); ++ if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) { ++ ++ struct yaffs_block_info *bi; ++ bi = yaffs_get_block_info(dev, ++ nand_chunk / ++ dev->param.chunks_per_block); ++ yaffs_handle_chunk_error(dev, bi); ++ } ++ return result; ++} ++ ++int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *buffer, struct yaffs_ext_tags *tags) ++{ ++ int result; ++ int flash_chunk = apply_chunk_offset(dev, nand_chunk); ++ ++ dev->n_page_writes++; ++ ++ if (!tags) { ++ yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags"); ++ BUG(); ++ return YAFFS_FAIL; ++ } ++ ++ tags->seq_number = dev->seq_number; ++ tags->chunk_used = 1; ++ yaffs_trace(YAFFS_TRACE_WRITE, ++ "Writing chunk %d tags %d %d", ++ nand_chunk, tags->obj_id, tags->chunk_id); ++ ++ result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk, ++ buffer, tags); ++ ++ yaffs_summary_add(dev, tags, nand_chunk); ++ ++ return result; ++} ++ ++int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ block_no -= dev->block_offset; ++ dev->n_bad_markings++; ++ return dev->tagger.mark_bad_fn(dev, block_no); ++} ++ ++ ++int yaffs_query_init_block_state(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ block_no -= dev->block_offset; ++ return dev->tagger.query_block_fn(dev, block_no, state, seq_number); ++} ++ ++int yaffs_erase_block(struct yaffs_dev *dev, int block_no) ++{ ++ int result; ++ ++ block_no -= dev->block_offset; ++ dev->n_erasures++; ++ result = dev->drv.drv_erase_fn(dev, block_no); ++ return result; ++} ++ ++int yaffs_init_nand(struct yaffs_dev *dev) ++{ ++ if (dev->drv.drv_initialise_fn) ++ return dev->drv.drv_initialise_fn(dev); ++ return YAFFS_OK; ++} ++ ++int yaffs_deinit_nand(struct yaffs_dev *dev) ++{ ++ if (dev->drv.drv_deinitialise_fn) ++ return dev->drv.drv_deinitialise_fn(dev); ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_nand.h b/fs/yaffs2/yaffs_nand.h +new file mode 100755 +index 00000000..804e97ad +--- /dev/null ++++ b/fs/yaffs2/yaffs_nand.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_NAND_H__ ++#define __YAFFS_NAND_H__ ++#include "yaffs_guts.h" ++ ++int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, ++ u8 *buffer, struct yaffs_ext_tags *tags); ++ ++int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *buffer, struct yaffs_ext_tags *tags); ++ ++int yaffs_mark_bad(struct yaffs_dev *dev, int block_no); ++ ++int yaffs_query_init_block_state(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ unsigned *seq_number); ++ ++int yaffs_erase_block(struct yaffs_dev *dev, int flash_block); ++ ++int yaffs_init_nand(struct yaffs_dev *dev); ++int yaffs_deinit_nand(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_packedtags1.c b/fs/yaffs2/yaffs_packedtags1.c +new file mode 100755 +index 00000000..dd9a331d +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags1.c +@@ -0,0 +1,56 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_packedtags1.h" ++#include "yportenv.h" ++ ++static const u8 all_ff[20] = { ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff ++}; ++ ++void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt, ++ const struct yaffs_ext_tags *t) ++{ ++ pt->chunk_id = t->chunk_id; ++ pt->serial_number = t->serial_number; ++ pt->n_bytes = t->n_bytes; ++ pt->obj_id = t->obj_id; ++ pt->ecc = 0; ++ pt->deleted = (t->is_deleted) ? 0 : 1; ++ pt->unused_stuff = 0; ++ pt->should_be_ff = 0xffffffff; ++} ++ ++void yaffs_unpack_tags1(struct yaffs_ext_tags *t, ++ const struct yaffs_packed_tags1 *pt) ++{ ++ ++ if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) { ++ t->block_bad = 0; ++ if (pt->should_be_ff != 0xffffffff) ++ t->block_bad = 1; ++ t->chunk_used = 1; ++ t->obj_id = pt->obj_id; ++ t->chunk_id = pt->chunk_id; ++ t->n_bytes = pt->n_bytes; ++ t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ t->is_deleted = (pt->deleted) ? 0 : 1; ++ t->serial_number = pt->serial_number; ++ } else { ++ memset(t, 0, sizeof(struct yaffs_ext_tags)); ++ } ++} +diff --git a/fs/yaffs2/yaffs_packedtags1.h b/fs/yaffs2/yaffs_packedtags1.h +new file mode 100755 +index 00000000..b80f0a5b +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags1.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */ ++ ++#ifndef __YAFFS_PACKEDTAGS1_H__ ++#define __YAFFS_PACKEDTAGS1_H__ ++ ++#include "yaffs_guts.h" ++ ++struct yaffs_packed_tags1 { ++ unsigned chunk_id:20; ++ unsigned serial_number:2; ++ unsigned n_bytes:10; ++ unsigned obj_id:18; ++ unsigned ecc:12; ++ unsigned deleted:1; ++ unsigned unused_stuff:1; ++ unsigned should_be_ff; ++ ++}; ++ ++void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt, ++ const struct yaffs_ext_tags *t); ++void yaffs_unpack_tags1(struct yaffs_ext_tags *t, ++ const struct yaffs_packed_tags1 *pt); ++#endif +diff --git a/fs/yaffs2/yaffs_packedtags2.c b/fs/yaffs2/yaffs_packedtags2.c +new file mode 100755 +index 00000000..e1d18cc3 +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags2.c +@@ -0,0 +1,197 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_packedtags2.h" ++#include "yportenv.h" ++#include "yaffs_trace.h" ++ ++/* This code packs a set of extended tags into a binary structure for ++ * NAND storage ++ */ ++ ++/* Some of the information is "extra" struff which can be packed in to ++ * speed scanning ++ * This is defined by having the EXTRA_HEADER_INFO_FLAG set. ++ */ ++ ++/* Extra flags applied to chunk_id */ ++ ++#define EXTRA_HEADER_INFO_FLAG 0x80000000 ++#define EXTRA_SHRINK_FLAG 0x40000000 ++#define EXTRA_SHADOWS_FLAG 0x20000000 ++#define EXTRA_SPARE_FLAGS 0x10000000 ++ ++#define ALL_EXTRA_FLAGS 0xf0000000 ++ ++/* Also, the top 4 bits of the object Id are set to the object type. */ ++#define EXTRA_OBJECT_TYPE_SHIFT (28) ++#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT) ++ ++static void yaffs_dump_packed_tags2_tags_only( ++ const struct yaffs_packed_tags2_tags_only *ptt) ++{ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "packed tags obj %d chunk %d byte %d seq %d", ++ ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number); ++} ++ ++static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) ++{ ++ yaffs_dump_packed_tags2_tags_only(&pt->t); ++} ++ ++static void yaffs_dump_tags2(const struct yaffs_ext_tags *t) ++{ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d", ++ t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, ++ t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, ++ t->seq_number); ++ ++} ++ ++static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t) ++{ ++ if (t->chunk_id != 0 || !t->extra_available) ++ return 0; ++ ++ /* Check if the file size is too long to store */ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE && ++ (t->extra_file_size >> 31) != 0) ++ return 0; ++ return 1; ++} ++ ++void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *ptt, ++ const struct yaffs_ext_tags *t) ++{ ++ ptt->chunk_id = t->chunk_id; ++ ptt->seq_number = t->seq_number; ++ ptt->n_bytes = t->n_bytes; ++ ptt->obj_id = t->obj_id; ++ ++ /* Only store extra tags for object headers. ++ * If it is a file then only store if the file size is short\ ++ * enough to fit. ++ */ ++ if (yaffs_check_tags_extra_packable(t)) { ++ /* Store the extra header info instead */ ++ /* We save the parent object in the chunk_id */ ++ ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id; ++ if (t->extra_is_shrink) ++ ptt->chunk_id |= EXTRA_SHRINK_FLAG; ++ if (t->extra_shadows) ++ ptt->chunk_id |= EXTRA_SHADOWS_FLAG; ++ ++ ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; ++ ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT); ++ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ ptt->n_bytes = t->extra_equiv_id; ++ else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE) ++ ptt->n_bytes = (unsigned) t->extra_file_size; ++ else ++ ptt->n_bytes = 0; ++ } ++ ++ yaffs_dump_packed_tags2_tags_only(ptt); ++ yaffs_dump_tags2(t); ++} ++ ++void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt, ++ const struct yaffs_ext_tags *t, int tags_ecc) ++{ ++ yaffs_pack_tags2_tags_only(&pt->t, t); ++ ++ if (tags_ecc) ++ yaffs_ecc_calc_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &pt->ecc); ++} ++ ++void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, ++ struct yaffs_packed_tags2_tags_only *ptt) ++{ ++ memset(t, 0, sizeof(struct yaffs_ext_tags)); ++ ++ if (ptt->seq_number == 0xffffffff) ++ return; ++ ++ t->block_bad = 0; ++ t->chunk_used = 1; ++ t->obj_id = ptt->obj_id; ++ t->chunk_id = ptt->chunk_id; ++ t->n_bytes = ptt->n_bytes; ++ t->is_deleted = 0; ++ t->serial_number = 0; ++ t->seq_number = ptt->seq_number; ++ ++ /* Do extra header info stuff */ ++ if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) { ++ t->chunk_id = 0; ++ t->n_bytes = 0; ++ ++ t->extra_available = 1; ++ t->extra_parent_id = ptt->chunk_id & (~(ALL_EXTRA_FLAGS)); ++ t->extra_is_shrink = ptt->chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0; ++ t->extra_shadows = ptt->chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0; ++ t->extra_obj_type = ptt->obj_id >> EXTRA_OBJECT_TYPE_SHIFT; ++ t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK; ++ ++ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ t->extra_equiv_id = ptt->n_bytes; ++ else ++ t->extra_file_size = ptt->n_bytes; ++ } ++ yaffs_dump_packed_tags2_tags_only(ptt); ++ yaffs_dump_tags2(t); ++} ++ ++void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, ++ int tags_ecc) ++{ ++ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ ++ if (pt->t.seq_number != 0xffffffff && tags_ecc) { ++ /* Chunk is in use and we need to do ECC */ ++ ++ struct yaffs_ecc_other ecc; ++ int result; ++ yaffs_ecc_calc_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &ecc); ++ result = ++ yaffs_ecc_correct_other((unsigned char *)&pt->t, ++ sizeof(struct yaffs_packed_tags2_tags_only), ++ &pt->ecc, &ecc); ++ switch (result) { ++ case 0: ++ ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ break; ++ case 1: ++ ecc_result = YAFFS_ECC_RESULT_FIXED; ++ break; ++ case -1: ++ ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ break; ++ default: ++ ecc_result = YAFFS_ECC_RESULT_UNKNOWN; ++ } ++ } ++ yaffs_unpack_tags2_tags_only(t, &pt->t); ++ ++ t->ecc_result = ecc_result; ++ ++ yaffs_dump_packed_tags2(pt); ++ yaffs_dump_tags2(t); ++} +diff --git a/fs/yaffs2/yaffs_packedtags2.h b/fs/yaffs2/yaffs_packedtags2.h +new file mode 100755 +index 00000000..675e7194 +--- /dev/null ++++ b/fs/yaffs2/yaffs_packedtags2.h +@@ -0,0 +1,47 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++/* This is used to pack YAFFS2 tags, not YAFFS1tags. */ ++ ++#ifndef __YAFFS_PACKEDTAGS2_H__ ++#define __YAFFS_PACKEDTAGS2_H__ ++ ++#include "yaffs_guts.h" ++#include "yaffs_ecc.h" ++ ++struct yaffs_packed_tags2_tags_only { ++ unsigned seq_number; ++ unsigned obj_id; ++ unsigned chunk_id; ++ unsigned n_bytes; ++}; ++ ++struct yaffs_packed_tags2 { ++ struct yaffs_packed_tags2_tags_only t; ++ struct yaffs_ecc_other ecc; ++}; ++ ++/* Full packed tags with ECC, used for oob tags */ ++void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt, ++ const struct yaffs_ext_tags *t, int tags_ecc); ++void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, ++ int tags_ecc); ++ ++/* Only the tags part (no ECC for use with inband tags */ ++void yaffs_pack_tags2_tags_only(struct yaffs_packed_tags2_tags_only *pt, ++ const struct yaffs_ext_tags *t); ++void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, ++ struct yaffs_packed_tags2_tags_only *pt); ++#endif +diff --git a/fs/yaffs2/yaffs_summary.c b/fs/yaffs2/yaffs_summary.c +new file mode 100755 +index 00000000..6f3c7839 +--- /dev/null ++++ b/fs/yaffs2/yaffs_summary.c +@@ -0,0 +1,313 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * 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. ++ */ ++ ++/* Summaries write the useful part of the tags for the chunks in a block into an ++ * an array which is written to the last n chunks of the block. ++ * Reading the summaries gives all the tags for the block in one read. Much ++ * faster. ++ * ++ * Chunks holding summaries are marked with tags making it look like ++ * they are part of a fake file. ++ * ++ * The summary could also be used during gc. ++ * ++ */ ++ ++#include "yaffs_summary.h" ++#include "yaffs_packedtags2.h" ++#include "yaffs_nand.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_bitmap.h" ++ ++/* ++ * The summary is built up in an array of summary tags. ++ * This gets written to the last one or two (maybe more) chunks in a block. ++ * A summary header is written as the first part of each chunk of summary data. ++ * The summary header must match or the summary is rejected. ++ */ ++ ++/* Summary tags don't need the sequence number because that is redundant. */ ++struct yaffs_summary_tags { ++ unsigned obj_id; ++ unsigned chunk_id; ++ unsigned n_bytes; ++}; ++ ++/* Summary header */ ++struct yaffs_summary_header { ++ unsigned version; /* Must match current version */ ++ unsigned block; /* Must be this block */ ++ unsigned seq; /* Must be this sequence number */ ++ unsigned sum; /* Just add up all the bytes in the tags */ ++}; ++ ++ ++static void yaffs_summary_clear(struct yaffs_dev *dev) ++{ ++ if (!dev->sum_tags) ++ return; ++ memset(dev->sum_tags, 0, dev->chunks_per_summary * ++ sizeof(struct yaffs_summary_tags)); ++} ++ ++ ++void yaffs_summary_deinit(struct yaffs_dev *dev) ++{ ++ kfree(dev->sum_tags); ++ dev->sum_tags = NULL; ++ kfree(dev->gc_sum_tags); ++ dev->gc_sum_tags = NULL; ++ dev->chunks_per_summary = 0; ++} ++ ++int yaffs_summary_init(struct yaffs_dev *dev) ++{ ++ int sum_bytes; ++ int chunks_used; /* Number of chunks used by summary */ ++ int sum_tags_bytes; ++ ++ sum_bytes = dev->param.chunks_per_block * ++ sizeof(struct yaffs_summary_tags); ++ ++ chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/ ++ (dev->data_bytes_per_chunk - ++ sizeof(struct yaffs_summary_header)); ++ ++ dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used; ++ sum_tags_bytes = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ dev->sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS); ++ dev->gc_sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS); ++ if (!dev->sum_tags || !dev->gc_sum_tags) { ++ yaffs_summary_deinit(dev); ++ return YAFFS_FAIL; ++ } ++ ++ yaffs_summary_clear(dev); ++ ++ return YAFFS_OK; ++} ++ ++static unsigned yaffs_summary_sum(struct yaffs_dev *dev) ++{ ++ u8 *sum_buffer = (u8 *)dev->sum_tags; ++ int i; ++ unsigned sum = 0; ++ ++ i = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ while (i > 0) { ++ sum += *sum_buffer; ++ sum_buffer++; ++ i--; ++ } ++ ++ return sum; ++} ++ ++static int yaffs_summary_write(struct yaffs_dev *dev, int blk) ++{ ++ struct yaffs_ext_tags tags; ++ u8 *buffer; ++ u8 *sum_buffer = (u8 *)dev->sum_tags; ++ int n_bytes; ++ int chunk_in_nand; ++ int chunk_in_block; ++ int result; ++ int this_tx; ++ struct yaffs_summary_header hdr; ++ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr); ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ ++ buffer = yaffs_get_temp_buffer(dev); ++ n_bytes = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ memset(&tags, 0, sizeof(struct yaffs_ext_tags)); ++ tags.obj_id = YAFFS_OBJECTID_SUMMARY; ++ tags.chunk_id = 1; ++ chunk_in_block = dev->chunks_per_summary; ++ chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block + ++ dev->chunks_per_summary; ++ hdr.version = YAFFS_SUMMARY_VERSION; ++ hdr.block = blk; ++ hdr.seq = bi->seq_number; ++ hdr.sum = yaffs_summary_sum(dev); ++ ++ do { ++ this_tx = n_bytes; ++ if (this_tx > sum_bytes_per_chunk) ++ this_tx = sum_bytes_per_chunk; ++ memcpy(buffer, &hdr, sizeof(hdr)); ++ memcpy(buffer + sizeof(hdr), sum_buffer, this_tx); ++ tags.n_bytes = this_tx + sizeof(hdr); ++ result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand, ++ buffer, &tags); ++ ++ if (result != YAFFS_OK) ++ break; ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ dev->n_free_chunks--; ++ ++ n_bytes -= this_tx; ++ sum_buffer += this_tx; ++ chunk_in_nand++; ++ chunk_in_block++; ++ tags.chunk_id++; ++ } while (result == YAFFS_OK && n_bytes > 0); ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ ++ if (result == YAFFS_OK) ++ bi->has_summary = 1; ++ ++ ++ return result; ++} ++ ++int yaffs_summary_read(struct yaffs_dev *dev, ++ struct yaffs_summary_tags *st, ++ int blk) ++{ ++ struct yaffs_ext_tags tags; ++ u8 *buffer; ++ u8 *sum_buffer = (u8 *)st; ++ int n_bytes; ++ int chunk_id; ++ int chunk_in_nand; ++ int chunk_in_block; ++ int result; ++ int this_tx; ++ struct yaffs_summary_header hdr; ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr); ++ int sum_tags_bytes; ++ ++ sum_tags_bytes = sizeof(struct yaffs_summary_tags) * ++ dev->chunks_per_summary; ++ buffer = yaffs_get_temp_buffer(dev); ++ n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary; ++ chunk_in_block = dev->chunks_per_summary; ++ chunk_in_nand = blk * dev->param.chunks_per_block + ++ dev->chunks_per_summary; ++ chunk_id = 1; ++ do { ++ this_tx = n_bytes; ++ if (this_tx > sum_bytes_per_chunk) ++ this_tx = sum_bytes_per_chunk; ++ result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand, ++ buffer, &tags); ++ ++ if (tags.chunk_id != chunk_id || ++ tags.obj_id != YAFFS_OBJECTID_SUMMARY || ++ tags.chunk_used == 0 || ++ tags.ecc_result > YAFFS_ECC_RESULT_FIXED || ++ tags.n_bytes != (this_tx + sizeof(hdr))) ++ result = YAFFS_FAIL; ++ if (result != YAFFS_OK) ++ break; ++ ++ if (st == dev->sum_tags) { ++ /* If we're scanning then update the block info */ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ } ++ memcpy(&hdr, buffer, sizeof(hdr)); ++ memcpy(sum_buffer, buffer + sizeof(hdr), this_tx); ++ n_bytes -= this_tx; ++ sum_buffer += this_tx; ++ chunk_in_nand++; ++ chunk_in_block++; ++ chunk_id++; ++ } while (result == YAFFS_OK && n_bytes > 0); ++ yaffs_release_temp_buffer(dev, buffer); ++ ++ if (result == YAFFS_OK) { ++ /* Verify header */ ++ if (hdr.version != YAFFS_SUMMARY_VERSION || ++ hdr.block != blk || ++ hdr.seq != bi->seq_number || ++ hdr.sum != yaffs_summary_sum(dev)) ++ result = YAFFS_FAIL; ++ } ++ ++ if (st == dev->sum_tags && result == YAFFS_OK) ++ bi->has_summary = 1; ++ ++ return result; ++} ++ ++int yaffs_summary_add(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_nand) ++{ ++ struct yaffs_packed_tags2_tags_only tags_only; ++ struct yaffs_summary_tags *sum_tags; ++ int block_in_nand = chunk_in_nand / dev->param.chunks_per_block; ++ int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block; ++ ++ if (!dev->sum_tags) ++ return YAFFS_OK; ++ ++ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) { ++ yaffs_pack_tags2_tags_only(&tags_only, tags); ++ sum_tags = &dev->sum_tags[chunk_in_block]; ++ sum_tags->chunk_id = tags_only.chunk_id; ++ sum_tags->n_bytes = tags_only.n_bytes; ++ sum_tags->obj_id = tags_only.obj_id; ++ ++ if (chunk_in_block == dev->chunks_per_summary - 1) { ++ /* Time to write out the summary */ ++ yaffs_summary_write(dev, block_in_nand); ++ yaffs_summary_clear(dev); ++ yaffs_skip_rest_of_block(dev); ++ } ++ } ++ return YAFFS_OK; ++} ++ ++int yaffs_summary_fetch(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block) ++{ ++ struct yaffs_packed_tags2_tags_only tags_only; ++ struct yaffs_summary_tags *sum_tags; ++ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) { ++ sum_tags = &dev->sum_tags[chunk_in_block]; ++ tags_only.chunk_id = sum_tags->chunk_id; ++ tags_only.n_bytes = sum_tags->n_bytes; ++ tags_only.obj_id = sum_tags->obj_id; ++ yaffs_unpack_tags2_tags_only(tags, &tags_only); ++ return YAFFS_OK; ++ } ++ return YAFFS_FAIL; ++} ++ ++void yaffs_summary_gc(struct yaffs_dev *dev, int blk) ++{ ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk); ++ int i; ++ ++ if (!bi->has_summary) ++ return; ++ ++ for (i = dev->chunks_per_summary; ++ i < dev->param.chunks_per_block; ++ i++) { ++ if (yaffs_check_chunk_bit(dev, blk, i)) { ++ yaffs_clear_chunk_bit(dev, blk, i); ++ bi->pages_in_use--; ++ dev->n_free_chunks++; ++ } ++ } ++} +diff --git a/fs/yaffs2/yaffs_summary.h b/fs/yaffs2/yaffs_summary.h +new file mode 100755 +index 00000000..be141d07 +--- /dev/null ++++ b/fs/yaffs2/yaffs_summary.h +@@ -0,0 +1,37 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_SUMMARY_H__ ++#define __YAFFS_SUMMARY_H__ ++ ++#include "yaffs_packedtags2.h" ++ ++ ++int yaffs_summary_init(struct yaffs_dev *dev); ++void yaffs_summary_deinit(struct yaffs_dev *dev); ++ ++int yaffs_summary_add(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block); ++int yaffs_summary_fetch(struct yaffs_dev *dev, ++ struct yaffs_ext_tags *tags, ++ int chunk_in_block); ++int yaffs_summary_read(struct yaffs_dev *dev, ++ struct yaffs_summary_tags *st, ++ int blk); ++void yaffs_summary_gc(struct yaffs_dev *dev, int blk); ++ ++ ++#endif +diff --git a/fs/yaffs2/yaffs_tagscompat.c b/fs/yaffs2/yaffs_tagscompat.c +new file mode 100755 +index 00000000..092430be +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagscompat.c +@@ -0,0 +1,381 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_tagscompat.h" ++#include "yaffs_ecc.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_trace.h" ++ ++static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); ++ ++ ++/********** Tags ECC calculations *********/ ++ ++ ++void yaffs_calc_tags_ecc(struct yaffs_tags *tags) ++{ ++ /* Calculate an ecc */ ++ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes; ++ unsigned i, j; ++ unsigned ecc = 0; ++ unsigned bit = 0; ++ ++ tags->ecc = 0; ++ ++ for (i = 0; i < 8; i++) { ++ for (j = 1; j & 0xff; j <<= 1) { ++ bit++; ++ if (b[i] & j) ++ ecc ^= bit; ++ } ++ } ++ tags->ecc = ecc; ++} ++ ++int yaffs_check_tags_ecc(struct yaffs_tags *tags) ++{ ++ unsigned ecc = tags->ecc; ++ ++ yaffs_calc_tags_ecc(tags); ++ ++ ecc ^= tags->ecc; ++ ++ if (ecc && ecc <= 64) { ++ /* TODO: Handle the failure better. Retire? */ ++ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes; ++ ++ ecc--; ++ ++ b[ecc / 8] ^= (1 << (ecc & 7)); ++ ++ /* Now recvalc the ecc */ ++ yaffs_calc_tags_ecc(tags); ++ ++ return 1; /* recovered error */ ++ } else if (ecc) { ++ /* Wierd ecc failure value */ ++ /* TODO Need to do somethiong here */ ++ return -1; /* unrecovered error */ ++ } ++ return 0; ++} ++ ++/********** Tags **********/ ++ ++static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr, ++ struct yaffs_tags *tags_ptr) ++{ ++ union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr; ++ ++ yaffs_calc_tags_ecc(tags_ptr); ++ ++ spare_ptr->tb0 = tu->as_bytes[0]; ++ spare_ptr->tb1 = tu->as_bytes[1]; ++ spare_ptr->tb2 = tu->as_bytes[2]; ++ spare_ptr->tb3 = tu->as_bytes[3]; ++ spare_ptr->tb4 = tu->as_bytes[4]; ++ spare_ptr->tb5 = tu->as_bytes[5]; ++ spare_ptr->tb6 = tu->as_bytes[6]; ++ spare_ptr->tb7 = tu->as_bytes[7]; ++} ++ ++static void yaffs_get_tags_from_spare(struct yaffs_dev *dev, ++ struct yaffs_spare *spare_ptr, ++ struct yaffs_tags *tags_ptr) ++{ ++ union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr; ++ int result; ++ ++ tu->as_bytes[0] = spare_ptr->tb0; ++ tu->as_bytes[1] = spare_ptr->tb1; ++ tu->as_bytes[2] = spare_ptr->tb2; ++ tu->as_bytes[3] = spare_ptr->tb3; ++ tu->as_bytes[4] = spare_ptr->tb4; ++ tu->as_bytes[5] = spare_ptr->tb5; ++ tu->as_bytes[6] = spare_ptr->tb6; ++ tu->as_bytes[7] = spare_ptr->tb7; ++ ++ result = yaffs_check_tags_ecc(tags_ptr); ++ if (result > 0) ++ dev->n_tags_ecc_fixed++; ++ else if (result < 0) ++ dev->n_tags_ecc_unfixed++; ++} ++ ++static void yaffs_spare_init(struct yaffs_spare *spare) ++{ ++ memset(spare, 0xff, sizeof(struct yaffs_spare)); ++} ++ ++static int yaffs_wr_nand(struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ struct yaffs_spare *spare) ++{ ++ int data_size = dev->data_bytes_per_chunk; ++ ++ return dev->drv.drv_write_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *) spare, sizeof(*spare)); ++} ++ ++static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, ++ struct yaffs_spare *spare, ++ enum yaffs_ecc_result *ecc_result, ++ int correct_errors) ++{ ++ int ret_val; ++ struct yaffs_spare local_spare; ++ int data_size; ++ int spare_size; ++ int ecc_result1, ecc_result2; ++ u8 calc_ecc[3]; ++ ++ if (!spare) { ++ /* If we don't have a real spare, then we use a local one. */ ++ /* Need this for the calculation of the ecc */ ++ spare = &local_spare; ++ } ++ data_size = dev->data_bytes_per_chunk; ++ spare_size = sizeof(struct yaffs_spare); ++ ++ if (dev->param.use_nand_ecc) ++ return dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *) spare, spare_size, ++ ecc_result); ++ ++ ++ /* Handle the ECC at this level. */ ++ ++ ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, data_size, ++ (u8 *)spare, spare_size, ++ NULL); ++ if (!data || !correct_errors) ++ return ret_val; ++ ++ /* Do ECC correction if needed. */ ++ yaffs_ecc_calc(data, calc_ecc); ++ ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc); ++ yaffs_ecc_calc(&data[256], calc_ecc); ++ ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc); ++ ++ if (ecc_result1 > 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error fix performed on chunk %d:0", ++ nand_chunk); ++ dev->n_ecc_fixed++; ++ } else if (ecc_result1 < 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error unfixed on chunk %d:0", ++ nand_chunk); ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (ecc_result2 > 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error fix performed on chunk %d:1", ++ nand_chunk); ++ dev->n_ecc_fixed++; ++ } else if (ecc_result2 < 0) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "**>>yaffs ecc error unfixed on chunk %d:1", ++ nand_chunk); ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (ecc_result1 || ecc_result2) { ++ /* We had a data problem on this page */ ++ yaffs_handle_rd_data_error(dev, nand_chunk); ++ } ++ ++ if (ecc_result1 < 0 || ecc_result2 < 0) ++ *ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ else if (ecc_result1 > 0 || ecc_result2 > 0) ++ *ecc_result = YAFFS_ECC_RESULT_FIXED; ++ else ++ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; ++ ++ return ret_val; ++} ++ ++/* ++ * Functions for robustisizing ++ */ ++ ++static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk) ++{ ++ int flash_block = nand_chunk / dev->param.chunks_per_block; ++ ++ /* Mark the block for retirement */ ++ yaffs_get_block_info(dev, flash_block + dev->block_offset)-> ++ needs_retiring = 1; ++ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, ++ "**>>Block %d marked for retirement", ++ flash_block); ++ ++ /* TODO: ++ * Just do a garbage collection on the affected block ++ * then retire the block ++ * NB recursion ++ */ ++} ++ ++static int yaffs_tags_compat_wr(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, const struct yaffs_ext_tags *ext_tags) ++{ ++ struct yaffs_spare spare; ++ struct yaffs_tags tags; ++ ++ yaffs_spare_init(&spare); ++ ++ if (ext_tags->is_deleted) ++ spare.page_status = 0; ++ else { ++ tags.obj_id = ext_tags->obj_id; ++ tags.chunk_id = ext_tags->chunk_id; ++ ++ tags.n_bytes_lsb = ext_tags->n_bytes & (1024 - 1); ++ ++ if (dev->data_bytes_per_chunk >= 1024) ++ tags.n_bytes_msb = (ext_tags->n_bytes >> 10) & 3; ++ else ++ tags.n_bytes_msb = 3; ++ ++ tags.serial_number = ext_tags->serial_number; ++ ++ if (!dev->param.use_nand_ecc && data) { ++ yaffs_ecc_calc(data, spare.ecc1); ++ yaffs_ecc_calc(&data[256], spare.ecc2); ++ } ++ ++ yaffs_load_tags_to_spare(&spare, &tags); ++ } ++ return yaffs_wr_nand(dev, nand_chunk, data, &spare); ++} ++ ++static int yaffs_tags_compat_rd(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, struct yaffs_ext_tags *ext_tags) ++{ ++ struct yaffs_spare spare; ++ struct yaffs_tags tags; ++ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN; ++ static struct yaffs_spare spare_ff; ++ static int init; ++ int deleted; ++ ++ if (!init) { ++ memset(&spare_ff, 0xff, sizeof(spare_ff)); ++ init = 1; ++ } ++ ++ if (!yaffs_rd_chunk_nand(dev, nand_chunk, ++ data, &spare, &ecc_result, 1)) ++ return YAFFS_FAIL; ++ ++ /* ext_tags may be NULL */ ++ if (!ext_tags) ++ return YAFFS_OK; ++ ++ deleted = (hweight8(spare.page_status) < 7) ? 1 : 0; ++ ++ ext_tags->is_deleted = deleted; ++ ext_tags->ecc_result = ecc_result; ++ ext_tags->block_bad = 0; /* We're reading it */ ++ /* therefore it is not a bad block */ ++ ext_tags->chunk_used = ++ memcmp(&spare_ff, &spare, sizeof(spare_ff)) ? 1 : 0; ++ ++ if (ext_tags->chunk_used) { ++ yaffs_get_tags_from_spare(dev, &spare, &tags); ++ ext_tags->obj_id = tags.obj_id; ++ ext_tags->chunk_id = tags.chunk_id; ++ ext_tags->n_bytes = tags.n_bytes_lsb; ++ ++ if (dev->data_bytes_per_chunk >= 1024) ++ ext_tags->n_bytes |= ++ (((unsigned)tags.n_bytes_msb) << 10); ++ ++ ext_tags->serial_number = tags.serial_number; ++ } ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) ++{ ++ struct yaffs_spare spare; ++ ++ memset(&spare, 0xff, sizeof(struct yaffs_spare)); ++ ++ spare.block_status = 'Y'; ++ ++ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block, NULL, ++ &spare); ++ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block + 1, ++ NULL, &spare); ++ ++ return YAFFS_OK; ++} ++ ++static int yaffs_tags_compat_query_block(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ struct yaffs_spare spare0, spare1; ++ static struct yaffs_spare spare_ff; ++ static int init; ++ enum yaffs_ecc_result dummy; ++ ++ if (!init) { ++ memset(&spare_ff, 0xff, sizeof(spare_ff)); ++ init = 1; ++ } ++ ++ *seq_number = 0; ++ ++ /* Look for bad block markers in the first two chunks */ ++ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block, ++ NULL, &spare0, &dummy, 0); ++ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1, ++ NULL, &spare1, &dummy, 0); ++ ++ if (hweight8(spare0.block_status & spare1.block_status) < 7) ++ *state = YAFFS_BLOCK_STATE_DEAD; ++ else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0) ++ *state = YAFFS_BLOCK_STATE_EMPTY; ++ else ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ ++ return YAFFS_OK; ++} ++ ++void yaffs_tags_compat_install(struct yaffs_dev *dev) ++{ ++ if(dev->param.is_yaffs2) ++ return; ++ if(!dev->tagger.write_chunk_tags_fn) ++ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr; ++ if(!dev->tagger.read_chunk_tags_fn) ++ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd; ++ if(!dev->tagger.query_block_fn) ++ dev->tagger.query_block_fn = yaffs_tags_compat_query_block; ++ if(!dev->tagger.mark_bad_fn) ++ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; ++} +diff --git a/fs/yaffs2/yaffs_tagscompat.h b/fs/yaffs2/yaffs_tagscompat.h +new file mode 100755 +index 00000000..92d298a6 +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagscompat.h +@@ -0,0 +1,44 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_TAGSCOMPAT_H__ ++#define __YAFFS_TAGSCOMPAT_H__ ++ ++ ++#include "yaffs_guts.h" ++ ++#if 0 ++ ++ ++int yaffs_tags_compat_wr(struct yaffs_dev *dev, ++ int nand_chunk, ++ const u8 *data, const struct yaffs_ext_tags *tags); ++int yaffs_tags_compat_rd(struct yaffs_dev *dev, ++ int nand_chunk, ++ u8 *data, struct yaffs_ext_tags *tags); ++int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no); ++int yaffs_tags_compat_query_block(struct yaffs_dev *dev, ++ int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number); ++ ++#endif ++ ++ ++void yaffs_tags_compat_install(struct yaffs_dev *dev); ++void yaffs_calc_tags_ecc(struct yaffs_tags *tags); ++int yaffs_check_tags_ecc(struct yaffs_tags *tags); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_tagsmarshall.c b/fs/yaffs2/yaffs_tagsmarshall.c +new file mode 100755 +index 00000000..44a83b12 +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagsmarshall.c +@@ -0,0 +1,199 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yaffs_packedtags2.h" ++ ++static int yaffs_tags_marshall_write(struct yaffs_dev *dev, ++ int nand_chunk, const u8 *data, ++ const struct yaffs_ext_tags *tags) ++{ ++ struct yaffs_packed_tags2 pt; ++ int retval; ++ ++ int packed_tags_size = ++ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); ++ void *packed_tags_ptr = ++ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "yaffs_tags_marshall_write chunk %d data %p tags %p", ++ nand_chunk, data, tags); ++ ++ /* For yaffs2 writing there must be both data and tags. ++ * If we're using inband tags, then the tags are stuffed into ++ * the end of the data buffer. ++ */ ++ if (!data || !tags) ++ BUG(); ++ else if (dev->param.inband_tags) { ++ struct yaffs_packed_tags2_tags_only *pt2tp; ++ pt2tp = ++ (struct yaffs_packed_tags2_tags_only *)(data + ++ dev-> ++ data_bytes_per_chunk); ++ yaffs_pack_tags2_tags_only(pt2tp, tags); ++ } else { ++ yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); ++ } ++ ++ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ (dev->param.inband_tags) ? NULL : packed_tags_ptr, ++ (dev->param.inband_tags) ? 0 : packed_tags_size); ++ ++ return retval; ++} ++ ++static int yaffs_tags_marshall_read(struct yaffs_dev *dev, ++ int nand_chunk, u8 *data, ++ struct yaffs_ext_tags *tags) ++{ ++ int retval = 0; ++ int local_data = 0; ++ u8 spare_buffer[100]; ++ enum yaffs_ecc_result ecc_result; ++ ++ struct yaffs_packed_tags2 pt; ++ ++ int packed_tags_size = ++ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); ++ void *packed_tags_ptr = ++ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "yaffs_tags_marshall_read chunk %d data %p tags %p", ++ nand_chunk, data, tags); ++ ++ if (dev->param.inband_tags) { ++ if (!data) { ++ local_data = 1; ++ data = yaffs_get_temp_buffer(dev); ++ } ++ } ++ ++ if (dev->param.inband_tags || (data && !tags)) ++ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ NULL, 0, ++ &ecc_result); ++ else if (tags) ++ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, ++ data, dev->param.total_bytes_per_chunk, ++ spare_buffer, packed_tags_size, ++ &ecc_result); ++ else ++ BUG(); ++ ++ ++ if (dev->param.inband_tags) { ++ if (tags) { ++ struct yaffs_packed_tags2_tags_only *pt2tp; ++ pt2tp = ++ (struct yaffs_packed_tags2_tags_only *) ++ &data[dev->data_bytes_per_chunk]; ++ yaffs_unpack_tags2_tags_only(tags, pt2tp); ++ } ++ } else if (tags) { ++ memcpy(packed_tags_ptr, spare_buffer, packed_tags_size); ++ yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc); ++ } ++ ++ if (local_data) ++ yaffs_release_temp_buffer(dev, data); ++ ++ if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) { ++ tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; ++ dev->n_ecc_unfixed++; ++ } ++ ++ if (tags && ecc_result == -YAFFS_ECC_RESULT_FIXED) { ++ if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR) ++ tags->ecc_result = YAFFS_ECC_RESULT_FIXED; ++ dev->n_ecc_fixed++; ++ } ++ ++ if (ecc_result < YAFFS_ECC_RESULT_UNFIXED) ++ return YAFFS_OK; ++ else ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no, ++ enum yaffs_block_state *state, ++ u32 *seq_number) ++{ ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d", ++ block_no); ++ ++ retval = dev->drv.drv_check_bad_fn(dev, block_no); ++ ++ if (retval== YAFFS_FAIL) { ++ yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); ++ ++ *state = YAFFS_BLOCK_STATE_DEAD; ++ *seq_number = 0; ++ } else { ++ struct yaffs_ext_tags t; ++ ++ yaffs_tags_marshall_read(dev, ++ block_no * dev->param.chunks_per_block, ++ NULL, &t); ++ ++ if (t.chunk_used) { ++ *seq_number = t.seq_number; ++ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; ++ } else { ++ *seq_number = 0; ++ *state = YAFFS_BLOCK_STATE_EMPTY; ++ } ++ } ++ ++ yaffs_trace(YAFFS_TRACE_MTD, ++ "block query returns seq %d state %d", ++ *seq_number, *state); ++ ++ if (retval == 0) ++ return YAFFS_OK; ++ else ++ return YAFFS_FAIL; ++} ++ ++static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no) ++{ ++ return dev->drv.drv_mark_bad_fn(dev, block_no); ++ ++} ++ ++ ++void yaffs_tags_marshall_install(struct yaffs_dev *dev) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!dev->tagger.write_chunk_tags_fn) ++ dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write; ++ ++ if (!dev->tagger.read_chunk_tags_fn) ++ dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read; ++ ++ if (!dev->tagger.query_block_fn) ++ dev->tagger.query_block_fn = yaffs_tags_marshall_query_block; ++ ++ if (!dev->tagger.mark_bad_fn) ++ dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad; ++ ++} +diff --git a/fs/yaffs2/yaffs_tagsmarshall.h b/fs/yaffs2/yaffs_tagsmarshall.h +new file mode 100755 +index 00000000..bf3e68a1 +--- /dev/null ++++ b/fs/yaffs2/yaffs_tagsmarshall.h +@@ -0,0 +1,22 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_TAGSMARSHALL_H__ ++#define __YAFFS_TAGSMARSHALL_H__ ++ ++#include "yaffs_guts.h" ++void yaffs_tags_marshall_install(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_trace.h b/fs/yaffs2/yaffs_trace.h +new file mode 100755 +index 00000000..fd26054d +--- /dev/null ++++ b/fs/yaffs2/yaffs_trace.h +@@ -0,0 +1,57 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YTRACE_H__ ++#define __YTRACE_H__ ++ ++extern unsigned int yaffs_trace_mask; ++extern unsigned int yaffs_wr_attempts; ++ ++/* ++ * Tracing flags. ++ * The flags masked in YAFFS_TRACE_ALWAYS are always traced. ++ */ ++ ++#define YAFFS_TRACE_OS 0x00000002 ++#define YAFFS_TRACE_ALLOCATE 0x00000004 ++#define YAFFS_TRACE_SCAN 0x00000008 ++#define YAFFS_TRACE_BAD_BLOCKS 0x00000010 ++#define YAFFS_TRACE_ERASE 0x00000020 ++#define YAFFS_TRACE_GC 0x00000040 ++#define YAFFS_TRACE_WRITE 0x00000080 ++#define YAFFS_TRACE_TRACING 0x00000100 ++#define YAFFS_TRACE_DELETION 0x00000200 ++#define YAFFS_TRACE_BUFFERS 0x00000400 ++#define YAFFS_TRACE_NANDACCESS 0x00000800 ++#define YAFFS_TRACE_GC_DETAIL 0x00001000 ++#define YAFFS_TRACE_SCAN_DEBUG 0x00002000 ++#define YAFFS_TRACE_MTD 0x00004000 ++#define YAFFS_TRACE_CHECKPOINT 0x00008000 ++ ++#define YAFFS_TRACE_VERIFY 0x00010000 ++#define YAFFS_TRACE_VERIFY_NAND 0x00020000 ++#define YAFFS_TRACE_VERIFY_FULL 0x00040000 ++#define YAFFS_TRACE_VERIFY_ALL 0x000f0000 ++ ++#define YAFFS_TRACE_SYNC 0x00100000 ++#define YAFFS_TRACE_BACKGROUND 0x00200000 ++#define YAFFS_TRACE_LOCK 0x00400000 ++#define YAFFS_TRACE_MOUNT 0x00800000 ++ ++#define YAFFS_TRACE_ERROR 0x40000000 ++#define YAFFS_TRACE_BUG 0x80000000 ++#define YAFFS_TRACE_ALWAYS 0xf0000000 ++ ++#endif +diff --git a/fs/yaffs2/yaffs_verify.c b/fs/yaffs2/yaffs_verify.c +new file mode 100755 +index 00000000..e8f2f0a6 +--- /dev/null ++++ b/fs/yaffs2/yaffs_verify.c +@@ -0,0 +1,529 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_verify.h" ++#include "yaffs_trace.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_nand.h" ++ ++int yaffs_skip_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & ++ (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); ++} ++ ++static int yaffs_skip_full_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL)); ++} ++ ++static int yaffs_skip_nand_verification(struct yaffs_dev *dev) ++{ ++ (void) dev; ++ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND)); ++} ++ ++static const char * const block_state_name[] = { ++ "Unknown", ++ "Needs scan", ++ "Scanning", ++ "Empty", ++ "Allocating", ++ "Full", ++ "Dirty", ++ "Checkpoint", ++ "Collecting", ++ "Dead" ++}; ++ ++void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n) ++{ ++ int actually_used; ++ int in_use; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Report illegal runtime states */ ++ if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has undefined state %d", ++ n, bi->block_state); ++ ++ switch (bi->block_state) { ++ case YAFFS_BLOCK_STATE_UNKNOWN: ++ case YAFFS_BLOCK_STATE_SCANNING: ++ case YAFFS_BLOCK_STATE_NEEDS_SCAN: ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has bad run-state %s", ++ n, block_state_name[bi->block_state]); ++ } ++ ++ /* Check pages in use and soft deletions are legal */ ++ ++ actually_used = bi->pages_in_use - bi->soft_del_pages; ++ ++ if (bi->pages_in_use < 0 || ++ bi->pages_in_use > dev->param.chunks_per_block || ++ bi->soft_del_pages < 0 || ++ bi->soft_del_pages > dev->param.chunks_per_block || ++ actually_used < 0 || actually_used > dev->param.chunks_per_block) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has illegal values pages_in_used %d soft_del_pages %d", ++ n, bi->pages_in_use, bi->soft_del_pages); ++ ++ /* Check chunk bitmap legal */ ++ in_use = yaffs_count_chunk_bits(dev, n); ++ if (in_use != bi->pages_in_use) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Block %d has inconsistent values pages_in_use %d counted chunk bits %d", ++ n, bi->pages_in_use, in_use); ++} ++ ++void yaffs_verify_collected_blk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, int n) ++{ ++ yaffs_verify_blk(dev, bi, n); ++ ++ /* After collection the block should be in the erased state */ ++ ++ if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING && ++ bi->block_state != YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Block %d is in state %d after gc, should be erased", ++ n, bi->block_state); ++ } ++} ++ ++void yaffs_verify_blocks(struct yaffs_dev *dev) ++{ ++ int i; ++ int state_count[YAFFS_NUMBER_OF_BLOCK_STATES]; ++ int illegal_states = 0; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ memset(state_count, 0, sizeof(state_count)); ++ ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i); ++ yaffs_verify_blk(dev, bi, i); ++ ++ if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES) ++ state_count[bi->block_state]++; ++ else ++ illegal_states++; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_VERIFY, "Block summary"); ++ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "%d blocks have illegal states", ++ illegal_states); ++ if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Too many allocating blocks"); ++ ++ for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "%s %d blocks", ++ block_state_name[i], state_count[i]); ++ ++ if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT]) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Checkpoint block count wrong dev %d count %d", ++ dev->blocks_in_checkpt, ++ state_count[YAFFS_BLOCK_STATE_CHECKPOINT]); ++ ++ if (dev->n_erased_blocks != state_count[YAFFS_BLOCK_STATE_EMPTY]) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Erased block count wrong dev %d count %d", ++ dev->n_erased_blocks, ++ state_count[YAFFS_BLOCK_STATE_EMPTY]); ++ ++ if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Too many collecting blocks %d (max is 1)", ++ state_count[YAFFS_BLOCK_STATE_COLLECTING]); ++} ++ ++/* ++ * Verify the object header. oh must be valid, but obj and tags may be NULL in ++ * which case those tests will not be performed. ++ */ ++void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, ++ struct yaffs_ext_tags *tags, int parent_check) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ if (!(tags && obj && oh)) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Verifying object header tags %p obj %p oh %p", ++ tags, obj, oh); ++ return; ++ } ++ ++ if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || ++ oh->type > YAFFS_OBJECT_TYPE_MAX) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header type is illegal value 0x%x", ++ tags->obj_id, oh->type); ++ ++ if (tags->obj_id != obj->obj_id) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch obj_id %d", ++ tags->obj_id, obj->obj_id); ++ ++ /* ++ * Check that the object's parent ids match if parent_check requested. ++ * ++ * Tests do not apply to the root object. ++ */ ++ ++ if (parent_check && tags->obj_id > 1 && !obj->parent) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch parent_id %d obj->parent is NULL", ++ tags->obj_id, oh->parent_obj_id); ++ ++ if (parent_check && obj->parent && ++ oh->parent_obj_id != obj->parent->obj_id && ++ (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED || ++ obj->parent->obj_id != YAFFS_OBJECTID_DELETED)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header mismatch parent_id %d parent_obj_id %d", ++ tags->obj_id, oh->parent_obj_id, ++ obj->parent->obj_id); ++ ++ if (tags->obj_id > 1 && oh->name[0] == 0) /* Null name */ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header name is NULL", ++ obj->obj_id); ++ ++ if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff) /* Junk name */ ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d header name is 0xff", ++ obj->obj_id); ++} ++ ++void yaffs_verify_file(struct yaffs_obj *obj) ++{ ++ u32 x; ++ int required_depth; ++ int actual_depth; ++ int last_chunk; ++ u32 offset_in_chunk; ++ u32 the_chunk; ++ ++ u32 i; ++ struct yaffs_dev *dev; ++ struct yaffs_ext_tags tags; ++ struct yaffs_tnode *tn; ++ u32 obj_id; ++ ++ if (!obj) ++ return; ++ ++ if (yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ dev = obj->my_dev; ++ obj_id = obj->obj_id; ++ ++ ++ /* Check file size is consistent with tnode depth */ ++ yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size, ++ &last_chunk, &offset_in_chunk); ++ last_chunk++; ++ x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS; ++ required_depth = 0; ++ while (x > 0) { ++ x >>= YAFFS_TNODES_INTERNAL_BITS; ++ required_depth++; ++ } ++ ++ actual_depth = obj->variant.file_variant.top_level; ++ ++ /* Check that the chunks in the tnode tree are all correct. ++ * We do this by scanning through the tnode tree and ++ * checking the tags for every chunk match. ++ */ ++ ++ if (yaffs_skip_nand_verification(dev)) ++ return; ++ ++ for (i = 1; i <= last_chunk; i++) { ++ tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i); ++ ++ if (!tn) ++ continue; ++ ++ the_chunk = yaffs_get_group_base(dev, tn, i); ++ if (the_chunk > 0) { ++ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL, ++ &tags); ++ if (tags.obj_id != obj_id || tags.chunk_id != i) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)", ++ obj_id, i, the_chunk, ++ tags.obj_id, tags.chunk_id); ++ } ++ } ++} ++ ++void yaffs_verify_link(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ /* Verify sane equivalent object */ ++} ++ ++void yaffs_verify_symlink(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ /* Verify symlink string */ ++} ++ ++void yaffs_verify_special(struct yaffs_obj *obj) ++{ ++ if (obj && yaffs_skip_verification(obj->my_dev)) ++ return; ++} ++ ++void yaffs_verify_obj(struct yaffs_obj *obj) ++{ ++ struct yaffs_dev *dev; ++ u32 chunk_min; ++ u32 chunk_max; ++ u32 chunk_id_ok; ++ u32 chunk_in_range; ++ u32 chunk_wrongly_deleted; ++ u32 chunk_valid; ++ ++ if (!obj) ++ return; ++ ++ if (obj->being_created) ++ return; ++ ++ dev = obj->my_dev; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Check sane object header chunk */ ++ ++ chunk_min = dev->internal_start_block * dev->param.chunks_per_block; ++ chunk_max = ++ (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1; ++ ++ chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min && ++ ((unsigned)(obj->hdr_chunk)) <= chunk_max); ++ chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0); ++ chunk_valid = chunk_in_range && ++ yaffs_check_chunk_bit(dev, ++ obj->hdr_chunk / dev->param.chunks_per_block, ++ obj->hdr_chunk % dev->param.chunks_per_block); ++ chunk_wrongly_deleted = chunk_in_range && !chunk_valid; ++ ++ if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted)) ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has chunk_id %d %s %s", ++ obj->obj_id, obj->hdr_chunk, ++ chunk_id_ok ? "" : ",out of range", ++ chunk_wrongly_deleted ? ",marked as deleted" : ""); ++ ++ if (chunk_valid && !yaffs_skip_nand_verification(dev)) { ++ struct yaffs_ext_tags tags; ++ struct yaffs_obj_hdr *oh; ++ u8 *buffer = yaffs_get_temp_buffer(dev); ++ ++ oh = (struct yaffs_obj_hdr *)buffer; ++ ++ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags); ++ ++ yaffs_verify_oh(obj, oh, &tags, 1); ++ ++ yaffs_release_temp_buffer(dev, buffer); ++ } ++ ++ /* Verify it has a parent */ ++ if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has parent pointer %p which does not look like an object", ++ obj->obj_id, obj->parent); ++ } ++ ++ /* Verify parent is a directory */ ++ if (obj->parent && ++ obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d's parent is not a directory (type %d)", ++ obj->obj_id, obj->parent->variant_type); ++ } ++ ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ yaffs_verify_file(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ yaffs_verify_symlink(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ yaffs_verify_dir(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ yaffs_verify_link(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ yaffs_verify_special(obj); ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ default: ++ yaffs_trace(YAFFS_TRACE_VERIFY, ++ "Obj %d has illegaltype %d", ++ obj->obj_id, obj->variant_type); ++ break; ++ } ++} ++ ++void yaffs_verify_objects(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ int i; ++ struct list_head *lh; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each(lh, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ yaffs_verify_obj(obj); ++ } ++ } ++} ++ ++void yaffs_verify_obj_in_dir(struct yaffs_obj *obj) ++{ ++ struct list_head *lh; ++ struct yaffs_obj *list_obj; ++ int count = 0; ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify"); ++ BUG(); ++ return; ++ } ++ ++ if (yaffs_skip_verification(obj->my_dev)) ++ return; ++ ++ if (!obj->parent) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent"); ++ BUG(); ++ return; ++ } ++ ++ if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory"); ++ BUG(); ++ } ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ list_for_each(lh, &obj->parent->variant.dir_variant.children) { ++ list_obj = list_entry(lh, struct yaffs_obj, siblings); ++ yaffs_verify_obj(list_obj); ++ if (obj == list_obj) ++ count++; ++ } ++ ++ if (count != 1) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Object in directory %d times", ++ count); ++ BUG(); ++ } ++} ++ ++void yaffs_verify_dir(struct yaffs_obj *directory) ++{ ++ struct list_head *lh; ++ struct yaffs_obj *list_obj; ++ ++ if (!directory) { ++ BUG(); ++ return; ++ } ++ ++ if (yaffs_skip_full_verification(directory->my_dev)) ++ return; ++ ++ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Directory has wrong type: %d", ++ directory->variant_type); ++ BUG(); ++ } ++ ++ /* Iterate through the objects in each hash entry */ ++ ++ list_for_each(lh, &directory->variant.dir_variant.children) { ++ list_obj = list_entry(lh, struct yaffs_obj, siblings); ++ if (list_obj->parent != directory) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Object in directory list has wrong parent %p", ++ list_obj->parent); ++ BUG(); ++ } ++ yaffs_verify_obj_in_dir(list_obj); ++ } ++} ++ ++static int yaffs_free_verification_failures; ++ ++void yaffs_verify_free_chunks(struct yaffs_dev *dev) ++{ ++ int counted; ++ int difference; ++ ++ if (yaffs_skip_verification(dev)) ++ return; ++ ++ counted = yaffs_count_free_chunks(dev); ++ ++ difference = dev->n_free_chunks - counted; ++ ++ if (difference) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Freechunks verification failure %d %d %d", ++ dev->n_free_chunks, counted, difference); ++ yaffs_free_verification_failures++; ++ } ++} ++ ++int yaffs_verify_file_sane(struct yaffs_obj *in) ++{ ++ (void) in; ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_verify.h b/fs/yaffs2/yaffs_verify.h +new file mode 100755 +index 00000000..4f4af8d2 +--- /dev/null ++++ b/fs/yaffs2/yaffs_verify.h +@@ -0,0 +1,43 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_VERIFY_H__ ++#define __YAFFS_VERIFY_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, ++ int n); ++void yaffs_verify_collected_blk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, int n); ++void yaffs_verify_blocks(struct yaffs_dev *dev); ++ ++void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, ++ struct yaffs_ext_tags *tags, int parent_check); ++void yaffs_verify_file(struct yaffs_obj *obj); ++void yaffs_verify_link(struct yaffs_obj *obj); ++void yaffs_verify_symlink(struct yaffs_obj *obj); ++void yaffs_verify_special(struct yaffs_obj *obj); ++void yaffs_verify_obj(struct yaffs_obj *obj); ++void yaffs_verify_objects(struct yaffs_dev *dev); ++void yaffs_verify_obj_in_dir(struct yaffs_obj *obj); ++void yaffs_verify_dir(struct yaffs_obj *directory); ++void yaffs_verify_free_chunks(struct yaffs_dev *dev); ++ ++int yaffs_verify_file_sane(struct yaffs_obj *obj); ++ ++int yaffs_skip_verification(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c +new file mode 100755 +index 00000000..75e8ef20 +--- /dev/null ++++ b/fs/yaffs2/yaffs_vfs.c +@@ -0,0 +1,3354 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * Acknowledgements: ++ * Luc van OostenRyck for numerous patches. ++ * Nick Bane for numerous patches. ++ * Nick Bane for 2.5/2.6 integration. ++ * Andras Toth for mknod rdev issue. ++ * Michael Fischer for finding the problem with inode inconsistency. ++ * Some code bodily lifted from JFFS ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/* ++ * ++ * This is the file system front-end to YAFFS that hooks it up to ++ * the VFS. ++ * ++ * Special notes: ++ * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with ++ * this superblock ++ * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this ++ * superblock ++ * >> inode->u.generic_ip points to the associated struct yaffs_obj. ++ */ ++ ++/* ++ * There are two variants of the VFS glue code. This variant should compile ++ * for any version of Linux. ++ */ ++#include <linux/version.h> ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)) ++#define YAFFS_COMPILE_BACKGROUND ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)) ++#define YAFFS_COMPILE_FREEZER ++#endif ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#define YAFFS_COMPILE_EXPORTFS ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++#define YAFFS_USE_SETATTR_COPY ++#define YAFFS_USE_TRUNCATE_SETSIZE ++#endif ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)) ++#define YAFFS_HAS_EVICT_INODE ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) ++#define YAFFS_NEW_FOLLOW_LINK 1 ++#else ++#define YAFFS_NEW_FOLLOW_LINK 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) ++#define YAFFS_HAS_WRITE_SUPER ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++#include <linux/config.h> ++#endif ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/fs.h> ++#include <linux/proc_fs.h> ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) ++#include <linux/smp_lock.h> ++#endif ++#include <linux/pagemap.h> ++#include <linux/mtd/mtd.h> ++#include <linux/interrupt.h> ++#include <linux/string.h> ++#include <linux/ctype.h> ++ ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++#include <linux/namei.h> ++#endif ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++#include <linux/exportfs.h> ++#endif ++ ++#ifdef YAFFS_COMPILE_BACKGROUND ++#include <linux/kthread.h> ++#include <linux/delay.h> ++#endif ++#ifdef YAFFS_COMPILE_FREEZER ++#include <linux/freezer.h> ++#endif ++ ++#include <asm/div64.h> ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ ++#include <linux/statfs.h> ++ ++#define UnlockPage(p) unlock_page(p) ++#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) ++ ++/* FIXME: use sb->s_id instead ? */ ++#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) ++ ++#else ++ ++#include <linux/locks.h> ++#define BDEVNAME_SIZE 0 ++#define yaffs_devname(sb, buf) kdevname(sb->s_dev) ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)) ++/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */ ++#define __user ++#endif ++ ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) ++#define YPROC_ROOT (&proc_root) ++#else ++#define YPROC_ROOT NULL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) ++#define Y_INIT_TIMER(a) init_timer(a) ++#else ++#define Y_INIT_TIMER(a) init_timer_on_stack(a) ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)) ++#define YAFFS_USE_WRITE_BEGIN_END 1 ++#else ++#define YAFFS_USE_WRITE_BEGIN_END 0 ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) ++#define YAFFS_SUPER_HAS_DIRTY ++#endif ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) ++#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0) ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) ++static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) ++{ ++ uint64_t result = partition_size; ++ do_div(result, block_size); ++ return (uint32_t) result; ++} ++#else ++#define YCALCBLOCKS(s, b) ((s)/(b)) ++#endif ++ ++#include <linux/uaccess.h> ++#include <linux/mtd/mtd.h> ++ ++#include "yportenv.h" ++#include "yaffs_trace.h" ++#include "yaffs_guts.h" ++#include "yaffs_attribs.h" ++ ++#include "yaffs_linux.h" ++ ++#include "yaffs_mtdif.h" ++ ++unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS; ++unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; ++unsigned int yaffs_auto_checkpoint = 1; ++unsigned int yaffs_gc_control = 1; ++unsigned int yaffs_bg_enable = 1; ++unsigned int yaffs_auto_select = 1; ++/* Module Parameters */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++module_param(yaffs_trace_mask, uint, 0644); ++module_param(yaffs_wr_attempts, uint, 0644); ++module_param(yaffs_auto_checkpoint, uint, 0644); ++module_param(yaffs_gc_control, uint, 0644); ++module_param(yaffs_bg_enable, uint, 0644); ++#else ++MODULE_PARM(yaffs_trace_mask, "i"); ++MODULE_PARM(yaffs_wr_attempts, "i"); ++MODULE_PARM(yaffs_auto_checkpoint, "i"); ++MODULE_PARM(yaffs_gc_control, "i"); ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) ++/* use iget and read_inode */ ++#define Y_IGET(sb, inum) iget((sb), (inum)) ++ ++#else ++/* Call local equivalent */ ++#define YAFFS_USE_OWN_IGET ++#define Y_IGET(sb, inum) yaffs_iget((sb), (inum)) ++ ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) ++#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private) ++#else ++#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip) ++#endif ++ ++#define yaffs_inode_to_obj(iptr) \ ++ ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr))) ++#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode) ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info) ++#else ++#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) ++#define Y_CLEAR_INODE(i) clear_inode(i) ++#else ++#define Y_CLEAR_INODE(i) end_writeback(i) ++#endif ++ ++ ++#define update_dir_time(dir) do {\ ++ (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \ ++ } while (0) ++ ++static void yaffs_fill_inode_from_obj(struct inode *inode, ++ struct yaffs_obj *obj); ++ ++ ++static void yaffs_gross_lock(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current); ++ mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock)); ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current); ++} ++ ++static void yaffs_gross_unlock(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current); ++ mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock)); ++} ++ ++ ++static int yaffs_readpage_nolock(struct file *f, struct page *pg) ++{ ++ /* Lifted from jffs2 */ ++ ++ struct yaffs_obj *obj; ++ unsigned char *pg_buf; ++ int ret; ++ loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readpage_nolock at %lld, size %08x", ++ (long long)pos, ++ (unsigned)PAGE_CACHE_SIZE); ++ ++ obj = yaffs_dentry_to_obj(f->f_dentry); ++ ++ dev = obj->my_dev; ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ BUG_ON(!PageLocked(pg)); ++#else ++ if (!PageLocked(pg)) ++ PAGE_BUG(pg); ++#endif ++ ++ pg_buf = kmap(pg); ++ /* FIXME: Can kmap fail? */ ++ ++ yaffs_gross_lock(dev); ++ ++ ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (ret >= 0) ++ ret = 0; ++ ++ if (ret) { ++ ClearPageUptodate(pg); ++ SetPageError(pg); ++ } else { ++ SetPageUptodate(pg); ++ ClearPageError(pg); ++ } ++ ++ flush_dcache_page(pg); ++ kunmap(pg); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done"); ++ return ret; ++} ++ ++static int yaffs_readpage_unlock(struct file *f, struct page *pg) ++{ ++ int ret = yaffs_readpage_nolock(f, pg); ++ UnlockPage(pg); ++ return ret; ++} ++ ++static int yaffs_readpage(struct file *f, struct page *pg) ++{ ++ int ret; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage"); ++ ret = yaffs_readpage_unlock(f, pg); ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done"); ++ return ret; ++} ++ ++ ++static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val) ++{ ++ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev); ++ ++ if (lc) ++ lc->dirty = val; ++ ++# ifdef YAFFS_SUPER_HAS_DIRTY ++ { ++ struct super_block *sb = lc->super; ++ ++ if (sb) ++ sb->s_dirt = val; ++ } ++#endif ++ ++} ++ ++static void yaffs_set_super_dirty(struct yaffs_dev *dev) ++{ ++ yaffs_set_super_dirty_val(dev, 1); ++} ++ ++static void yaffs_clear_super_dirty(struct yaffs_dev *dev) ++{ ++ yaffs_set_super_dirty_val(dev, 0); ++} ++ ++static int yaffs_check_super_dirty(struct yaffs_dev *dev) ++{ ++ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev); ++ ++ if (lc && lc->dirty) ++ return 1; ++ ++# ifdef YAFFS_SUPER_HAS_DIRTY ++ { ++ struct super_block *sb = lc->super; ++ ++ if (sb && sb->s_dirt) ++ return 1; ++ } ++#endif ++ return 0; ++ ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_writepage(struct page *page, struct writeback_control *wbc) ++#else ++static int yaffs_writepage(struct page *page) ++#endif ++{ ++ struct yaffs_dev *dev; ++ struct address_space *mapping = page->mapping; ++ struct inode *inode; ++ unsigned long end_index; ++ char *buffer; ++ struct yaffs_obj *obj; ++ int n_written = 0; ++ unsigned n_bytes; ++ loff_t i_size; ++ ++ if (!mapping) ++ BUG(); ++ inode = mapping->host; ++ if (!inode) ++ BUG(); ++ i_size = i_size_read(inode); ++ ++ end_index = i_size >> PAGE_CACHE_SHIFT; ++ ++ if (page->index < end_index) ++ n_bytes = PAGE_CACHE_SIZE; ++ else { ++ n_bytes = i_size & (PAGE_CACHE_SIZE - 1); ++ ++ if (page->index > end_index || !n_bytes) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_writepage at %lld, inode size = %lld!!", ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, ++ inode->i_size); ++ yaffs_trace(YAFFS_TRACE_OS, ++ " -> don't care!!"); ++ ++ zero_user_segment(page, 0, PAGE_CACHE_SIZE); ++ set_page_writeback(page); ++ unlock_page(page); ++ end_page_writeback(page); ++ return 0; ++ } ++ } ++ ++ if (n_bytes != PAGE_CACHE_SIZE) ++ zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE); ++ ++ get_page(page); ++ ++ buffer = kmap(page); ++ ++ obj = yaffs_inode_to_obj(inode); ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_writepage at %lld, size %08x", ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "writepag0: obj = %lld, ino = %lld", ++ obj->variant.file_variant.file_size, inode->i_size); ++ ++ n_written = yaffs_wr_file(obj, buffer, ++ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0); ++ ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "writepag1: obj = %lld, ino = %lld", ++ obj->variant.file_variant.file_size, inode->i_size); ++ ++ yaffs_gross_unlock(dev); ++ ++ kunmap(page); ++ set_page_writeback(page); ++ unlock_page(page); ++ end_page_writeback(page); ++ put_page(page); ++ ++ return (n_written == n_bytes) ? 0 : -ENOSPC; ++} ++ ++/* Space holding and freeing is done to ensure we have space available for write_begin/end */ ++/* For now we just assume few parallel writes and check against a small number. */ ++/* Todo: need to do this with a counter to handle parallel reads better */ ++ ++static ssize_t yaffs_hold_space(struct file *f) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ int n_free_chunks; ++ ++ obj = yaffs_dentry_to_obj(f->f_dentry); ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ n_free_chunks = yaffs_get_n_free_chunks(dev); ++ ++ yaffs_gross_unlock(dev); ++ ++ return (n_free_chunks > 20) ? 1 : 0; ++} ++ ++static void yaffs_release_space(struct file *f) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_dentry_to_obj(f->f_dentry); ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_gross_unlock(dev); ++} ++ ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++static int yaffs_write_begin(struct file *filp, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned flags, ++ struct page **pagep, void **fsdata) ++{ ++ struct page *pg = NULL; ++ pgoff_t index = pos >> PAGE_CACHE_SHIFT; ++ ++ int ret = 0; ++ int space_held = 0; ++ ++ /* Get a page */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) ++ pg = grab_cache_page_write_begin(mapping, index, flags); ++#else ++ pg = __grab_cache_page(mapping, index); ++#endif ++ ++ *pagep = pg; ++ if (!pg) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "start yaffs_write_begin index %d(%x) uptodate %d", ++ (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0); ++ ++ /* Get fs space */ ++ space_held = yaffs_hold_space(filp); ++ ++ if (!space_held) { ++ ret = -ENOSPC; ++ goto out; ++ } ++ ++ /* Update page if required */ ++ ++ if (!Page_Uptodate(pg)) ++ ret = yaffs_readpage_nolock(filp, pg); ++ ++ if (ret) ++ goto out; ++ ++ /* Happy path return */ ++ yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok"); ++ ++ return 0; ++ ++out: ++ yaffs_trace(YAFFS_TRACE_OS, ++ "end yaffs_write_begin fail returning %d", ret); ++ if (space_held) ++ yaffs_release_space(filp); ++ if (pg) { ++ unlock_page(pg); ++ page_cache_release(pg); ++ } ++ return ret; ++} ++ ++#else ++ ++static int yaffs_prepare_write(struct file *f, struct page *pg, ++ unsigned offset, unsigned to) ++{ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write"); ++ ++ if (!Page_Uptodate(pg)) ++ return yaffs_readpage_nolock(f, pg); ++ return 0; ++} ++#endif ++ ++ ++static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, ++ loff_t * pos) ++{ ++ struct yaffs_obj *obj; ++ int n_written; ++ loff_t ipos; ++ struct inode *inode; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_dentry_to_obj(f->f_dentry); ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write: hey obj is null!"); ++ return -EINVAL; ++ } ++ ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ inode = f->f_dentry->d_inode; ++ ++ if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) ++ ipos = inode->i_size; ++ else ++ ipos = *pos; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld", ++ (unsigned)n, (unsigned)n, obj->obj_id, ipos); ++ ++ n_written = yaffs_wr_file(obj, buf, ipos, n, 0); ++ ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write: %d(%x) bytes written", ++ (unsigned)n, (unsigned)n); ++ ++ if (n_written > 0) { ++ ipos += n_written; ++ *pos = ipos; ++ if (ipos > inode->i_size) { ++ inode->i_size = ipos; ++ inode->i_blocks = (ipos + 511) >> 9; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_write size updated to %lld bytes, %d blocks", ++ ipos, (int)(inode->i_blocks)); ++ } ++ ++ } ++ yaffs_gross_unlock(dev); ++ return (n_written == 0) && (n > 0) ? -ENOSPC : n_written; ++} ++ ++ ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++static int yaffs_write_end(struct file *filp, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned copied, ++ struct page *pg, void *fsdadata) ++{ ++ int ret = 0; ++ void *addr, *kva; ++ uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1); ++ ++ kva = kmap(pg); ++ addr = kva + offset_into_page; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_write_end addr %p pos %lld n_bytes %d", ++ addr, pos, copied); ++ ++ ret = yaffs_file_write(filp, addr, copied, &pos); ++ ++ if (ret != copied) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_write_end not same size ret %d copied %d", ++ ret, copied); ++ SetPageError(pg); ++ } ++ ++ kunmap(pg); ++ ++ yaffs_release_space(filp); ++ unlock_page(pg); ++ page_cache_release(pg); ++ return ret; ++} ++#else ++ ++static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, ++ unsigned to) ++{ ++ void *addr, *kva; ++ ++ loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; ++ int n_bytes = to - offset; ++ int n_written; ++ ++ kva = kmap(pg); ++ addr = kva + offset; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write addr %p pos %lld n_bytes %d", ++ addr, pos, n_bytes); ++ ++ n_written = yaffs_file_write(f, addr, n_bytes, &pos); ++ ++ if (n_written != n_bytes) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write not same size n_written %d n_bytes %d", ++ n_written, n_bytes); ++ SetPageError(pg); ++ } ++ kunmap(pg); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_commit_write returning %d", ++ n_written == n_bytes ? 0 : n_written); ++ ++ return n_written == n_bytes ? 0 : n_written; ++} ++#endif ++ ++static struct address_space_operations yaffs_file_address_operations = { ++ .readpage = yaffs_readpage, ++ .writepage = yaffs_writepage, ++#if (YAFFS_USE_WRITE_BEGIN_END > 0) ++ .write_begin = yaffs_write_begin, ++ .write_end = yaffs_write_end, ++#else ++ .prepare_write = yaffs_prepare_write, ++ .commit_write = yaffs_commit_write, ++#endif ++}; ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_file_flush(struct file *file, fl_owner_t id) ++#else ++static int yaffs_file_flush(struct file *file) ++#endif ++{ ++ struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry); ++ ++ struct yaffs_dev *dev = obj->my_dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_file_flush object %d (%s)", ++ obj->obj_id, ++ obj->dirty ? "dirty" : "clean"); ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_flush_file(obj, 1, 0); ++ ++ yaffs_gross_unlock(dev); ++ ++ return 0; ++} ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)) ++static int yaffs_sync_object(struct file *file, int datasync) ++#else ++static int yaffs_sync_object(struct file *file, struct dentry *dentry, ++ int datasync) ++#endif ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34)) ++ struct dentry *dentry = file->f_path.dentry; ++#endif ++ ++ obj = yaffs_dentry_to_obj(dentry); ++ ++ dev = obj->my_dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ++ "yaffs_sync_object"); ++ yaffs_gross_lock(dev); ++ yaffs_flush_file(obj, 1, datasync); ++ yaffs_gross_unlock(dev); ++ return 0; ++} ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)) ++static const struct file_operations yaffs_file_operations = { ++ .read = do_sync_read, ++ .write = do_sync_write, ++ .aio_read = generic_file_aio_read, ++ .aio_write = generic_file_aio_write, ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++ .splice_read = generic_file_splice_read, ++ .splice_write = generic_file_splice_write, ++ .llseek = generic_file_llseek, ++}; ++ ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) ++ ++static const struct file_operations yaffs_file_operations = { ++ .read = do_sync_read, ++ .write = do_sync_write, ++ .aio_read = generic_file_aio_read, ++ .aio_write = generic_file_aio_write, ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++ .sendfile = generic_file_sendfile, ++}; ++ ++#else ++ ++static const struct file_operations yaffs_file_operations = { ++ .read = generic_file_read, ++ .write = generic_file_write, ++ .mmap = generic_file_mmap, ++ .flush = yaffs_file_flush, ++ .fsync = yaffs_sync_object, ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ .sendfile = generic_file_sendfile, ++#endif ++}; ++#endif ++ ++ ++ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) ++static void zero_user_segment(struct page *page, unsigned start, unsigned end) ++{ ++ void *kaddr = kmap_atomic(page, KM_USER0); ++ memset(kaddr + start, 0, end - start); ++ kunmap_atomic(kaddr, KM_USER0); ++ flush_dcache_page(page); ++} ++#endif ++ ++ ++static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize) ++{ ++#ifdef YAFFS_USE_TRUNCATE_SETSIZE ++ truncate_setsize(inode, newsize); ++ return 0; ++#else ++ truncate_inode_pages(&inode->i_data, newsize); ++ return 0; ++#endif ++ ++} ++ ++ ++static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr) ++{ ++#ifdef YAFFS_USE_SETATTR_COPY ++ setattr_copy(inode, attr); ++ return 0; ++#else ++ return inode_setattr(inode, attr); ++#endif ++ ++} ++ ++static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_setattr of object %d", ++ yaffs_inode_to_obj(inode)->obj_id); ++#if 0 ++ /* Fail if a requested resize >= 2GB */ ++ if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31)) ++ error = -EINVAL; ++#endif ++ ++ if (error == 0) ++ error = inode_change_ok(inode, attr); ++ if (error == 0) { ++ int result; ++ if (!error) { ++ error = yaffs_vfs_setattr(inode, attr); ++ yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called"); ++ if (attr->ia_valid & ATTR_SIZE) { ++ yaffs_vfs_setsize(inode, attr->ia_size); ++ inode->i_blocks = (inode->i_size + 511) >> 9; ++ } ++ } ++ dev = yaffs_inode_to_obj(inode)->my_dev; ++ if (attr->ia_valid & ATTR_SIZE) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "resize to %d(%x)", ++ (int)(attr->ia_size), ++ (int)(attr->ia_size)); ++ } ++ yaffs_gross_lock(dev); ++ result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr); ++ if (result == YAFFS_OK) { ++ error = 0; ++ } else { ++ error = -EPERM; ++ } ++ yaffs_gross_unlock(dev); ++ ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error); ++ ++ return error; ++} ++ ++static int yaffs_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ int result; ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ result = yaffs_set_xattrib(obj, name, value, size, flags); ++ if (result == YAFFS_OK) ++ error = 0; ++ else if (result < 0) ++ error = result; ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error); ++ ++ return error; ++} ++ ++static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name, ++ void *buff, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_getxattr \"%s\" from object %d", ++ name, obj->obj_id); ++ ++ if (error == 0) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ error = yaffs_get_xattrib(obj, name, buff, size); ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error); ++ ++ return error; ++} ++ ++static int yaffs_removexattr(struct dentry *dentry, const char *name) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_removexattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ int result; ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ result = yaffs_remove_xattrib(obj, name); ++ if (result == YAFFS_OK) ++ error = 0; ++ else if (result < 0) ++ error = result; ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_removexattr done returning %d", error); ++ ++ return error; ++} ++ ++static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++ int error = 0; ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_listxattr of object %d", obj->obj_id); ++ ++ if (error == 0) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ error = yaffs_list_xattrib(obj, buff, size); ++ yaffs_gross_unlock(dev); ++ ++ } ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_listxattr done returning %d", error); ++ ++ return error; ++} ++ ++ ++static const struct inode_operations yaffs_file_inode_operations = { ++ .setattr = yaffs_setattr, ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .listxattr = yaffs_listxattr, ++ .removexattr = yaffs_removexattr, ++}; ++ ++ ++static int yaffs_readlink(struct dentry *dentry, char __user * buffer, ++ int buflen) ++{ ++ unsigned char *alias; ++ int ret; ++ ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry)); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (!alias) ++ return -ENOMEM; ++ ++ ret = vfs_readlink(dentry, buffer, buflen, alias); ++ kfree(alias); ++ return ret; ++} ++ ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ void *ret; ++#else ++static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ int ret ++#endif ++ unsigned char *alias; ++ int ret_int = 0; ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry)); ++ yaffs_gross_unlock(dev); ++ ++ if (!alias) { ++ ret_int = -ENOMEM; ++ goto out; ++ } ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++ nd_set_link(nd, alias); ++ ret = alias; ++out: ++ if (ret_int) ++ ret = ERR_PTR(ret_int); ++ return ret; ++#else ++ ret = vfs_follow_link(nd, alias); ++ kfree(alias); ++out: ++ if (ret_int) ++ ret = ret_int; ++ return ret; ++#endif ++} ++ ++ ++#ifdef YAFFS_HAS_PUT_INODE ++ ++/* For now put inode is just for debugging ++ * Put inode is called when the inode **structure** is put. ++ */ ++static void yaffs_put_inode(struct inode *inode) ++{ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_put_inode: ino %d, count %d"), ++ (int)inode->i_ino, atomic_read(&inode->i_count); ++ ++} ++#endif ++ ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias) ++{ ++ kfree(alias); ++} ++#endif ++ ++static const struct inode_operations yaffs_symlink_inode_operations = { ++ .readlink = yaffs_readlink, ++ .follow_link = yaffs_follow_link, ++#if (YAFFS_NEW_FOLLOW_LINK == 1) ++ .put_link = yaffs_put_link, ++#endif ++ .setattr = yaffs_setattr, ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .listxattr = yaffs_listxattr, ++ .removexattr = yaffs_removexattr, ++}; ++ ++#ifdef YAFFS_USE_OWN_IGET ++ ++static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino) ++{ ++ struct inode *inode; ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino); ++ ++ inode = iget_locked(sb, ino); ++ if (!inode) ++ return ERR_PTR(-ENOMEM); ++ if (!(inode->i_state & I_NEW)) ++ return inode; ++ ++ /* NB This is called as a side effect of other functions, but ++ * we had to release the lock to prevent deadlocks, so ++ * need to lock again. ++ */ ++ ++ yaffs_gross_lock(dev); ++ ++ obj = yaffs_find_by_number(dev, inode->i_ino); ++ ++ yaffs_fill_inode_from_obj(inode, obj); ++ ++ yaffs_gross_unlock(dev); ++ ++ unlock_new_inode(inode); ++ return inode; ++} ++ ++#else ++ ++static void yaffs_read_inode(struct inode *inode) ++{ ++ /* NB This is called as a side effect of other functions, but ++ * we had to release the lock to prevent deadlocks, so ++ * need to lock again. ++ */ ++ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_inode for %d", (int)inode->i_ino); ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_lock(dev); ++ ++ obj = yaffs_find_by_number(dev, inode->i_ino); ++ ++ yaffs_fill_inode_from_obj(inode, obj); ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_unlock(dev); ++} ++ ++#endif ++ ++ ++ ++struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, ++ struct yaffs_obj *obj) ++{ ++ struct inode *inode; ++ ++ if (!sb) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for NULL super_block!!"); ++ return NULL; ++ ++ } ++ ++ if (!obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for NULL object!!"); ++ return NULL; ++ ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_get_inode for object %d", obj->obj_id); ++ ++ inode = Y_IGET(sb, obj->obj_id); ++ if (IS_ERR(inode)) ++ return NULL; ++ ++ /* NB Side effect: iget calls back to yaffs_read_inode(). */ ++ /* iget also increments the inode's i_count */ ++ /* NB You can't be holding gross_lock or deadlock will happen! */ ++ ++ return inode; ++} ++ ++ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) ++#define YCRED(x) x ++#else ++#define YCRED(x) (x->cred) ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t rdev) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ dev_t rdev) ++#else ++static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ int rdev) ++#endif ++{ ++ struct inode *inode; ++ ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_dev *dev; ++ ++ struct yaffs_obj *parent = yaffs_inode_to_obj(dir); ++ ++ int error = -ENOSPC; ++ uid_t uid = YCRED(current)->fsuid; ++ gid_t gid = ++ (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; ++ ++ if ((dir->i_mode & S_ISGID) && S_ISDIR(mode)) ++ mode |= S_ISGID; ++ ++ if (parent) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: parent object %d type %d", ++ parent->obj_id, parent->variant_type); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: could not get parent object"); ++ return -EPERM; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod: making oject for %s, mode %x dev %x", ++ dentry->d_name.name, mode, rdev); ++ ++ dev = parent->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ switch (mode & S_IFMT) { ++ default: ++ /* Special (socket, fifo, device...) */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special"); ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ obj = ++ yaffs_create_special(parent, dentry->d_name.name, mode, uid, ++ gid, old_encode_dev(rdev)); ++#else ++ obj = ++ yaffs_create_special(parent, dentry->d_name.name, mode, uid, ++ gid, rdev); ++#endif ++ break; ++ case S_IFREG: /* file */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file"); ++ obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid, ++ gid); ++ break; ++ case S_IFDIR: /* directory */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory"); ++ obj = yaffs_create_dir(parent, dentry->d_name.name, mode, ++ uid, gid); ++ break; ++ case S_IFLNK: /* symlink */ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink"); ++ obj = NULL; /* Do we ever get here? */ ++ break; ++ } ++ ++ /* Can not call yaffs_get_inode() with gross lock held */ ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); ++ d_instantiate(dentry, inode); ++ update_dir_time(dir); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_mknod created object %d count = %d", ++ obj->obj_id, atomic_read(&inode->i_count)); ++ error = 0; ++ yaffs_fill_inode_from_obj(dir, parent); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object"); ++ error = -ENOMEM; ++ } ++ ++ return error; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++#else ++static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++#endif ++{ ++ int ret_val; ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir"); ++ ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); ++ return ret_val; ++} ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool dummy) ++#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ struct nameidata *n) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, ++ struct nameidata *n) ++#else ++static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) ++#endif ++{ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_create"); ++ return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, ++ unsigned int dummy) ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *n) ++#else ++static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) ++#endif ++{ ++ struct yaffs_obj *obj; ++ struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */ ++ ++ struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev; ++ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_lock(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s", ++ yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name); ++ ++ obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name); ++ ++ obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */ ++ ++ /* Can't hold gross lock when calling yaffs_get_inode() */ ++ if (current != yaffs_dev_to_lc(dev)->readdir_process) ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_lookup found %d", obj->obj_id); ++ ++ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found"); ++ ++ } ++ ++/* added NCB for 2.5/6 compatability - forces add even if inode is ++ * NULL which creates dentry hash */ ++ d_add(dentry, inode); ++ ++ return NULL; ++} ++ ++/* ++ * Create a link... ++ */ ++static int yaffs_link(struct dentry *old_dentry, struct inode *dir, ++ struct dentry *dentry) ++{ ++ struct inode *inode = old_dentry->d_inode; ++ struct yaffs_obj *obj = NULL; ++ struct yaffs_obj *link = NULL; ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_link"); ++ ++ obj = yaffs_inode_to_obj(inode); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ ++ link = ++ yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name, ++ obj); ++ ++ if (link) { ++ set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj)); ++ d_instantiate(dentry, old_dentry->d_inode); ++ atomic_inc(&old_dentry->d_inode->i_count); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_link link count %d i_count %d", ++ old_dentry->d_inode->i_nlink, ++ atomic_read(&old_dentry->d_inode->i_count)); ++ } ++ ++ yaffs_gross_unlock(dev); ++ ++ if (link) { ++ update_dir_time(dir); ++ return 0; ++ } ++ ++ return -EPERM; ++} ++ ++static int yaffs_symlink(struct inode *dir, struct dentry *dentry, ++ const char *symname) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ uid_t uid = YCRED(current)->fsuid; ++ gid_t gid = ++ (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink"); ++ ++ if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) > ++ YAFFS_MAX_NAME_LENGTH) ++ return -ENAMETOOLONG; ++ ++ if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) > ++ YAFFS_MAX_ALIAS_LENGTH) ++ return -ENAMETOOLONG; ++ ++ dev = yaffs_inode_to_obj(dir)->my_dev; ++ yaffs_gross_lock(dev); ++ obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name, ++ S_IFLNK | S_IRWXUGO, uid, gid, symname); ++ yaffs_gross_unlock(dev); ++ ++ if (obj) { ++ struct inode *inode; ++ ++ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); ++ d_instantiate(dentry, inode); ++ update_dir_time(dir); ++ yaffs_trace(YAFFS_TRACE_OS, "symlink created OK"); ++ return 0; ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, "symlink not created"); ++ } ++ ++ return -ENOMEM; ++} ++ ++/* ++ * The VFS layer already does all the dentry stuff for rename. ++ * ++ * NB: POSIX says you can rename an object over an old object of the same name ++ */ ++static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, ++ struct inode *new_dir, struct dentry *new_dentry) ++{ ++ struct yaffs_dev *dev; ++ int ret_val = YAFFS_FAIL; ++ struct yaffs_obj *target; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename"); ++ dev = yaffs_inode_to_obj(old_dir)->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ /* Check if the target is an existing directory that is not empty. */ ++ target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir), ++ new_dentry->d_name.name); ++ ++ if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY && ++ !list_empty(&target->variant.dir_variant.children)) { ++ ++ yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir"); ++ ++ ret_val = YAFFS_FAIL; ++ } else { ++ /* Now does unlinking internally using shadowing mechanism */ ++ yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj"); ++ ++ ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir), ++ old_dentry->d_name.name, ++ yaffs_inode_to_obj(new_dir), ++ new_dentry->d_name.name); ++ } ++ yaffs_gross_unlock(dev); ++ ++ if (ret_val == YAFFS_OK) { ++ if (target) ++ inode_dec_link_count(new_dentry->d_inode); ++ ++ update_dir_time(old_dir); ++ if (old_dir != new_dir) ++ update_dir_time(new_dir); ++ return 0; ++ } else { ++ return -ENOTEMPTY; ++ } ++} ++ ++ ++ ++ ++static int yaffs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ int ret_val; ++ ++ struct yaffs_dev *dev; ++ struct yaffs_obj *obj; ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s", ++ (int)(dir->i_ino), dentry->d_name.name); ++ obj = yaffs_inode_to_obj(dir); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ ret_val = yaffs_unlinker(obj, dentry->d_name.name); ++ ++ if (ret_val == YAFFS_OK) { ++ inode_dec_link_count(dentry->d_inode); ++ dir->i_version++; ++ yaffs_gross_unlock(dev); ++ update_dir_time(dir); ++ return 0; ++ } ++ yaffs_gross_unlock(dev); ++ return -ENOTEMPTY; ++} ++ ++ ++ ++static const struct inode_operations yaffs_dir_inode_operations = { ++ .create = yaffs_create, ++ .lookup = yaffs_lookup, ++ .link = yaffs_link, ++ .unlink = yaffs_unlink, ++ .symlink = yaffs_symlink, ++ .mkdir = yaffs_mkdir, ++ .rmdir = yaffs_unlink, ++ .mknod = yaffs_mknod, ++ .rename = yaffs_rename, ++ .setattr = yaffs_setattr, ++ .setxattr = yaffs_setxattr, ++ .getxattr = yaffs_getxattr, ++ .listxattr = yaffs_listxattr, ++ .removexattr = yaffs_removexattr, ++}; ++ ++/*-----------------------------------------------------------------*/ ++/* Directory search context allows us to unlock access to yaffs during ++ * filldir without causing problems with the directory being modified. ++ * This is similar to the tried and tested mechanism used in yaffs direct. ++ * ++ * A search context iterates along a doubly linked list of siblings in the ++ * directory. If the iterating object is deleted then this would corrupt ++ * the list iteration, likely causing a crash. The search context avoids ++ * this by using the remove_obj_fn to move the search context to the ++ * next object before the object is deleted. ++ * ++ * Many readdirs (and thus seach conexts) may be alive simulateously so ++ * each struct yaffs_dev has a list of these. ++ * ++ * A seach context lives for the duration of a readdir. ++ * ++ * All these functions must be called while yaffs is locked. ++ */ ++ ++struct yaffs_search_context { ++ struct yaffs_dev *dev; ++ struct yaffs_obj *dir_obj; ++ struct yaffs_obj *next_return; ++ struct list_head others; ++}; ++ ++/* ++ * yaffs_new_search() creates a new search context, initialises it and ++ * adds it to the device's search context list. ++ * ++ * Called at start of readdir. ++ */ ++static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir) ++{ ++ struct yaffs_dev *dev = dir->my_dev; ++ struct yaffs_search_context *sc = ++ kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS); ++ if (sc) { ++ sc->dir_obj = dir; ++ sc->dev = dev; ++ if (list_empty(&sc->dir_obj->variant.dir_variant.children)) ++ sc->next_return = NULL; ++ else ++ sc->next_return = ++ list_entry(dir->variant.dir_variant.children.next, ++ struct yaffs_obj, siblings); ++ INIT_LIST_HEAD(&sc->others); ++ list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts)); ++ } ++ return sc; ++} ++ ++/* ++ * yaffs_search_end() disposes of a search context and cleans up. ++ */ ++static void yaffs_search_end(struct yaffs_search_context *sc) ++{ ++ if (sc) { ++ list_del(&sc->others); ++ kfree(sc); ++ } ++} ++ ++/* ++ * yaffs_search_advance() moves a search context to the next object. ++ * Called when the search iterates or when an object removal causes ++ * the search context to be moved to the next object. ++ */ ++static void yaffs_search_advance(struct yaffs_search_context *sc) ++{ ++ if (!sc) ++ return; ++ ++ if (sc->next_return == NULL || ++ list_empty(&sc->dir_obj->variant.dir_variant.children)) ++ sc->next_return = NULL; ++ else { ++ struct list_head *next = sc->next_return->siblings.next; ++ ++ if (next == &sc->dir_obj->variant.dir_variant.children) ++ sc->next_return = NULL; /* end of list */ ++ else ++ sc->next_return = ++ list_entry(next, struct yaffs_obj, siblings); ++ } ++} ++ ++/* ++ * yaffs_remove_obj_callback() is called when an object is unlinked. ++ * We check open search contexts and advance any which are currently ++ * on the object being iterated. ++ */ ++static void yaffs_remove_obj_callback(struct yaffs_obj *obj) ++{ ++ ++ struct list_head *i; ++ struct yaffs_search_context *sc; ++ struct list_head *search_contexts = ++ &(yaffs_dev_to_lc(obj->my_dev)->search_contexts); ++ ++ /* Iterate through the directory search contexts. ++ * If any are currently on the object being removed, then advance ++ * the search context to the next object to prevent a hanging pointer. ++ */ ++ list_for_each(i, search_contexts) { ++ sc = list_entry(i, struct yaffs_search_context, others); ++ if (sc->next_return == obj) ++ yaffs_search_advance(sc); ++ } ++ ++} ++ ++ ++/*-----------------------------------------------------------------*/ ++ ++static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ struct yaffs_search_context *sc; ++ struct inode *inode = f->f_dentry->d_inode; ++ unsigned long offset, curoffs; ++ struct yaffs_obj *l; ++ int ret_val = 0; ++ ++ char name[YAFFS_MAX_NAME_LENGTH + 1]; ++ ++ obj = yaffs_dentry_to_obj(f->f_dentry); ++ dev = obj->my_dev; ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_dev_to_lc(dev)->readdir_process = current; ++ ++ offset = f->f_pos; ++ ++ sc = yaffs_new_search(obj); ++ if (!sc) { ++ ret_val = -ENOMEM; ++ goto out; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: starting at %d", (int)offset); ++ ++ if (offset == 0) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: entry . ino %d", ++ (int)inode->i_ino); ++ yaffs_gross_unlock(dev); ++ if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ yaffs_gross_lock(dev); ++ offset++; ++ f->f_pos++; ++ } ++ if (offset == 1) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: entry .. ino %d", ++ (int)f->f_dentry->d_parent->d_inode->i_ino); ++ yaffs_gross_unlock(dev); ++ if (filldir(dirent, "..", 2, offset, ++ f->f_dentry->d_parent->d_inode->i_ino, ++ DT_DIR) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ yaffs_gross_lock(dev); ++ offset++; ++ f->f_pos++; ++ } ++ ++ curoffs = 1; ++ ++ /* If the directory has changed since the open or last call to ++ readdir, rewind to after the 2 canned entries. */ ++ if (f->f_version != inode->i_version) { ++ offset = 2; ++ f->f_pos = offset; ++ f->f_version = inode->i_version; ++ } ++ ++ while (sc->next_return) { ++ curoffs++; ++ l = sc->next_return; ++ if (curoffs >= offset) { ++ int this_inode = yaffs_get_obj_inode(l); ++ int this_type = yaffs_get_obj_type(l); ++ ++ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_readdir: %s inode %d", ++ name, yaffs_get_obj_inode(l)); ++ ++ yaffs_gross_unlock(dev); ++ ++ if (filldir(dirent, ++ name, ++ strlen(name), ++ offset, this_inode, this_type) < 0) { ++ yaffs_gross_lock(dev); ++ goto out; ++ } ++ ++ yaffs_gross_lock(dev); ++ ++ offset++; ++ f->f_pos++; ++ } ++ yaffs_search_advance(sc); ++ } ++ ++out: ++ yaffs_search_end(sc); ++ yaffs_dev_to_lc(dev)->readdir_process = NULL; ++ yaffs_gross_unlock(dev); ++ ++ return ret_val; ++} ++ ++static const struct file_operations yaffs_dir_operations = { ++ .read = generic_read_dir, ++ .readdir = yaffs_readdir, ++ .fsync = yaffs_sync_object, ++ .llseek = generic_file_llseek, ++}; ++ ++static void yaffs_fill_inode_from_obj(struct inode *inode, ++ struct yaffs_obj *obj) ++{ ++ if (inode && obj) { ++ ++ /* Check mode against the variant type and attempt to repair if broken. */ ++ u32 mode = obj->yst_mode; ++ switch (obj->variant_type) { ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (!S_ISREG(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFREG; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ if (!S_ISLNK(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFLNK; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ if (!S_ISDIR(mode)) { ++ obj->yst_mode &= ~S_IFMT; ++ obj->yst_mode |= S_IFDIR; ++ } ++ ++ break; ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ default: ++ /* TODO? */ ++ break; ++ } ++ ++ inode->i_flags |= S_NOATIME; ++ ++ inode->i_ino = obj->obj_id; ++ inode->i_mode = obj->yst_mode; ++ inode->i_uid = obj->yst_uid; ++ inode->i_gid = obj->yst_gid; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++ inode->i_blksize = inode->i_sb->s_blocksize; ++#endif ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ ++ inode->i_rdev = old_decode_dev(obj->yst_rdev); ++ inode->i_atime.tv_sec = (time_t) (obj->yst_atime); ++ inode->i_atime.tv_nsec = 0; ++ inode->i_mtime.tv_sec = (time_t) obj->yst_mtime; ++ inode->i_mtime.tv_nsec = 0; ++ inode->i_ctime.tv_sec = (time_t) obj->yst_ctime; ++ inode->i_ctime.tv_nsec = 0; ++#else ++ inode->i_rdev = obj->yst_rdev; ++ inode->i_atime = obj->yst_atime; ++ inode->i_mtime = obj->yst_mtime; ++ inode->i_ctime = obj->yst_ctime; ++#endif ++ inode->i_size = yaffs_get_obj_length(obj); ++ inode->i_blocks = (inode->i_size + 511) >> 9; ++ ++ set_nlink(inode, yaffs_get_obj_link_count(obj)); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d", ++ inode->i_mode, inode->i_uid, inode->i_gid, ++ inode->i_size, atomic_read(&inode->i_count)); ++ ++ switch (obj->yst_mode & S_IFMT) { ++ default: /* fifo, device or socket */ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ init_special_inode(inode, obj->yst_mode, ++ old_decode_dev(obj->yst_rdev)); ++#else ++ init_special_inode(inode, obj->yst_mode, ++ (dev_t) (obj->yst_rdev)); ++#endif ++ break; ++ case S_IFREG: /* file */ ++ inode->i_op = &yaffs_file_inode_operations; ++ inode->i_fop = &yaffs_file_operations; ++ inode->i_mapping->a_ops = ++ &yaffs_file_address_operations; ++ break; ++ case S_IFDIR: /* directory */ ++ inode->i_op = &yaffs_dir_inode_operations; ++ inode->i_fop = &yaffs_dir_operations; ++ break; ++ case S_IFLNK: /* symlink */ ++ inode->i_op = &yaffs_symlink_inode_operations; ++ break; ++ } ++ ++ yaffs_inode_to_obj_lv(inode) = obj; ++ ++ obj->my_inode = inode; ++ ++ } else { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_fill_inode invalid parameters"); ++ } ++ ++} ++ ++ ++ ++/* ++ * yaffs background thread functions . ++ * yaffs_bg_thread_fn() the thread function ++ * yaffs_bg_start() launches the background thread. ++ * yaffs_bg_stop() cleans up the background thread. ++ * ++ * NB: ++ * The thread should only run after the yaffs is initialised ++ * The thread should be stopped before yaffs is unmounted. ++ * The thread should not do any writing while the fs is in read only. ++ */ ++ ++static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev) ++{ ++ unsigned erased_chunks = ++ dev->n_erased_blocks * dev->param.chunks_per_block; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ unsigned scattered = 0; /* Free chunks not in an erased block */ ++ ++ if (erased_chunks < dev->n_free_chunks) ++ scattered = (dev->n_free_chunks - erased_chunks); ++ ++ if (!context->bg_running) ++ return 0; ++ else if (scattered < (dev->param.chunks_per_block * 2)) ++ return 0; ++ else if (erased_chunks > dev->n_free_chunks / 2) ++ return 0; ++ else if (erased_chunks > dev->n_free_chunks / 4) ++ return 1; ++ else ++ return 2; ++} ++ ++#ifdef YAFFS_COMPILE_BACKGROUND ++ ++void yaffs_background_waker(unsigned long data) ++{ ++ wake_up_process((struct task_struct *)data); ++} ++ ++static int yaffs_bg_thread_fn(void *data) ++{ ++ struct yaffs_dev *dev = (struct yaffs_dev *)data; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ unsigned long now = jiffies; ++ unsigned long next_dir_update = now; ++ unsigned long next_gc = now; ++ unsigned long expires; ++ unsigned int urgency; ++ ++ int gc_result; ++ struct timer_list timer; ++ ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, ++ "yaffs_background starting for dev %p", (void *)dev); ++ ++#ifdef YAFFS_COMPILE_FREEZER ++ set_freezable(); ++#endif ++ while (context->bg_running) { ++ yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background"); ++ ++ if (kthread_should_stop()) ++ break; ++ ++#ifdef YAFFS_COMPILE_FREEZER ++ if (try_to_freeze()) ++ continue; ++#endif ++ yaffs_gross_lock(dev); ++ ++ now = jiffies; ++ ++ if (time_after(now, next_dir_update) && yaffs_bg_enable) { ++ yaffs_update_dirty_dirs(dev); ++ next_dir_update = now + HZ; ++ } ++ ++ if (time_after(now, next_gc) && yaffs_bg_enable) { ++ if (!dev->is_checkpointed) { ++ urgency = yaffs_bg_gc_urgency(dev); ++ gc_result = yaffs_bg_gc(dev, urgency); ++ if (urgency > 1) ++ next_gc = now + HZ / 20 + 1; ++ else if (urgency > 0) ++ next_gc = now + HZ / 10 + 1; ++ else ++ next_gc = now + HZ * 2; ++ } else { ++ /* ++ * gc not running so set to next_dir_update ++ * to cut down on wake ups ++ */ ++ next_gc = next_dir_update; ++ } ++ } ++ yaffs_gross_unlock(dev); ++#if 1 ++ expires = next_dir_update; ++ if (time_before(next_gc, expires)) ++ expires = next_gc; ++ if (time_before(expires, now)) ++ expires = now + HZ; ++ ++ Y_INIT_TIMER(&timer); ++ timer.expires = expires + 1; ++ timer.data = (unsigned long)current; ++ timer.function = yaffs_background_waker; ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_timer(&timer); ++ schedule(); ++ del_timer_sync(&timer); ++#else ++ msleep(10); ++#endif ++ } ++ ++ return 0; ++} ++ ++static int yaffs_bg_start(struct yaffs_dev *dev) ++{ ++ int retval = 0; ++ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev); ++ ++ if (dev->read_only) ++ return -1; ++ ++ context->bg_running = 1; ++ ++ context->bg_thread = kthread_run(yaffs_bg_thread_fn, ++ (void *)dev, "yaffs-bg-%d", ++ context->mount_id); ++ ++ if (IS_ERR(context->bg_thread)) { ++ retval = PTR_ERR(context->bg_thread); ++ context->bg_thread = NULL; ++ context->bg_running = 0; ++ } ++ return retval; ++} ++ ++static void yaffs_bg_stop(struct yaffs_dev *dev) ++{ ++ struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev); ++ ++ ctxt->bg_running = 0; ++ ++ if (ctxt->bg_thread) { ++ kthread_stop(ctxt->bg_thread); ++ ctxt->bg_thread = NULL; ++ } ++} ++#else ++static int yaffs_bg_thread_fn(void *data) ++{ ++ return 0; ++} ++ ++static int yaffs_bg_start(struct yaffs_dev *dev) ++{ ++ return 0; ++} ++ ++static void yaffs_bg_stop(struct yaffs_dev *dev) ++{ ++} ++#endif ++ ++ ++static void yaffs_flush_inodes(struct super_block *sb) ++{ ++ struct inode *iptr; ++ struct yaffs_obj *obj; ++ ++ list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) { ++ obj = yaffs_inode_to_obj(iptr); ++ if (obj) { ++ yaffs_trace(YAFFS_TRACE_OS, ++ "flushing obj %d", ++ obj->obj_id); ++ yaffs_flush_file(obj, 1, 0); ++ } ++ } ++} ++ ++static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ if (!dev) ++ return; ++ ++ yaffs_flush_inodes(sb); ++ yaffs_update_dirty_dirs(dev); ++ yaffs_flush_whole_cache(dev); ++ if (do_checkpoint) ++ yaffs_checkpoint_save(dev); ++} ++ ++static LIST_HEAD(yaffs_context_list); ++struct mutex yaffs_context_lock; ++ ++static void yaffs_put_super(struct super_block *sb) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ struct mtd_info *mtd = yaffs_dev_to_mtd(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, ++ "yaffs_put_super"); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND, ++ "Shutting down yaffs background thread"); ++ yaffs_bg_stop(dev); ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND, ++ "yaffs background thread shut down"); ++ ++ yaffs_gross_lock(dev); ++ ++ yaffs_flush_super(sb, 1); ++ ++ yaffs_deinitialise(dev); ++ ++ yaffs_gross_unlock(dev); ++ ++ mutex_lock(&yaffs_context_lock); ++ list_del_init(&(yaffs_dev_to_lc(dev)->context_list)); ++ mutex_unlock(&yaffs_context_lock); ++ ++ if (yaffs_dev_to_lc(dev)->spare_buffer) { ++ kfree(yaffs_dev_to_lc(dev)->spare_buffer); ++ yaffs_dev_to_lc(dev)->spare_buffer = NULL; ++ } ++ ++ kfree(dev); ++ ++ yaffs_put_mtd_device(mtd); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, ++ "yaffs_put_super done"); ++} ++ ++ ++static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev) ++{ ++ return yaffs_gc_control; ++} ++ ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++ ++static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino, ++ uint32_t generation) ++{ ++ return Y_IGET(sb, ino); ++} ++ ++static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb, ++ struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ++ yaffs2_nfs_get_inode); ++} ++ ++static struct dentry *yaffs2_fh_to_parent(struct super_block *sb, ++ struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ return generic_fh_to_parent(sb, fid, fh_len, fh_type, ++ yaffs2_nfs_get_inode); ++} ++ ++struct dentry *yaffs2_get_parent(struct dentry *dentry) ++{ ++ ++ struct super_block *sb = dentry->d_inode->i_sb; ++ struct dentry *parent = ERR_PTR(-ENOENT); ++ struct inode *inode; ++ unsigned long parent_ino; ++ struct yaffs_obj *d_obj; ++ struct yaffs_obj *parent_obj; ++ ++ d_obj = yaffs_inode_to_obj(dentry->d_inode); ++ ++ if (d_obj) { ++ parent_obj = d_obj->parent; ++ if (parent_obj) { ++ parent_ino = yaffs_get_obj_inode(parent_obj); ++ inode = Y_IGET(sb, parent_ino); ++ ++ if (IS_ERR(inode)) { ++ parent = ERR_CAST(inode); ++ } else { ++ parent = d_obtain_alias(inode); ++ if (!IS_ERR(parent)) { ++ parent = ERR_PTR(-ENOMEM); ++ iput(inode); ++ } ++ } ++ } ++ } ++ ++ return parent; ++} ++ ++/* Just declare a zero structure as a NULL value implies ++ * using the default functions of exportfs. ++ */ ++ ++static struct export_operations yaffs_export_ops = { ++ .fh_to_dentry = yaffs2_fh_to_dentry, ++ .fh_to_parent = yaffs2_fh_to_parent, ++ .get_parent = yaffs2_get_parent, ++}; ++ ++#endif ++ ++static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj) ++{ ++ /* Clear the association between the inode and ++ * the struct yaffs_obj. ++ */ ++ obj->my_inode = NULL; ++ yaffs_inode_to_obj_lv(inode) = NULL; ++ ++ /* If the object freeing was deferred, then the real ++ * free happens now. ++ * This should fix the inode inconsistency problem. ++ */ ++ yaffs_handle_defered_free(obj); ++} ++ ++#ifdef YAFFS_HAS_EVICT_INODE ++/* yaffs_evict_inode combines into one operation what was previously done in ++ * yaffs_clear_inode() and yaffs_delete_inode() ++ * ++ */ ++static void yaffs_evict_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ int deleteme = 0; ++ ++ obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_evict_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (!inode->i_nlink && !is_bad_inode(inode)) ++ deleteme = 1; ++ truncate_inode_pages(&inode->i_data, 0); ++ Y_CLEAR_INODE(inode); ++ ++ if (deleteme && obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_del_obj(obj); ++ yaffs_gross_unlock(dev); ++ } ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_unstitch_obj(inode, obj); ++ yaffs_gross_unlock(dev); ++ } ++} ++#else ++ ++/* clear is called to tell the fs to release any per-inode data it holds. ++ * The object might still exist on disk and is just being thrown out of the cache ++ * or else the object has actually been deleted and we're being called via ++ * the chain ++ * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode() ++ */ ++ ++static void yaffs_clear_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_dev *dev; ++ ++ obj = yaffs_inode_to_obj(inode); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_clear_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_unstitch_obj(inode, obj); ++ yaffs_gross_unlock(dev); ++ } ++ ++} ++ ++/* delete is called when the link count is zero and the inode ++ * is put (ie. nobody wants to know about it anymore, time to ++ * delete the file). ++ * NB Must call clear_inode() ++ */ ++static void yaffs_delete_inode(struct inode *inode) ++{ ++ struct yaffs_obj *obj = yaffs_inode_to_obj(inode); ++ struct yaffs_dev *dev; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_delete_inode: ino %d, count %d %s", ++ (int)inode->i_ino, atomic_read(&inode->i_count), ++ obj ? "object exists" : "null object"); ++ ++ if (obj) { ++ dev = obj->my_dev; ++ yaffs_gross_lock(dev); ++ yaffs_del_obj(obj); ++ yaffs_gross_unlock(dev); ++ } ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) ++ truncate_inode_pages(&inode->i_data, 0); ++#endif ++ clear_inode(inode); ++} ++#endif ++ ++ ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; ++ struct super_block *sb = dentry->d_sb; ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++#else ++static int yaffs_statfs(struct super_block *sb, struct statfs *buf) ++{ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++#endif ++ ++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs"); ++ ++ yaffs_gross_lock(dev); ++ ++ buf->f_type = YAFFS_MAGIC; ++ buf->f_bsize = sb->s_blocksize; ++ buf->f_namelen = 255; ++ ++ if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) { ++ /* Do this if chunk size is not a power of 2 */ ++ ++ uint64_t bytes_in_dev; ++ uint64_t bytes_free; ++ ++ bytes_in_dev = ++ ((uint64_t) ++ ((dev->param.end_block - dev->param.start_block + ++ 1))) * ((uint64_t) (dev->param.chunks_per_block * ++ dev->data_bytes_per_chunk)); ++ ++ do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */ ++ buf->f_blocks = bytes_in_dev; ++ ++ bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) * ++ ((uint64_t) (dev->data_bytes_per_chunk)); ++ ++ do_div(bytes_free, sb->s_blocksize); ++ ++ buf->f_bfree = bytes_free; ++ ++ } else if (sb->s_blocksize > dev->data_bytes_per_chunk) { ++ ++ buf->f_blocks = ++ (dev->param.end_block - dev->param.start_block + 1) * ++ dev->param.chunks_per_block / ++ (sb->s_blocksize / dev->data_bytes_per_chunk); ++ buf->f_bfree = ++ yaffs_get_n_free_chunks(dev) / ++ (sb->s_blocksize / dev->data_bytes_per_chunk); ++ } else { ++ buf->f_blocks = ++ (dev->param.end_block - dev->param.start_block + 1) * ++ dev->param.chunks_per_block * ++ (dev->data_bytes_per_chunk / sb->s_blocksize); ++ ++ buf->f_bfree = ++ yaffs_get_n_free_chunks(dev) * ++ (dev->data_bytes_per_chunk / sb->s_blocksize); ++ } ++ ++ buf->f_files = 0; ++ buf->f_ffree = 0; ++ buf->f_bavail = buf->f_bfree; ++ ++ yaffs_gross_unlock(dev); ++ return 0; ++} ++ ++ ++ ++static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint) ++{ ++ ++ struct yaffs_dev *dev = yaffs_super_to_dev(sb); ++ unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4); ++ unsigned gc_urgent = yaffs_bg_gc_urgency(dev); ++ int do_checkpoint; ++ int dirty = yaffs_check_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND, ++ "yaffs_do_sync_fs: gc-urgency %d %s %s%s", ++ gc_urgent, ++ dirty ? "dirty" : "clean", ++ request_checkpoint ? "checkpoint requested" : "no checkpoint", ++ oneshot_checkpoint ? " one-shot" : ""); ++ ++ yaffs_gross_lock(dev); ++ do_checkpoint = ((request_checkpoint && !gc_urgent) || ++ oneshot_checkpoint) && !dev->is_checkpointed; ++ ++ if (dirty || do_checkpoint) { ++ yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint); ++ yaffs_clear_super_dirty(dev); ++ if (oneshot_checkpoint) ++ yaffs_auto_checkpoint &= ~4; ++ } ++ yaffs_gross_unlock(dev); ++ ++ return 0; ++} ++ ++ ++#ifdef YAFFS_HAS_WRITE_SUPER ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static void yaffs_write_super(struct super_block *sb) ++#else ++static int yaffs_write_super(struct super_block *sb) ++#endif ++{ ++ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND, ++ "yaffs_write_super %s", ++ request_checkpoint ? " checkpt" : ""); ++ ++ yaffs_do_sync_fs(sb, request_checkpoint); ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) ++ return 0; ++#endif ++} ++#endif ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_sync_fs(struct super_block *sb, int wait) ++#else ++static int yaffs_sync_fs(struct super_block *sb) ++#endif ++{ ++ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1); ++ ++ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, ++ "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : ""); ++ ++ yaffs_do_sync_fs(sb, request_checkpoint); ++ ++ return 0; ++} ++ ++ ++ ++static const struct super_operations yaffs_super_ops = { ++ .statfs = yaffs_statfs, ++ ++#ifndef YAFFS_USE_OWN_IGET ++ .read_inode = yaffs_read_inode, ++#endif ++#ifdef YAFFS_HAS_PUT_INODE ++ .put_inode = yaffs_put_inode, ++#endif ++ .put_super = yaffs_put_super, ++#ifdef YAFFS_HAS_EVICT_INODE ++ .evict_inode = yaffs_evict_inode, ++#else ++ .delete_inode = yaffs_delete_inode, ++ .clear_inode = yaffs_clear_inode, ++#endif ++ .sync_fs = yaffs_sync_fs, ++#ifdef YAFFS_HAS_WRITE_SUPER ++ .write_super = yaffs_write_super, ++#endif ++}; ++ ++struct yaffs_options { ++ int inband_tags; ++ int skip_checkpoint_read; ++ int skip_checkpoint_write; ++ int no_cache; ++ int tags_ecc_on; ++ int tags_ecc_overridden; ++ int lazy_loading_enabled; ++ int lazy_loading_overridden; ++ int empty_lost_and_found; ++ int empty_lost_and_found_overridden; ++ int disable_summary; ++}; ++ ++#define MAX_OPT_LEN 30 ++static int yaffs_parse_options(struct yaffs_options *options, ++ const char *options_str) ++{ ++ char cur_opt[MAX_OPT_LEN + 1]; ++ int p; ++ int error = 0; ++ ++ /* Parse through the options which is a comma seperated list */ ++ ++ while (options_str && *options_str && !error) { ++ memset(cur_opt, 0, MAX_OPT_LEN + 1); ++ p = 0; ++ ++ while (*options_str == ',') ++ options_str++; ++ ++ while (*options_str && *options_str != ',') { ++ if (p < MAX_OPT_LEN) { ++ cur_opt[p] = *options_str; ++ p++; ++ } ++ options_str++; ++ } ++ ++ if (!strcmp(cur_opt, "inband-tags")) { ++ options->inband_tags = 1; ++ } else if (!strcmp(cur_opt, "tags-ecc-off")) { ++ options->tags_ecc_on = 0; ++ options->tags_ecc_overridden = 1; ++ } else if (!strcmp(cur_opt, "tags-ecc-on")) { ++ options->tags_ecc_on = 1; ++ options->tags_ecc_overridden = 1; ++ } else if (!strcmp(cur_opt, "lazy-loading-off")) { ++ options->lazy_loading_enabled = 0; ++ options->lazy_loading_overridden = 1; ++ } else if (!strcmp(cur_opt, "lazy-loading-on")) { ++ options->lazy_loading_enabled = 1; ++ options->lazy_loading_overridden = 1; ++ } else if (!strcmp(cur_opt, "disable-summary")) { ++ options->disable_summary = 1; ++ } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) { ++ options->empty_lost_and_found = 0; ++ options->empty_lost_and_found_overridden = 1; ++ } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) { ++ options->empty_lost_and_found = 1; ++ options->empty_lost_and_found_overridden = 1; ++ } else if (!strcmp(cur_opt, "no-cache")) { ++ options->no_cache = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint-read")) { ++ options->skip_checkpoint_read = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint-write")) { ++ options->skip_checkpoint_write = 1; ++ } else if (!strcmp(cur_opt, "no-checkpoint")) { ++ options->skip_checkpoint_read = 1; ++ options->skip_checkpoint_write = 1; ++ } else { ++ printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n", ++ cur_opt); ++ error = 1; ++ } ++ } ++ ++ return error; ++} ++ ++ ++static struct dentry *yaffs_make_root(struct inode *inode) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++ struct dentry *root = d_alloc_root(inode); ++ ++ if (!root) ++ iput(inode); ++ ++ return root; ++#else ++ return d_make_root(inode); ++#endif ++} ++ ++ ++ ++ ++static struct super_block *yaffs_internal_read_super(int yaffs_version, ++ struct super_block *sb, ++ void *data, int silent) ++{ ++ int n_blocks; ++ struct inode *inode = NULL; ++ struct dentry *root; ++ struct yaffs_dev *dev = 0; ++ char devname_buf[BDEVNAME_SIZE + 1]; ++ struct mtd_info *mtd; ++ int err; ++ char *data_str = (char *)data; ++ struct yaffs_linux_context *context = NULL; ++ struct yaffs_param *param; ++ ++ int read_only = 0; ++ ++ struct yaffs_options options; ++ ++ unsigned mount_id; ++ int found; ++ struct yaffs_linux_context *context_iterator; ++ struct list_head *l; ++ ++ if (!sb) { ++ printk(KERN_INFO "yaffs: sb is NULL\n"); ++ return NULL; ++ } ++ ++ sb->s_magic = YAFFS_MAGIC; ++ sb->s_op = &yaffs_super_ops; ++ sb->s_flags |= MS_NOATIME; ++ ++ read_only = ((sb->s_flags & MS_RDONLY) != 0); ++ ++#ifdef YAFFS_COMPILE_EXPORTFS ++ sb->s_export_op = &yaffs_export_ops; ++#endif ++ ++ if (!sb->s_dev) ++ printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); ++ else if (!yaffs_devname(sb, devname_buf)) ++ printk(KERN_INFO "yaffs: devname is NULL\n"); ++ else ++ printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n", ++ sb->s_dev, ++ yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw"); ++ ++ if (!data_str) ++ data_str = ""; ++ ++ printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str); ++ ++ memset(&options, 0, sizeof(options)); ++ ++ if (yaffs_parse_options(&options, data_str)) { ++ /* Option parsing failed */ ++ return NULL; ++ } ++ ++ sb->s_blocksize = PAGE_CACHE_SIZE; ++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT; ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: Using yaffs%d", yaffs_version); ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: block size %d", (int)(sb->s_blocksize)); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: Attempting MTD mount of %u.%u,\"%s\"", ++ MAJOR(sb->s_dev), MINOR(sb->s_dev), ++ yaffs_devname(sb, devname_buf)); ++ ++ /* Get the device */ ++ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); ++ if (!mtd) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs: MTD device %u either not valid or unavailable", ++ MINOR(sb->s_dev)); ++ return NULL; ++ } ++ ++ if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2"); ++ yaffs_version = 2; ++ } ++ ++ /* Added NCB 26/5/2006 for completeness */ ++ if (yaffs_version == 2 && !options.inband_tags ++ && WRITE_SIZE(mtd) == 512) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1"); ++ yaffs_version = 1; ++ } ++ ++ if(yaffs_verify_mtd(mtd, yaffs_version, options.inband_tags) < 0) ++ return NULL; ++ ++ /* OK, so if we got here, we have an MTD that's NAND and looks ++ * like it has the right capabilities ++ * Set the struct yaffs_dev up for mtd ++ */ ++ ++ if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { ++ read_only = 1; ++ printk(KERN_INFO ++ "yaffs: mtd is read only, setting superblock read only\n" ++ ); ++ sb->s_flags |= MS_RDONLY; ++ } ++ ++ dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL); ++ context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL); ++ ++ if (!dev || !context) { ++ if (dev) ++ kfree(dev); ++ if (context) ++ kfree(context); ++ dev = NULL; ++ context = NULL; ++ } ++ ++ if (!dev) { ++ /* Deep shit could not allocate device structure */ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs_read_super: Failed trying to allocate struct yaffs_dev." ++ ); ++ return NULL; ++ } ++ memset(dev, 0, sizeof(struct yaffs_dev)); ++ param = &(dev->param); ++ ++ memset(context, 0, sizeof(struct yaffs_linux_context)); ++ dev->os_context = context; ++ INIT_LIST_HEAD(&(context->context_list)); ++ context->dev = dev; ++ context->super = sb; ++ ++ dev->read_only = read_only; ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++ sb->s_fs_info = dev; ++#else ++ sb->u.generic_sbp = dev; ++#endif ++ ++ ++ dev->driver_context = mtd; ++ param->name = mtd->name; ++ ++ /* Set up the memory size parameters.... */ ++ ++ ++ param->n_reserved_blocks = 5; ++ param->n_caches = (options.no_cache) ? 0 : 10; ++ param->inband_tags = options.inband_tags; ++ ++ param->enable_xattr = 1; ++ if (options.lazy_loading_overridden) ++ param->disable_lazy_load = !options.lazy_loading_enabled; ++ ++ param->defered_dir_update = 1; ++ ++ if (options.tags_ecc_overridden) ++ param->no_tags_ecc = !options.tags_ecc_on; ++ ++ param->empty_lost_n_found = 1; ++ param->refresh_period = 500; ++ param->disable_summary = options.disable_summary; ++ ++ if (options.empty_lost_and_found_overridden) ++ param->empty_lost_n_found = options.empty_lost_and_found; ++ ++ /* ... and the functions. */ ++ if (yaffs_version == 2) { ++ param->is_yaffs2 = 1; ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++ param->total_bytes_per_chunk = mtd->writesize; ++ param->chunks_per_block = mtd->erasesize / mtd->writesize; ++#else ++ param->total_bytes_per_chunk = mtd->oobblock; ++ param->chunks_per_block = mtd->erasesize / mtd->oobblock; ++#endif ++ n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize); ++ ++ param->start_block = 0; ++ param->end_block = n_blocks - 1; ++ } else { ++ param->is_yaffs2 = 0; ++ n_blocks = YCALCBLOCKS(mtd->size, ++ YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); ++ ++ param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK; ++ param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK; ++ } ++ ++ param->start_block = 0; ++ param->end_block = n_blocks - 1; ++ ++ yaffs_mtd_drv_install(dev); ++ ++ param->sb_dirty_fn = yaffs_set_super_dirty; ++ param->gc_control_fn = yaffs_gc_control_callback; ++ ++ yaffs_dev_to_lc(dev)->super = sb; ++ ++ param->use_nand_ecc = 1; ++ ++ param->skip_checkpt_rd = options.skip_checkpoint_read; ++ param->skip_checkpt_wr = options.skip_checkpoint_write; ++ ++ mutex_lock(&yaffs_context_lock); ++ /* Get a mount id */ ++ found = 0; ++ for (mount_id = 0; !found; mount_id++) { ++ found = 1; ++ list_for_each(l, &yaffs_context_list) { ++ context_iterator = ++ list_entry(l, struct yaffs_linux_context, ++ context_list); ++ if (context_iterator->mount_id == mount_id) ++ found = 0; ++ } ++ } ++ context->mount_id = mount_id; ++ ++ list_add_tail(&(yaffs_dev_to_lc(dev)->context_list), ++ &yaffs_context_list); ++ mutex_unlock(&yaffs_context_lock); ++ ++ /* Directory search handling... */ ++ INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts)); ++ param->remove_obj_fn = yaffs_remove_obj_callback; ++ ++ mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock)); ++ ++ yaffs_gross_lock(dev); ++ ++ err = yaffs_guts_initialise(dev); ++ ++ yaffs_trace(YAFFS_TRACE_OS, ++ "yaffs_read_super: guts initialised %s", ++ (err == YAFFS_OK) ? "OK" : "FAILED"); ++ ++ if (err == YAFFS_OK) ++ yaffs_bg_start(dev); ++ ++ if (!context->bg_thread) ++ param->defered_dir_update = 0; ++ ++ sb->s_maxbytes = yaffs_max_file_size(dev); ++ ++ /* Release lock before yaffs_get_inode() */ ++ yaffs_gross_unlock(dev); ++ ++ /* Create root inode */ ++ if (err == YAFFS_OK) ++ inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev)); ++ ++ if (!inode) ++ return NULL; ++ ++ inode->i_op = &yaffs_dir_inode_operations; ++ inode->i_fop = &yaffs_dir_operations; ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs_read_super: got root inode"); ++ ++ root = yaffs_make_root(inode); ++ ++ if (!root) ++ return NULL; ++ ++ sb->s_root = root; ++ if(!dev->is_checkpointed) ++ yaffs_set_super_dirty(dev); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs_read_super: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs_read_super: done"); ++ return sb; ++} ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *data) ++{ ++ return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd); ++} ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data, struct vfsmount *mnt) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs_internal_read_super_mtd, mnt); ++} ++#else ++static struct super_block *yaffs_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs_internal_read_super_mtd); ++} ++#endif ++ ++static struct file_system_type yaffs_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "yaffs", ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++ .mount = yaffs_mount, ++#else ++ .get_sb = yaffs_read_super, ++#endif ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV, ++}; ++#else ++static struct super_block *yaffs_read_super(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(1, sb, data, silent); ++} ++ ++static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, ++ FS_REQUIRES_DEV); ++#endif ++ ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, ++ int silent) ++{ ++ return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *data) ++{ ++ return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd); ++} ++#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) ++static int yaffs2_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, void *data, ++ struct vfsmount *mnt) ++{ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs2_internal_read_super_mtd, mnt); ++} ++#else ++static struct super_block *yaffs2_read_super(struct file_system_type *fs, ++ int flags, const char *dev_name, ++ void *data) ++{ ++ ++ return get_sb_bdev(fs, flags, dev_name, data, ++ yaffs2_internal_read_super_mtd); ++} ++#endif ++ ++static struct file_system_type yaffs2_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "yaffs2", ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++ .mount = yaffs2_mount, ++#else ++ .get_sb = yaffs2_read_super, ++#endif ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV, ++}; ++#else ++static struct super_block *yaffs2_read_super(struct super_block *sb, ++ void *data, int silent) ++{ ++ return yaffs_internal_read_super(2, sb, data, silent); ++} ++ ++static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, ++ FS_REQUIRES_DEV); ++#endif ++ ++ ++static struct proc_dir_entry *my_proc_entry; ++ ++static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) ++{ ++ struct yaffs_param *param = &dev->param; ++ ++ buf += sprintf(buf, "start_block.......... %d\n", param->start_block); ++ buf += sprintf(buf, "end_block............ %d\n", param->end_block); ++ buf += sprintf(buf, "total_bytes_per_chunk %d\n", ++ param->total_bytes_per_chunk); ++ buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc); ++ buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc); ++ buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2); ++ buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags); ++ buf += sprintf(buf, "empty_lost_n_found... %d\n", ++ param->empty_lost_n_found); ++ buf += sprintf(buf, "disable_lazy_load.... %d\n", ++ param->disable_lazy_load); ++ buf += sprintf(buf, "refresh_period....... %d\n", ++ param->refresh_period); ++ buf += sprintf(buf, "n_caches............. %d\n", param->n_caches); ++ buf += sprintf(buf, "n_reserved_blocks.... %d\n", ++ param->n_reserved_blocks); ++ buf += sprintf(buf, "always_check_erased.. %d\n", ++ param->always_check_erased); ++ buf += sprintf(buf, "\n"); ++ ++ return buf; ++} ++ ++static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev) ++{ ++ buf += sprintf(buf, "max file size....... %lld\n", ++ (long long) yaffs_max_file_size(dev)); ++ buf += sprintf(buf, "data_bytes_per_chunk. %d\n", ++ dev->data_bytes_per_chunk); ++ buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits); ++ buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size); ++ buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks); ++ buf += sprintf(buf, "blocks_in_checkpt.... %d\n", ++ dev->blocks_in_checkpt); ++ buf += sprintf(buf, "\n"); ++ buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes); ++ buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj); ++ buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks); ++ buf += sprintf(buf, "\n"); ++ buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes); ++ buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads); ++ buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures); ++ buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies); ++ buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs); ++ buf += sprintf(buf, "passive_gc_count..... %u\n", ++ dev->passive_gc_count); ++ buf += sprintf(buf, "oldest_dirty_gc_count %u\n", ++ dev->oldest_dirty_gc_count); ++ buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks); ++ buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs); ++ buf += sprintf(buf, "n_retried_writes..... %u\n", ++ dev->n_retried_writes); ++ buf += sprintf(buf, "n_retired_blocks..... %u\n", ++ dev->n_retired_blocks); ++ buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed); ++ buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed); ++ buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n", ++ dev->n_tags_ecc_fixed); ++ buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n", ++ dev->n_tags_ecc_unfixed); ++ buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits); ++ buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files); ++ buf += sprintf(buf, "n_unlinked_files..... %u\n", ++ dev->n_unlinked_files); ++ buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count); ++ buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions); ++ buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used); ++ buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used); ++ ++ return buf; ++} ++ ++static int yaffs_proc_read(char *page, ++ char **start, ++ off_t offset, int count, int *eof, void *data) ++{ ++ struct list_head *item; ++ char *buf = page; ++ int step = offset; ++ int n = 0; ++ ++ /* Get proc_file_read() to step 'offset' by one on each sucessive call. ++ * We use 'offset' (*ppos) to indicate where we are in dev_list. ++ * This also assumes the user has posted a read buffer large ++ * enough to hold the complete output; but that's life in /proc. ++ */ ++ ++ *(int *)start = 1; ++ ++ /* Print header first */ ++ if (step == 0) ++ buf += ++ sprintf(buf, ++ "Multi-version YAFFS built:" __DATE__ " " __TIME__ ++ "\n"); ++ else if (step == 1) ++ buf += sprintf(buf, "\n"); ++ else { ++ step -= 2; ++ ++ mutex_lock(&yaffs_context_lock); ++ ++ /* Locate and print the Nth entry. Order N-squared but N is small. */ ++ list_for_each(item, &yaffs_context_list) { ++ struct yaffs_linux_context *dc = ++ list_entry(item, struct yaffs_linux_context, ++ context_list); ++ struct yaffs_dev *dev = dc->dev; ++ ++ if (n < (step & ~1)) { ++ n += 2; ++ continue; ++ } ++ if ((step & 1) == 0) { ++ buf += ++ sprintf(buf, "\nDevice %d \"%s\"\n", n, ++ dev->param.name); ++ buf = yaffs_dump_dev_part0(buf, dev); ++ } else { ++ buf = yaffs_dump_dev_part1(buf, dev); ++ } ++ ++ break; ++ } ++ mutex_unlock(&yaffs_context_lock); ++ } ++ ++ return buf - page < count ? buf - page : count; ++} ++ ++/** ++ * Set the verbosity of the warnings and error messages. ++ * ++ * Note that the names can only be a..z or _ with the current code. ++ */ ++ ++static struct { ++ char *mask_name; ++ unsigned mask_bitfield; ++} mask_flags[] = { ++ {"allocate", YAFFS_TRACE_ALLOCATE}, ++ {"always", YAFFS_TRACE_ALWAYS}, ++ {"background", YAFFS_TRACE_BACKGROUND}, ++ {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, ++ {"buffers", YAFFS_TRACE_BUFFERS}, ++ {"bug", YAFFS_TRACE_BUG}, ++ {"checkpt", YAFFS_TRACE_CHECKPOINT}, ++ {"deletion", YAFFS_TRACE_DELETION}, ++ {"erase", YAFFS_TRACE_ERASE}, ++ {"error", YAFFS_TRACE_ERROR}, ++ {"gc_detail", YAFFS_TRACE_GC_DETAIL}, ++ {"gc", YAFFS_TRACE_GC}, ++ {"lock", YAFFS_TRACE_LOCK}, ++ {"mtd", YAFFS_TRACE_MTD}, ++ {"nandaccess", YAFFS_TRACE_NANDACCESS}, ++ {"os", YAFFS_TRACE_OS}, ++ {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, ++ {"scan", YAFFS_TRACE_SCAN}, ++ {"mount", YAFFS_TRACE_MOUNT}, ++ {"tracing", YAFFS_TRACE_TRACING}, ++ {"sync", YAFFS_TRACE_SYNC}, ++ {"write", YAFFS_TRACE_WRITE}, ++ {"verify", YAFFS_TRACE_VERIFY}, ++ {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, ++ {"verify_full", YAFFS_TRACE_VERIFY_FULL}, ++ {"verify_all", YAFFS_TRACE_VERIFY_ALL}, ++ {"all", 0xffffffff}, ++ {"none", 0}, ++ {NULL, 0}, ++}; ++ ++#define MAX_MASK_NAME_LENGTH 40 ++static int yaffs_proc_write_trace_options(struct file *file, const char *buf, ++ unsigned long count, void *data) ++{ ++ unsigned rg = 0, mask_bitfield; ++ char *end; ++ char *mask_name; ++ const char *x; ++ char substring[MAX_MASK_NAME_LENGTH + 1]; ++ int i; ++ int done = 0; ++ int add, len = 0; ++ int pos = 0; ++ ++ rg = yaffs_trace_mask; ++ ++ while (!done && (pos < count)) { ++ done = 1; ++ while ((pos < count) && isspace(buf[pos])) ++ pos++; ++ ++ switch (buf[pos]) { ++ case '+': ++ case '-': ++ case '=': ++ add = buf[pos]; ++ pos++; ++ break; ++ ++ default: ++ add = ' '; ++ break; ++ } ++ mask_name = NULL; ++ ++ mask_bitfield = simple_strtoul(buf + pos, &end, 0); ++ ++ if (end > buf + pos) { ++ mask_name = "numeral"; ++ len = end - (buf + pos); ++ pos += len; ++ done = 0; ++ } else { ++ for (x = buf + pos, i = 0; ++ (*x == '_' || (*x >= 'a' && *x <= 'z')) && ++ i < MAX_MASK_NAME_LENGTH; x++, i++, pos++) ++ substring[i] = *x; ++ substring[i] = '\0'; ++ ++ for (i = 0; mask_flags[i].mask_name != NULL; i++) { ++ if (strcmp(substring, mask_flags[i].mask_name) ++ == 0) { ++ mask_name = mask_flags[i].mask_name; ++ mask_bitfield = ++ mask_flags[i].mask_bitfield; ++ done = 0; ++ break; ++ } ++ } ++ } ++ ++ if (mask_name != NULL) { ++ done = 0; ++ switch (add) { ++ case '-': ++ rg &= ~mask_bitfield; ++ break; ++ case '+': ++ rg |= mask_bitfield; ++ break; ++ case '=': ++ rg = mask_bitfield; ++ break; ++ default: ++ rg |= mask_bitfield; ++ break; ++ } ++ } ++ } ++ ++ yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS; ++ ++ printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask); ++ ++ if (rg & YAFFS_TRACE_ALWAYS) { ++ for (i = 0; mask_flags[i].mask_name != NULL; i++) { ++ char flag; ++ flag = ((rg & mask_flags[i].mask_bitfield) == ++ mask_flags[i].mask_bitfield) ? '+' : '-'; ++ printk(KERN_DEBUG "%c%s\n", flag, ++ mask_flags[i].mask_name); ++ } ++ } ++ ++ return count; ++} ++ ++static int yaffs_proc_write(struct file *file, const char *buf, ++ unsigned long count, void *data) ++{ ++ return yaffs_proc_write_trace_options(file, buf, count, data); ++} ++ ++/* Stuff to handle installation of file systems */ ++struct file_system_to_install { ++ struct file_system_type *fst; ++ int installed; ++}; ++ ++static struct file_system_to_install fs_to_install[] = { ++ {&yaffs_fs_type, 0}, ++ {&yaffs2_fs_type, 0}, ++ {NULL, 0} ++}; ++ ++static int __init init_yaffs_fs(void) ++{ ++ int error = 0; ++ struct file_system_to_install *fsinst; ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs built " __DATE__ " " __TIME__ " Installing."); ++ ++ mutex_init(&yaffs_context_lock); ++ ++ /* Install the proc_fs entries */ ++ my_proc_entry = create_proc_entry("yaffs", ++ S_IRUGO | S_IFREG, YPROC_ROOT); ++ ++ if (my_proc_entry) { ++ my_proc_entry->write_proc = yaffs_proc_write; ++ my_proc_entry->read_proc = yaffs_proc_read; ++ my_proc_entry->data = NULL; ++ } else { ++ return -ENOMEM; ++ } ++ ++ /* Now add the file system entries */ ++ ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst && !error) { ++ error = register_filesystem(fsinst->fst); ++ if (!error) ++ fsinst->installed = 1; ++ fsinst++; ++ } ++ ++ /* Any errors? uninstall */ ++ if (error) { ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst) { ++ if (fsinst->installed) { ++ unregister_filesystem(fsinst->fst); ++ fsinst->installed = 0; ++ } ++ fsinst++; ++ } ++ } ++ ++ return error; ++} ++ ++static void __exit exit_yaffs_fs(void) ++{ ++ ++ struct file_system_to_install *fsinst; ++ ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "yaffs built " __DATE__ " " __TIME__ " removing."); ++ ++ remove_proc_entry("yaffs", YPROC_ROOT); ++ ++ fsinst = fs_to_install; ++ ++ while (fsinst->fst) { ++ if (fsinst->installed) { ++ unregister_filesystem(fsinst->fst); ++ fsinst->installed = 0; ++ } ++ fsinst++; ++ } ++} ++ ++module_init(init_yaffs_fs) ++ module_exit(exit_yaffs_fs) ++ ++ MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); ++MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011"); ++MODULE_LICENSE("GPL"); +diff --git a/fs/yaffs2/yaffs_yaffs1.c b/fs/yaffs2/yaffs_yaffs1.c +new file mode 100755 +index 00000000..d277e20e +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs1.c +@@ -0,0 +1,422 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_yaffs1.h" ++#include "yportenv.h" ++#include "yaffs_trace.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_nand.h" ++#include "yaffs_attribs.h" ++ ++int yaffs1_scan(struct yaffs_dev *dev) ++{ ++ struct yaffs_ext_tags tags; ++ int blk; ++ int result; ++ int chunk; ++ int c; ++ int deleted; ++ enum yaffs_block_state state; ++ LIST_HEAD(hard_list); ++ struct yaffs_block_info *bi; ++ u32 seq_number; ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_obj *in; ++ struct yaffs_obj *parent; ++ int alloc_failed = 0; ++ struct yaffs_shadow_fixer *shadow_fixers = NULL; ++ u8 *chunk_data; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs1_scan starts intstartblk %d intendblk %d...", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ chunk_data = yaffs_get_temp_buffer(dev); ++ ++ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER; ++ ++ /* Scan all the blocks to determine their state */ ++ bi = dev->block_info; ++ for (blk = dev->internal_start_block; blk <= dev->internal_end_block; ++ blk++) { ++ yaffs_clear_chunk_bits(dev, blk); ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ ++ yaffs_query_init_block_state(dev, blk, &state, &seq_number); ++ ++ bi->block_state = state; ++ bi->seq_number = seq_number; ++ ++ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) ++ bi->block_state = state = YAFFS_BLOCK_STATE_DEAD; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, ++ "Block scanning block %d state %d seq %d", ++ blk, state, seq_number); ++ ++ if (state == YAFFS_BLOCK_STATE_DEAD) { ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, ++ "block %d is bad", blk); ++ } else if (state == YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty "); ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += dev->param.chunks_per_block; ++ } ++ bi++; ++ } ++ ++ /* For each block.... */ ++ for (blk = dev->internal_start_block; ++ !alloc_failed && blk <= dev->internal_end_block; blk++) { ++ ++ cond_resched(); ++ ++ bi = yaffs_get_block_info(dev, blk); ++ state = bi->block_state; ++ ++ deleted = 0; ++ ++ /* For each chunk in each block that needs scanning.... */ ++ for (c = 0; ++ !alloc_failed && c < dev->param.chunks_per_block && ++ state == YAFFS_BLOCK_STATE_NEEDS_SCAN; c++) { ++ /* Read the tags and decide what to do */ ++ chunk = blk * dev->param.chunks_per_block + c; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, ++ &tags); ++ ++ /* Let's have a good look at this chunk... */ ++ ++ if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED || ++ tags.is_deleted) { ++ /* YAFFS1 only... ++ * A deleted chunk ++ */ ++ deleted++; ++ dev->n_free_chunks++; ++ } else if (!tags.chunk_used) { ++ /* An unassigned chunk in the block ++ * This means that either the block is empty or ++ * this is the one being allocated from ++ */ ++ ++ if (c == 0) { ++ /* We're looking at the first chunk in ++ *the block so the block is unused */ ++ state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ } else { ++ /* this is the block being allocated */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Allocating from %d %d", ++ blk, c); ++ state = YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->alloc_block = blk; ++ dev->alloc_page = c; ++ dev->alloc_block_finder = blk; ++ ++ } ++ ++ dev->n_free_chunks += ++ (dev->param.chunks_per_block - c); ++ } else if (tags.chunk_id > 0) { ++ /* chunk_id > 0 so it is a data chunk... */ ++ unsigned int endpos; ++ ++ yaffs_set_chunk_bit(dev, blk, c); ++ bi->pages_in_use++; ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ YAFFS_OBJECT_TYPE_FILE); ++ /* PutChunkIntoFile checks for a clash ++ * (two data chunks with the same chunk_id). ++ */ ++ ++ if (!in) ++ alloc_failed = 1; ++ ++ if (in) { ++ if (!yaffs_put_chunk_in_file ++ (in, tags.chunk_id, chunk, 1)) ++ alloc_failed = 1; ++ } ++ ++ endpos = ++ (tags.chunk_id - 1) * ++ dev->data_bytes_per_chunk + ++ tags.n_bytes; ++ if (in && ++ in->variant_type == ++ YAFFS_OBJECT_TYPE_FILE && ++ in->variant.file_variant.scanned_size < ++ endpos) { ++ in->variant.file_variant.scanned_size = ++ endpos; ++ if (!dev->param.use_header_file_size) { ++ in->variant. ++ file_variant.file_size = ++ in->variant. ++ file_variant.scanned_size; ++ } ++ ++ } ++ } else { ++ /* chunk_id == 0, so it is an ObjectHeader. ++ * Make the object ++ */ ++ yaffs_set_chunk_bit(dev, blk, c); ++ bi->pages_in_use++; ++ ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, ++ chunk_data, ++ NULL); ++ ++ oh = (struct yaffs_obj_hdr *)chunk_data; ++ ++ in = yaffs_find_by_number(dev, tags.obj_id); ++ if (in && in->variant_type != oh->type) { ++ /* This should not happen, but somehow ++ * Wev'e ended up with an obj_id that ++ * has been reused but not yet deleted, ++ * and worse still it has changed type. ++ * Delete the old object. ++ */ ++ ++ yaffs_del_obj(in); ++ in = NULL; ++ } ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ oh->type); ++ ++ if (!in) ++ alloc_failed = 1; ++ ++ if (in && oh->shadows_obj > 0) { ++ ++ struct yaffs_shadow_fixer *fixer; ++ fixer = ++ kmalloc(sizeof ++ (struct yaffs_shadow_fixer), ++ GFP_NOFS); ++ if (fixer) { ++ fixer->next = shadow_fixers; ++ shadow_fixers = fixer; ++ fixer->obj_id = tags.obj_id; ++ fixer->shadowed_id = ++ oh->shadows_obj; ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Shadow fixer: %d shadows %d", ++ fixer->obj_id, ++ fixer->shadowed_id); ++ ++ } ++ ++ } ++ ++ if (in && in->valid) { ++ /* We have already filled this one. ++ * We have a duplicate and need to ++ * resolve it. */ ++ ++ unsigned existing_serial = in->serial; ++ unsigned new_serial = ++ tags.serial_number; ++ ++ if (((existing_serial + 1) & 3) == ++ new_serial) { ++ /* Use new one - destroy the ++ * exisiting one */ ++ yaffs_chunk_del(dev, ++ in->hdr_chunk, ++ 1, __LINE__); ++ in->valid = 0; ++ } else { ++ /* Use existing - destroy ++ * this one. */ ++ yaffs_chunk_del(dev, chunk, 1, ++ __LINE__); ++ } ++ } ++ ++ if (in && !in->valid && ++ (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == ++ YAFFS_OBJECTID_LOSTNFOUND)) { ++ /* We only load some info, don't fiddle ++ * with directory structure */ ++ in->valid = 1; ++ in->variant_type = oh->type; ++ ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->hdr_chunk = chunk; ++ in->serial = tags.serial_number; ++ ++ } else if (in && !in->valid) { ++ /* we need to load this info */ ++ ++ in->valid = 1; ++ in->variant_type = oh->type; ++ ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->hdr_chunk = chunk; ++ in->serial = tags.serial_number; ++ ++ yaffs_set_obj_name_from_oh(in, oh); ++ in->dirty = 0; ++ ++ /* directory stuff... ++ * hook up to parent ++ */ ++ ++ parent = ++ yaffs_find_or_create_by_number ++ (dev, oh->parent_obj_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ if (!parent) ++ alloc_failed = 1; ++ if (parent && parent->variant_type == ++ YAFFS_OBJECT_TYPE_UNKNOWN) { ++ /* Set up as a directory */ ++ parent->variant_type = ++ YAFFS_OBJECT_TYPE_DIRECTORY; ++ INIT_LIST_HEAD(&parent-> ++ variant.dir_variant. ++ children); ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ /* Hoosterman, a problem.... ++ * We're trying to use a ++ * non-directory as a directory ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." ++ ); ++ parent = dev->lost_n_found; ++ } ++ ++ yaffs_add_obj_to_dir(parent, in); ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Todo got a problem */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ if (dev->param. ++ use_header_file_size) ++ in->variant. ++ file_variant.file_size ++ = yaffs_oh_to_size(oh); ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ in->variant. ++ hardlink_variant.equiv_id = ++ oh->equiv_id; ++ list_add(&in->hard_links, ++ &hard_list); ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ in->variant.symlink_variant. ++ alias = ++ yaffs_clone_str(oh->alias); ++ if (!in->variant. ++ symlink_variant.alias) ++ alloc_failed = 1; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (state == YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* If we got this far while scanning, ++ * then the block is fully allocated. */ ++ state = YAFFS_BLOCK_STATE_FULL; ++ } ++ ++ if (state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ /* If the block was partially allocated then ++ * treat it as fully allocated. */ ++ state = YAFFS_BLOCK_STATE_FULL; ++ dev->alloc_block = -1; ++ } ++ ++ bi->block_state = state; ++ ++ /* Now let's see if it was dirty */ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state == YAFFS_BLOCK_STATE_FULL) ++ yaffs_block_became_dirty(dev, blk); ++ } ++ ++ /* Ok, we've done all the scanning. ++ * Fix up the hard link chains. ++ * We should now have scanned all the objects, now it's time to add ++ * these hardlinks. ++ */ ++ ++ yaffs_link_fixup(dev, &hard_list); ++ ++ /* ++ * Fix up any shadowed objects. ++ * There should not be more than one of these. ++ */ ++ { ++ struct yaffs_shadow_fixer *fixer; ++ struct yaffs_obj *obj; ++ ++ while (shadow_fixers) { ++ fixer = shadow_fixers; ++ shadow_fixers = fixer->next; ++ /* Complete the rename transaction by deleting the ++ * shadowed object then setting the object header ++ to unshadowed. ++ */ ++ obj = yaffs_find_by_number(dev, fixer->shadowed_id); ++ if (obj) ++ yaffs_del_obj(obj); ++ ++ obj = yaffs_find_by_number(dev, fixer->obj_id); ++ ++ if (obj) ++ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); ++ ++ kfree(fixer); ++ } ++ } ++ ++ yaffs_release_temp_buffer(dev, chunk_data); ++ ++ if (alloc_failed) ++ return YAFFS_FAIL; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends"); ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_yaffs1.h b/fs/yaffs2/yaffs_yaffs1.h +new file mode 100755 +index 00000000..97e2fdd0 +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs1.h +@@ -0,0 +1,22 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_YAFFS1_H__ ++#define __YAFFS_YAFFS1_H__ ++ ++#include "yaffs_guts.h" ++int yaffs1_scan(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yaffs_yaffs2.c b/fs/yaffs2/yaffs_yaffs2.c +new file mode 100755 +index 00000000..f1dc9722 +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs2.c +@@ -0,0 +1,1532 @@ ++/* ++ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "yaffs_guts.h" ++#include "yaffs_trace.h" ++#include "yaffs_yaffs2.h" ++#include "yaffs_checkptrw.h" ++#include "yaffs_bitmap.h" ++#include "yaffs_nand.h" ++#include "yaffs_getblockinfo.h" ++#include "yaffs_verify.h" ++#include "yaffs_attribs.h" ++#include "yaffs_summary.h" ++ ++/* ++ * Checkpoints are really no benefit on very small partitions. ++ * ++ * To save space on small partitions don't bother with checkpoints unless ++ * the partition is at least this big. ++ */ ++#define YAFFS_CHECKPOINT_MIN_BLOCKS 60 ++#define YAFFS_SMALL_HOLE_THRESHOLD 4 ++ ++/* ++ * Oldest Dirty Sequence Number handling. ++ */ ++ ++/* yaffs_calc_oldest_dirty_seq() ++ * yaffs2_find_oldest_dirty_seq() ++ * Calculate the oldest dirty sequence number if we don't know it. ++ */ ++void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev) ++{ ++ int i; ++ unsigned seq; ++ unsigned block_no = 0; ++ struct yaffs_block_info *b; ++ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ /* Find the oldest dirty sequence number. */ ++ seq = dev->seq_number + 1; ++ b = dev->block_info; ++ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { ++ if (b->block_state == YAFFS_BLOCK_STATE_FULL && ++ (b->pages_in_use - b->soft_del_pages) < ++ dev->param.chunks_per_block && ++ b->seq_number < seq) { ++ seq = b->seq_number; ++ block_no = i; ++ } ++ b++; ++ } ++ ++ if (block_no) { ++ dev->oldest_dirty_seq = seq; ++ dev->oldest_dirty_block = block_no; ++ } ++} ++ ++void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!dev->oldest_dirty_seq) ++ yaffs_calc_oldest_dirty_seq(dev); ++} ++ ++/* ++ * yaffs_clear_oldest_dirty_seq() ++ * Called when a block is erased or marked bad. (ie. when its seq_number ++ * becomes invalid). If the value matches the oldest then we clear ++ * dev->oldest_dirty_seq to force its recomputation. ++ */ ++void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi) ++{ ++ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (!bi || bi->seq_number == dev->oldest_dirty_seq) { ++ dev->oldest_dirty_seq = 0; ++ dev->oldest_dirty_block = 0; ++ } ++} ++ ++/* ++ * yaffs2_update_oldest_dirty_seq() ++ * Update the oldest dirty sequence number whenever we dirty a block. ++ * Only do this if the oldest_dirty_seq is actually being tracked. ++ */ ++void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no, ++ struct yaffs_block_info *bi) ++{ ++ if (!dev->param.is_yaffs2) ++ return; ++ ++ if (dev->oldest_dirty_seq) { ++ if (dev->oldest_dirty_seq > bi->seq_number) { ++ dev->oldest_dirty_seq = bi->seq_number; ++ dev->oldest_dirty_block = block_no; ++ } ++ } ++} ++ ++int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi) ++{ ++ ++ if (!dev->param.is_yaffs2) ++ return 1; /* disqualification only applies to yaffs2. */ ++ ++ if (!bi->has_shrink_hdr) ++ return 1; /* can gc */ ++ ++ yaffs2_find_oldest_dirty_seq(dev); ++ ++ /* Can't do gc of this block if there are any blocks older than this ++ * one that have discarded pages. ++ */ ++ return (bi->seq_number <= dev->oldest_dirty_seq); ++} ++ ++/* ++ * yaffs2_find_refresh_block() ++ * periodically finds the oldest full block by sequence number for refreshing. ++ * Only for yaffs2. ++ */ ++u32 yaffs2_find_refresh_block(struct yaffs_dev *dev) ++{ ++ u32 b; ++ u32 oldest = 0; ++ u32 oldest_seq = 0; ++ struct yaffs_block_info *bi; ++ ++ if (!dev->param.is_yaffs2) ++ return oldest; ++ ++ /* ++ * If refresh period < 10 then refreshing is disabled. ++ */ ++ if (dev->param.refresh_period < 10) ++ return oldest; ++ ++ /* ++ * Fix broken values. ++ */ ++ if (dev->refresh_skip > dev->param.refresh_period) ++ dev->refresh_skip = dev->param.refresh_period; ++ ++ if (dev->refresh_skip > 0) ++ return oldest; ++ ++ /* ++ * Refresh skip is now zero. ++ * We'll do a refresh this time around.... ++ * Update the refresh skip and find the oldest block. ++ */ ++ dev->refresh_skip = dev->param.refresh_period; ++ dev->refresh_count++; ++ bi = dev->block_info; ++ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) { ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_FULL) { ++ ++ if (oldest < 1 || bi->seq_number < oldest_seq) { ++ oldest = b; ++ oldest_seq = bi->seq_number; ++ } ++ } ++ bi++; ++ } ++ ++ if (oldest > 0) { ++ yaffs_trace(YAFFS_TRACE_GC, ++ "GC refresh count %d selected block %d with seq_number %d", ++ dev->refresh_count, oldest, oldest_seq); ++ } ++ ++ return oldest; ++} ++ ++int yaffs2_checkpt_required(struct yaffs_dev *dev) ++{ ++ int nblocks; ++ ++ if (!dev->param.is_yaffs2) ++ return 0; ++ ++ nblocks = dev->internal_end_block - dev->internal_start_block + 1; ++ ++ return !dev->param.skip_checkpt_wr && ++ !dev->read_only && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS); ++} ++ ++int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev) ++{ ++ int retval; ++ int n_bytes = 0; ++ int n_blocks; ++ int dev_blocks; ++ ++ if (!dev->param.is_yaffs2) ++ return 0; ++ ++ if (!dev->checkpoint_blocks_required && yaffs2_checkpt_required(dev)) { ++ /* Not a valid value so recalculate */ ++ dev_blocks = dev->param.end_block - dev->param.start_block + 1; ++ n_bytes += sizeof(struct yaffs_checkpt_validity); ++ n_bytes += sizeof(struct yaffs_checkpt_dev); ++ n_bytes += dev_blocks * sizeof(struct yaffs_block_info); ++ n_bytes += dev_blocks * dev->chunk_bit_stride; ++ n_bytes += ++ (sizeof(struct yaffs_checkpt_obj) + sizeof(u32)) * ++ dev->n_obj; ++ n_bytes += (dev->tnode_size + sizeof(u32)) * dev->n_tnodes; ++ n_bytes += sizeof(struct yaffs_checkpt_validity); ++ n_bytes += sizeof(u32); /* checksum */ ++ ++ /* Round up and add 2 blocks to allow for some bad blocks, ++ * so add 3 */ ++ ++ n_blocks = ++ (n_bytes / ++ (dev->data_bytes_per_chunk * ++ dev->param.chunks_per_block)) + 3; ++ ++ dev->checkpoint_blocks_required = n_blocks; ++ } ++ ++ retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt; ++ if (retval < 0) ++ retval = 0; ++ return retval; ++} ++ ++/*--------------------- Checkpointing --------------------*/ ++ ++static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev *dev, int head) ++{ ++ struct yaffs_checkpt_validity cp; ++ ++ memset(&cp, 0, sizeof(cp)); ++ ++ cp.struct_type = sizeof(cp); ++ cp.magic = YAFFS_MAGIC; ++ cp.version = YAFFS_CHECKPOINT_VERSION; ++ cp.head = (head) ? 1 : 0; ++ ++ return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev *dev, int head) ++{ ++ struct yaffs_checkpt_validity cp; ++ int ok; ++ ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ ++ if (ok) ++ ok = (cp.struct_type == sizeof(cp)) && ++ (cp.magic == YAFFS_MAGIC) && ++ (cp.version == YAFFS_CHECKPOINT_VERSION) && ++ (cp.head == ((head) ? 1 : 0)); ++ return ok ? 1 : 0; ++} ++ ++static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev *cp, ++ struct yaffs_dev *dev) ++{ ++ cp->n_erased_blocks = dev->n_erased_blocks; ++ cp->alloc_block = dev->alloc_block; ++ cp->alloc_page = dev->alloc_page; ++ cp->n_free_chunks = dev->n_free_chunks; ++ ++ cp->n_deleted_files = dev->n_deleted_files; ++ cp->n_unlinked_files = dev->n_unlinked_files; ++ cp->n_bg_deletions = dev->n_bg_deletions; ++ cp->seq_number = dev->seq_number; ++ ++} ++ ++static void yaffs_checkpt_dev_to_dev(struct yaffs_dev *dev, ++ struct yaffs_checkpt_dev *cp) ++{ ++ dev->n_erased_blocks = cp->n_erased_blocks; ++ dev->alloc_block = cp->alloc_block; ++ dev->alloc_page = cp->alloc_page; ++ dev->n_free_chunks = cp->n_free_chunks; ++ ++ dev->n_deleted_files = cp->n_deleted_files; ++ dev->n_unlinked_files = cp->n_unlinked_files; ++ dev->n_bg_deletions = cp->n_bg_deletions; ++ dev->seq_number = cp->seq_number; ++} ++ ++static int yaffs2_wr_checkpt_dev(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_dev cp; ++ u32 n_bytes; ++ u32 n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ int ok; ++ ++ /* Write device runtime values */ ++ yaffs2_dev_to_checkpt_dev(&cp, dev); ++ cp.struct_type = sizeof(cp); ++ ++ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ if (!ok) ++ return 0; ++ ++ /* Write block info */ ++ n_bytes = n_blocks * sizeof(struct yaffs_block_info); ++ ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) == n_bytes); ++ if (!ok) ++ return 0; ++ ++ /* Write chunk bits */ ++ n_bytes = n_blocks * dev->chunk_bit_stride; ++ ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) == n_bytes); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev) ++{ ++ struct yaffs_checkpt_dev cp; ++ u32 n_bytes; ++ u32 n_blocks = ++ (dev->internal_end_block - dev->internal_start_block + 1); ++ int ok; ++ ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ if (!ok) ++ return 0; ++ ++ if (cp.struct_type != sizeof(cp)) ++ return 0; ++ ++ yaffs_checkpt_dev_to_dev(dev, &cp); ++ ++ n_bytes = n_blocks * sizeof(struct yaffs_block_info); ++ ++ ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) == n_bytes); ++ ++ if (!ok) ++ return 0; ++ ++ n_bytes = n_blocks * dev->chunk_bit_stride; ++ ++ ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) == n_bytes); ++ ++ return ok ? 1 : 0; ++} ++ ++static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp, ++ struct yaffs_obj *obj) ++{ ++ cp->obj_id = obj->obj_id; ++ cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0; ++ cp->hdr_chunk = obj->hdr_chunk; ++ cp->variant_type = obj->variant_type; ++ cp->deleted = obj->deleted; ++ cp->soft_del = obj->soft_del; ++ cp->unlinked = obj->unlinked; ++ cp->fake = obj->fake; ++ cp->rename_allowed = obj->rename_allowed; ++ cp->unlink_allowed = obj->unlink_allowed; ++ cp->serial = obj->serial; ++ cp->n_data_chunks = obj->n_data_chunks; ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) ++ cp->size_or_equiv_obj = obj->variant.file_variant.file_size; ++ else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id; ++} ++ ++static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj, ++ struct yaffs_checkpt_obj *cp) ++{ ++ struct yaffs_obj *parent; ++ ++ if (obj->variant_type != cp->variant_type) { ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "Checkpoint read object %d type %d chunk %d does not match existing object type %d", ++ cp->obj_id, cp->variant_type, cp->hdr_chunk, ++ obj->variant_type); ++ return 0; ++ } ++ ++ obj->obj_id = cp->obj_id; ++ ++ if (cp->parent_id) ++ parent = yaffs_find_or_create_by_number(obj->my_dev, ++ cp->parent_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ else ++ parent = NULL; ++ ++ if (parent) { ++ if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { ++ yaffs_trace(YAFFS_TRACE_ALWAYS, ++ "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory", ++ cp->obj_id, cp->parent_id, ++ cp->variant_type, cp->hdr_chunk, ++ parent->variant_type); ++ return 0; ++ } ++ yaffs_add_obj_to_dir(parent, obj); ++ } ++ ++ obj->hdr_chunk = cp->hdr_chunk; ++ obj->variant_type = cp->variant_type; ++ obj->deleted = cp->deleted; ++ obj->soft_del = cp->soft_del; ++ obj->unlinked = cp->unlinked; ++ obj->fake = cp->fake; ++ obj->rename_allowed = cp->rename_allowed; ++ obj->unlink_allowed = cp->unlink_allowed; ++ obj->serial = cp->serial; ++ obj->n_data_chunks = cp->n_data_chunks; ++ ++ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) ++ obj->variant.file_variant.file_size = cp->size_or_equiv_obj; ++ else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) ++ obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj; ++ ++ if (obj->hdr_chunk > 0) ++ obj->lazy_loaded = 1; ++ return 1; ++} ++ ++static int yaffs2_checkpt_tnode_worker(struct yaffs_obj *in, ++ struct yaffs_tnode *tn, u32 level, ++ int chunk_offset) ++{ ++ int i; ++ struct yaffs_dev *dev = in->my_dev; ++ int ok = 1; ++ u32 base_offset; ++ ++ if (!tn) ++ return 1; ++ ++ if (level > 0) { ++ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) { ++ if (!tn->internal[i]) ++ continue; ++ ok = yaffs2_checkpt_tnode_worker(in, ++ tn->internal[i], ++ level - 1, ++ (chunk_offset << ++ YAFFS_TNODES_INTERNAL_BITS) + i); ++ } ++ return ok; ++ } ++ ++ /* Level 0 tnode */ ++ base_offset = chunk_offset << YAFFS_TNODES_LEVEL0_BITS; ++ ok = (yaffs2_checkpt_wr(dev, &base_offset, sizeof(base_offset)) == ++ sizeof(base_offset)); ++ if (ok) ++ ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) == ++ dev->tnode_size); ++ ++ return ok; ++} ++ ++static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj *obj) ++{ ++ u32 end_marker = ~0; ++ int ok = 1; ++ ++ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return ok; ++ ++ ok = yaffs2_checkpt_tnode_worker(obj, ++ obj->variant.file_variant.top, ++ obj->variant.file_variant. ++ top_level, 0); ++ if (ok) ++ ok = (yaffs2_checkpt_wr(obj->my_dev, &end_marker, ++ sizeof(end_marker)) == sizeof(end_marker)); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj *obj) ++{ ++ u32 base_chunk; ++ int ok = 1; ++ struct yaffs_dev *dev = obj->my_dev; ++ struct yaffs_file_var *file_stuct_ptr = &obj->variant.file_variant; ++ struct yaffs_tnode *tn; ++ int nread = 0; ++ ++ ok = (yaffs2_checkpt_rd(dev, &base_chunk, sizeof(base_chunk)) == ++ sizeof(base_chunk)); ++ ++ while (ok && (~base_chunk)) { ++ nread++; ++ /* Read level 0 tnode */ ++ ++ tn = yaffs_get_tnode(dev); ++ if (tn) ++ ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) == ++ dev->tnode_size); ++ else ++ ok = 0; ++ ++ if (tn && ok) ++ ok = yaffs_add_find_tnode_0(dev, ++ file_stuct_ptr, ++ base_chunk, tn) ? 1 : 0; ++ ++ if (ok) ++ ok = (yaffs2_checkpt_rd ++ (dev, &base_chunk, ++ sizeof(base_chunk)) == sizeof(base_chunk)); ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint read tnodes %d records, last %d. ok %d", ++ nread, base_chunk, ok); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_checkpt_obj cp; ++ int i; ++ int ok = 1; ++ struct list_head *lh; ++ ++ /* Iterate through the objects in each hash entry, ++ * dumping them to the checkpointing stream. ++ */ ++ ++ for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) { ++ list_for_each(lh, &dev->obj_bucket[i].list) { ++ obj = list_entry(lh, struct yaffs_obj, hash_link); ++ if (!obj->defered_free) { ++ yaffs2_obj_checkpt_obj(&cp, obj); ++ cp.struct_type = sizeof(cp); ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint write object %d parent %d type %d chunk %d obj addr %p", ++ cp.obj_id, cp.parent_id, ++ cp.variant_type, cp.hdr_chunk, obj); ++ ++ ok = (yaffs2_checkpt_wr(dev, &cp, ++ sizeof(cp)) == sizeof(cp)); ++ ++ if (ok && ++ obj->variant_type == ++ YAFFS_OBJECT_TYPE_FILE) ++ ok = yaffs2_wr_checkpt_tnodes(obj); ++ } ++ } ++ } ++ ++ /* Dump end of list */ ++ memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj)); ++ cp.struct_type = sizeof(cp); ++ ++ if (ok) ++ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev) ++{ ++ struct yaffs_obj *obj; ++ struct yaffs_checkpt_obj cp; ++ int ok = 1; ++ int done = 0; ++ LIST_HEAD(hard_list); ++ ++ ++ while (ok && !done) { ++ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp)); ++ if (cp.struct_type != sizeof(cp)) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "struct size %d instead of %d ok %d", ++ cp.struct_type, (int)sizeof(cp), ok); ++ ok = 0; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "Checkpoint read object %d parent %d type %d chunk %d ", ++ cp.obj_id, cp.parent_id, cp.variant_type, ++ cp.hdr_chunk); ++ ++ if (ok && cp.obj_id == ~0) { ++ done = 1; ++ } else if (ok) { ++ obj = ++ yaffs_find_or_create_by_number(dev, cp.obj_id, ++ cp.variant_type); ++ if (obj) { ++ ok = yaffs2_checkpt_obj_to_obj(obj, &cp); ++ if (!ok) ++ break; ++ if (obj->variant_type == ++ YAFFS_OBJECT_TYPE_FILE) { ++ ok = yaffs2_rd_checkpt_tnodes(obj); ++ } else if (obj->variant_type == ++ YAFFS_OBJECT_TYPE_HARDLINK) { ++ list_add(&obj->hard_links, &hard_list); ++ } ++ } else { ++ ok = 0; ++ } ++ } ++ } ++ ++ if (ok) ++ yaffs_link_fixup(dev, &hard_list); ++ ++ return ok ? 1 : 0; ++} ++ ++static int yaffs2_wr_checkpt_sum(struct yaffs_dev *dev) ++{ ++ u32 checkpt_sum; ++ int ok; ++ ++ yaffs2_get_checkpt_sum(dev, &checkpt_sum); ++ ++ ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) == ++ sizeof(checkpt_sum)); ++ ++ if (!ok) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs2_rd_checkpt_sum(struct yaffs_dev *dev) ++{ ++ u32 checkpt_sum0; ++ u32 checkpt_sum1; ++ int ok; ++ ++ yaffs2_get_checkpt_sum(dev, &checkpt_sum0); ++ ++ ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) == ++ sizeof(checkpt_sum1)); ++ ++ if (!ok) ++ return 0; ++ ++ if (checkpt_sum0 != checkpt_sum1) ++ return 0; ++ ++ return 1; ++} ++ ++static int yaffs2_wr_checkpt_data(struct yaffs_dev *dev) ++{ ++ int ok = 1; ++ ++ if (!yaffs2_checkpt_required(dev)) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "skipping checkpoint write"); ++ ok = 0; ++ } ++ ++ if (ok) ++ ok = yaffs2_checkpt_open(dev, 1); ++ ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint validity"); ++ ok = yaffs2_wr_checkpt_validity_marker(dev, 1); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint device"); ++ ok = yaffs2_wr_checkpt_dev(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint objects"); ++ ok = yaffs2_wr_checkpt_objs(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "write checkpoint validity"); ++ ok = yaffs2_wr_checkpt_validity_marker(dev, 0); ++ } ++ ++ if (ok) ++ ok = yaffs2_wr_checkpt_sum(dev); ++ ++ if (!yaffs_checkpt_close(dev)) ++ ok = 0; ++ ++ if (ok) ++ dev->is_checkpointed = 1; ++ else ++ dev->is_checkpointed = 0; ++ ++ return dev->is_checkpointed; ++} ++ ++static int yaffs2_rd_checkpt_data(struct yaffs_dev *dev) ++{ ++ int ok = 1; ++ ++ if (!dev->param.is_yaffs2) ++ ok = 0; ++ ++ if (ok && dev->param.skip_checkpt_rd) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "skipping checkpoint read"); ++ ok = 0; ++ } ++ ++ if (ok) ++ ok = yaffs2_checkpt_open(dev, 0); /* open for read */ ++ ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint validity"); ++ ok = yaffs2_rd_checkpt_validity_marker(dev, 1); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint device"); ++ ok = yaffs2_rd_checkpt_dev(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint objects"); ++ ok = yaffs2_rd_checkpt_objs(dev); ++ } ++ if (ok) { ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint validity"); ++ ok = yaffs2_rd_checkpt_validity_marker(dev, 0); ++ } ++ ++ if (ok) { ++ ok = yaffs2_rd_checkpt_sum(dev); ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "read checkpoint checksum %d", ok); ++ } ++ ++ if (!yaffs_checkpt_close(dev)) ++ ok = 0; ++ ++ if (ok) ++ dev->is_checkpointed = 1; ++ else ++ dev->is_checkpointed = 0; ++ ++ return ok ? 1 : 0; ++} ++ ++void yaffs2_checkpt_invalidate(struct yaffs_dev *dev) ++{ ++ if (dev->is_checkpointed || dev->blocks_in_checkpt > 0) { ++ dev->is_checkpointed = 0; ++ yaffs2_checkpt_invalidate_stream(dev); ++ } ++ if (dev->param.sb_dirty_fn) ++ dev->param.sb_dirty_fn(dev); ++} ++ ++int yaffs_checkpoint_save(struct yaffs_dev *dev) ++{ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "save entry: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ yaffs_verify_objects(dev); ++ yaffs_verify_blocks(dev); ++ yaffs_verify_free_chunks(dev); ++ ++ if (!dev->is_checkpointed) { ++ yaffs2_checkpt_invalidate(dev); ++ yaffs2_wr_checkpt_data(dev); ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_MOUNT, ++ "save exit: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ return dev->is_checkpointed; ++} ++ ++int yaffs2_checkpt_restore(struct yaffs_dev *dev) ++{ ++ int retval; ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "restore entry: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ retval = yaffs2_rd_checkpt_data(dev); ++ ++ if (dev->is_checkpointed) { ++ yaffs_verify_objects(dev); ++ yaffs_verify_blocks(dev); ++ yaffs_verify_free_chunks(dev); ++ } ++ ++ yaffs_trace(YAFFS_TRACE_CHECKPOINT, ++ "restore exit: is_checkpointed %d", ++ dev->is_checkpointed); ++ ++ return retval; ++} ++ ++int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size) ++{ ++ /* if new_size > old_file_size. ++ * We're going to be writing a hole. ++ * If the hole is small then write zeros otherwise write a start ++ * of hole marker. ++ */ ++ loff_t old_file_size; ++ loff_t increase; ++ int small_hole; ++ int result = YAFFS_OK; ++ struct yaffs_dev *dev = NULL; ++ u8 *local_buffer = NULL; ++ int small_increase_ok = 0; ++ ++ if (!obj) ++ return YAFFS_FAIL; ++ ++ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE) ++ return YAFFS_FAIL; ++ ++ dev = obj->my_dev; ++ ++ /* Bail out if not yaffs2 mode */ ++ if (!dev->param.is_yaffs2) ++ return YAFFS_OK; ++ ++ old_file_size = obj->variant.file_variant.file_size; ++ ++ if (new_size <= old_file_size) ++ return YAFFS_OK; ++ ++ increase = new_size - old_file_size; ++ ++ if (increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk && ++ yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1)) ++ small_hole = 1; ++ else ++ small_hole = 0; ++ ++ if (small_hole) ++ local_buffer = yaffs_get_temp_buffer(dev); ++ ++ if (local_buffer) { ++ /* fill hole with zero bytes */ ++ loff_t pos = old_file_size; ++ int this_write; ++ int written; ++ memset(local_buffer, 0, dev->data_bytes_per_chunk); ++ small_increase_ok = 1; ++ ++ while (increase > 0 && small_increase_ok) { ++ this_write = increase; ++ if (this_write > dev->data_bytes_per_chunk) ++ this_write = dev->data_bytes_per_chunk; ++ written = ++ yaffs_do_file_wr(obj, local_buffer, pos, this_write, ++ 0); ++ if (written == this_write) { ++ pos += this_write; ++ increase -= this_write; ++ } else { ++ small_increase_ok = 0; ++ } ++ } ++ ++ yaffs_release_temp_buffer(dev, local_buffer); ++ ++ /* If out of space then reverse any chunks we've added */ ++ if (!small_increase_ok) ++ yaffs_resize_file_down(obj, old_file_size); ++ } ++ ++ if (!small_increase_ok && ++ obj->parent && ++ obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED && ++ obj->parent->obj_id != YAFFS_OBJECTID_DELETED) { ++ /* Write a hole start header with the old file size */ ++ yaffs_update_oh(obj, NULL, 0, 1, 0, NULL); ++ } ++ ++ return result; ++} ++ ++struct yaffs_block_index { ++ int seq; ++ int block; ++}; ++ ++static int yaffs2_ybicmp(const void *a, const void *b) ++{ ++ int aseq = ((struct yaffs_block_index *)a)->seq; ++ int bseq = ((struct yaffs_block_index *)b)->seq; ++ int ablock = ((struct yaffs_block_index *)a)->block; ++ int bblock = ((struct yaffs_block_index *)b)->block; ++ ++ if (aseq == bseq) ++ return ablock - bblock; ++ ++ return aseq - bseq; ++} ++ ++static inline int yaffs2_scan_chunk(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi, ++ int blk, int chunk_in_block, ++ int *found_chunks, ++ u8 *chunk_data, ++ struct list_head *hard_list, ++ int summary_available) ++{ ++ struct yaffs_obj_hdr *oh; ++ struct yaffs_obj *in; ++ struct yaffs_obj *parent; ++ int equiv_id; ++ loff_t file_size; ++ int is_shrink; ++ int is_unlinked; ++ struct yaffs_ext_tags tags; ++ int result; ++ int alloc_failed = 0; ++ int chunk = blk * dev->param.chunks_per_block + chunk_in_block; ++ struct yaffs_file_var *file_var; ++ struct yaffs_hardlink_var *hl_var; ++ struct yaffs_symlink_var *sl_var; ++ ++ if (summary_available) { ++ result = yaffs_summary_fetch(dev, &tags, chunk_in_block); ++ tags.seq_number = bi->seq_number; ++ } ++ ++ if (!summary_available || tags.obj_id == 0) { ++ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags); ++ dev->tags_used++; ++ } else { ++ dev->summary_used++; ++ } ++ ++ /* Let's have a good look at this chunk... */ ++ ++ if (!tags.chunk_used) { ++ /* An unassigned chunk in the block. ++ * If there are used chunks after this one, then ++ * it is a chunk that was skipped due to failing ++ * the erased check. Just skip it so that it can ++ * be deleted. ++ * But, more typically, We get here when this is ++ * an unallocated chunk and his means that ++ * either the block is empty or this is the one ++ * being allocated from ++ */ ++ ++ if (*found_chunks) { ++ /* This is a chunk that was skipped due ++ * to failing the erased check */ ++ } else if (chunk_in_block == 0) { ++ /* We're looking at the first chunk in ++ * the block so the block is unused */ ++ bi->block_state = YAFFS_BLOCK_STATE_EMPTY; ++ dev->n_erased_blocks++; ++ } else { ++ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) { ++ if (dev->seq_number == bi->seq_number) { ++ /* Allocating from this block*/ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Allocating from %d %d", ++ blk, chunk_in_block); ++ ++ bi->block_state = ++ YAFFS_BLOCK_STATE_ALLOCATING; ++ dev->alloc_block = blk; ++ dev->alloc_page = chunk_in_block; ++ dev->alloc_block_finder = blk; ++ } else { ++ /* This is a partially written block ++ * that is not the current ++ * allocation block. ++ */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Partially written block %d detected. gc will fix this.", ++ blk); ++ } ++ } ++ } ++ ++ dev->n_free_chunks++; ++ ++ } else if (tags.ecc_result == ++ YAFFS_ECC_RESULT_UNFIXED) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ " Unfixed ECC in chunk(%d:%d), chunk ignored", ++ blk, chunk_in_block); ++ dev->n_free_chunks++; ++ } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID || ++ tags.chunk_id > YAFFS_MAX_CHUNK_ID || ++ tags.obj_id == YAFFS_OBJECTID_SUMMARY || ++ (tags.chunk_id > 0 && ++ tags.n_bytes > dev->data_bytes_per_chunk) || ++ tags.seq_number != bi->seq_number) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored", ++ blk, chunk_in_block, tags.obj_id, ++ tags.chunk_id, tags.n_bytes); ++ dev->n_free_chunks++; ++ } else if (tags.chunk_id > 0) { ++ /* chunk_id > 0 so it is a data chunk... */ ++ loff_t endpos; ++ loff_t chunk_base = (tags.chunk_id - 1) * ++ dev->data_bytes_per_chunk; ++ ++ *found_chunks = 1; ++ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ YAFFS_OBJECT_TYPE_FILE); ++ if (!in) ++ /* Out of memory */ ++ alloc_failed = 1; ++ ++ if (in && ++ in->variant_type == YAFFS_OBJECT_TYPE_FILE && ++ chunk_base < in->variant.file_variant.shrink_size) { ++ /* This has not been invalidated by ++ * a resize */ ++ if (!yaffs_put_chunk_in_file(in, tags.chunk_id, ++ chunk, -1)) ++ alloc_failed = 1; ++ ++ /* File size is calculated by looking at ++ * the data chunks if we have not ++ * seen an object header yet. ++ * Stop this practice once we find an ++ * object header. ++ */ ++ endpos = chunk_base + tags.n_bytes; ++ ++ if (!in->valid && ++ in->variant.file_variant.scanned_size < endpos) { ++ in->variant.file_variant. ++ scanned_size = endpos; ++ in->variant.file_variant. ++ file_size = endpos; ++ } ++ } else if (in) { ++ /* This chunk has been invalidated by a ++ * resize, or a past file deletion ++ * so delete the chunk*/ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ } ++ } else { ++ /* chunk_id == 0, so it is an ObjectHeader. ++ * Thus, we read in the object header and make ++ * the object ++ */ ++ *found_chunks = 1; ++ ++ yaffs_set_chunk_bit(dev, blk, chunk_in_block); ++ bi->pages_in_use++; ++ ++ oh = NULL; ++ in = NULL; ++ ++ if (tags.extra_available) { ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, ++ tags.extra_obj_type); ++ if (!in) ++ alloc_failed = 1; ++ } ++ ++ if (!in || ++ (!in->valid && dev->param.disable_lazy_load) || ++ tags.extra_shadows || ++ (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) { ++ ++ /* If we don't have valid info then we ++ * need to read the chunk ++ * TODO In future we can probably defer ++ * reading the chunk and living with ++ * invalid data until needed. ++ */ ++ ++ result = yaffs_rd_chunk_tags_nand(dev, ++ chunk, ++ chunk_data, ++ NULL); ++ ++ oh = (struct yaffs_obj_hdr *)chunk_data; ++ ++ if (dev->param.inband_tags) { ++ /* Fix up the header if they got ++ * corrupted by inband tags */ ++ oh->shadows_obj = ++ oh->inband_shadowed_obj_id; ++ oh->is_shrink = ++ oh->inband_is_shrink; ++ } ++ ++ if (!in) { ++ in = yaffs_find_or_create_by_number(dev, ++ tags.obj_id, oh->type); ++ if (!in) ++ alloc_failed = 1; ++ } ++ } ++ ++ if (!in) { ++ /* TODO Hoosterman we have a problem! */ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: Could not make object for object %d at chunk %d during scan", ++ tags.obj_id, chunk); ++ return YAFFS_FAIL; ++ } ++ ++ if (in->valid) { ++ /* We have already filled this one. ++ * We have a duplicate that will be ++ * discarded, but we first have to suck ++ * out resize info if it is a file. ++ */ ++ if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) && ++ ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) || ++ (tags.extra_available && ++ tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE) ++ )) { ++ loff_t this_size = (oh) ? ++ yaffs_oh_to_size(oh) : ++ tags.extra_file_size; ++ u32 parent_obj_id = (oh) ? ++ oh->parent_obj_id : ++ tags.extra_parent_id; ++ ++ is_shrink = (oh) ? ++ oh->is_shrink : ++ tags.extra_is_shrink; ++ ++ /* If it is deleted (unlinked ++ * at start also means deleted) ++ * we treat the file size as ++ * being zeroed at this point. ++ */ ++ if (parent_obj_id == YAFFS_OBJECTID_DELETED || ++ parent_obj_id == YAFFS_OBJECTID_UNLINKED) { ++ this_size = 0; ++ is_shrink = 1; ++ } ++ ++ if (is_shrink && ++ in->variant.file_variant.shrink_size > ++ this_size) ++ in->variant.file_variant.shrink_size = ++ this_size; ++ ++ if (is_shrink) ++ bi->has_shrink_hdr = 1; ++ } ++ /* Use existing - destroy this one. */ ++ yaffs_chunk_del(dev, chunk, 1, __LINE__); ++ } ++ ++ if (!in->valid && in->variant_type != ++ (oh ? oh->type : tags.extra_obj_type)) ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: Bad object type, %d != %d, for object %d at chunk %d during scan", ++ oh ? oh->type : tags.extra_obj_type, ++ in->variant_type, tags.obj_id, ++ chunk); ++ ++ if (!in->valid && ++ (tags.obj_id == YAFFS_OBJECTID_ROOT || ++ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) { ++ /* We only load some info, don't fiddle ++ * with directory structure */ ++ in->valid = 1; ++ ++ if (oh) { ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ in->lazy_loaded = 0; ++ } else { ++ in->lazy_loaded = 1; ++ } ++ in->hdr_chunk = chunk; ++ ++ } else if (!in->valid) { ++ /* we need to load this info */ ++ in->valid = 1; ++ in->hdr_chunk = chunk; ++ if (oh) { ++ in->variant_type = oh->type; ++ in->yst_mode = oh->yst_mode; ++ yaffs_load_attribs(in, oh); ++ ++ if (oh->shadows_obj > 0) ++ yaffs_handle_shadowed_obj(dev, ++ oh->shadows_obj, 1); ++ ++ yaffs_set_obj_name_from_oh(in, oh); ++ parent = yaffs_find_or_create_by_number(dev, ++ oh->parent_obj_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ file_size = yaffs_oh_to_size(oh); ++ is_shrink = oh->is_shrink; ++ equiv_id = oh->equiv_id; ++ } else { ++ in->variant_type = tags.extra_obj_type; ++ parent = yaffs_find_or_create_by_number(dev, ++ tags.extra_parent_id, ++ YAFFS_OBJECT_TYPE_DIRECTORY); ++ file_size = tags.extra_file_size; ++ is_shrink = tags.extra_is_shrink; ++ equiv_id = tags.extra_equiv_id; ++ in->lazy_loaded = 1; ++ } ++ in->dirty = 0; ++ ++ if (!parent) ++ alloc_failed = 1; ++ ++ /* directory stuff... ++ * hook up to parent ++ */ ++ ++ if (parent && ++ parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) { ++ /* Set up as a directory */ ++ parent->variant_type = ++ YAFFS_OBJECT_TYPE_DIRECTORY; ++ INIT_LIST_HEAD(&parent-> ++ variant.dir_variant.children); ++ } else if (!parent || ++ parent->variant_type != ++ YAFFS_OBJECT_TYPE_DIRECTORY) { ++ /* Hoosterman, another problem.... ++ * Trying to use a non-directory as a directory ++ */ ++ ++ yaffs_trace(YAFFS_TRACE_ERROR, ++ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." ++ ); ++ parent = dev->lost_n_found; ++ } ++ yaffs_add_obj_to_dir(parent, in); ++ ++ is_unlinked = (parent == dev->del_dir) || ++ (parent == dev->unlinked_dir); ++ ++ if (is_shrink) ++ /* Mark the block */ ++ bi->has_shrink_hdr = 1; ++ ++ /* Note re hardlinks. ++ * Since we might scan a hardlink before its equivalent ++ * object is scanned we put them all in a list. ++ * After scanning is complete, we should have all the ++ * objects, so we run through this list and fix up all ++ * the chains. ++ */ ++ ++ switch (in->variant_type) { ++ case YAFFS_OBJECT_TYPE_UNKNOWN: ++ /* Todo got a problem */ ++ break; ++ case YAFFS_OBJECT_TYPE_FILE: ++ file_var = &in->variant.file_variant; ++ if (file_var->scanned_size < file_size) { ++ /* This covers the case where the file ++ * size is greater than the data held. ++ * This will happen if the file is ++ * resized to be larger than its ++ * current data extents. ++ */ ++ file_var->file_size = file_size; ++ file_var->scanned_size = file_size; ++ } ++ ++ if (file_var->shrink_size > file_size) ++ file_var->shrink_size = file_size; ++ ++ break; ++ case YAFFS_OBJECT_TYPE_HARDLINK: ++ hl_var = &in->variant.hardlink_variant; ++ if (!is_unlinked) { ++ hl_var->equiv_id = equiv_id; ++ list_add(&in->hard_links, hard_list); ++ } ++ break; ++ case YAFFS_OBJECT_TYPE_DIRECTORY: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SPECIAL: ++ /* Do nothing */ ++ break; ++ case YAFFS_OBJECT_TYPE_SYMLINK: ++ sl_var = &in->variant.symlink_variant; ++ if (oh) { ++ sl_var->alias = ++ yaffs_clone_str(oh->alias); ++ if (!sl_var->alias) ++ alloc_failed = 1; ++ } ++ break; ++ } ++ } ++ } ++ return alloc_failed ? YAFFS_FAIL : YAFFS_OK; ++} ++ ++int yaffs2_scan_backwards(struct yaffs_dev *dev) ++{ ++ int blk; ++ int block_iter; ++ int start_iter; ++ int end_iter; ++ int n_to_scan = 0; ++ enum yaffs_block_state state; ++ int c; ++ int deleted; ++ LIST_HEAD(hard_list); ++ struct yaffs_block_info *bi; ++ u32 seq_number; ++ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1; ++ u8 *chunk_data; ++ int found_chunks; ++ int alloc_failed = 0; ++ struct yaffs_block_index *block_index = NULL; ++ int alt_block_index = 0; ++ int summary_available; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs2_scan_backwards starts intstartblk %d intendblk %d...", ++ dev->internal_start_block, dev->internal_end_block); ++ ++ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER; ++ ++ block_index = ++ kmalloc(n_blocks * sizeof(struct yaffs_block_index), GFP_NOFS); ++ ++ if (!block_index) { ++ block_index = ++ vmalloc(n_blocks * sizeof(struct yaffs_block_index)); ++ alt_block_index = 1; ++ } ++ ++ if (!block_index) { ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "yaffs2_scan_backwards() could not allocate block index!" ++ ); ++ return YAFFS_FAIL; ++ } ++ ++ dev->blocks_in_checkpt = 0; ++ ++ chunk_data = yaffs_get_temp_buffer(dev); ++ ++ /* Scan all the blocks to determine their state */ ++ bi = dev->block_info; ++ for (blk = dev->internal_start_block; blk <= dev->internal_end_block; ++ blk++) { ++ yaffs_clear_chunk_bits(dev, blk); ++ bi->pages_in_use = 0; ++ bi->soft_del_pages = 0; ++ ++ yaffs_query_init_block_state(dev, blk, &state, &seq_number); ++ ++ bi->block_state = state; ++ bi->seq_number = seq_number; ++ ++ if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA) ++ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; ++ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) ++ bi->block_state = YAFFS_BLOCK_STATE_DEAD; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, ++ "Block scanning block %d state %d seq %d", ++ blk, bi->block_state, seq_number); ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) { ++ dev->blocks_in_checkpt++; ++ ++ } else if (bi->block_state == YAFFS_BLOCK_STATE_DEAD) { ++ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, ++ "block %d is bad", blk); ++ } else if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty "); ++ dev->n_erased_blocks++; ++ dev->n_free_chunks += dev->param.chunks_per_block; ++ } else if (bi->block_state == ++ YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* Determine the highest sequence number */ ++ if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER && ++ seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) { ++ block_index[n_to_scan].seq = seq_number; ++ block_index[n_to_scan].block = blk; ++ n_to_scan++; ++ if (seq_number >= dev->seq_number) ++ dev->seq_number = seq_number; ++ } else { ++ /* TODO: Nasty sequence number! */ ++ yaffs_trace(YAFFS_TRACE_SCAN, ++ "Block scanning block %d has bad sequence number %d", ++ blk, seq_number); ++ } ++ } ++ bi++; ++ } ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "%d blocks to be sorted...", n_to_scan); ++ ++ cond_resched(); ++ ++ /* Sort the blocks by sequence number */ ++ sort(block_index, n_to_scan, sizeof(struct yaffs_block_index), ++ yaffs2_ybicmp, NULL); ++ ++ cond_resched(); ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "...done"); ++ ++ /* Now scan the blocks looking at the data. */ ++ start_iter = 0; ++ end_iter = n_to_scan - 1; ++ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "%d blocks to scan", n_to_scan); ++ ++ /* For each block.... backwards */ ++ for (block_iter = end_iter; ++ !alloc_failed && block_iter >= start_iter; ++ block_iter--) { ++ /* Cooperative multitasking! This loop can run for so ++ long that watchdog timers expire. */ ++ cond_resched(); ++ ++ /* get the block to scan in the correct order */ ++ blk = block_index[block_iter].block; ++ bi = yaffs_get_block_info(dev, blk); ++ deleted = 0; ++ ++ summary_available = yaffs_summary_read(dev, dev->sum_tags, blk); ++ ++ /* For each chunk in each block that needs scanning.... */ ++ found_chunks = 0; ++ if (summary_available) ++ c = dev->chunks_per_summary - 1; ++ else ++ c = dev->param.chunks_per_block - 1; ++ ++ for (/* c is already initialised */; ++ !alloc_failed && c >= 0 && ++ (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN || ++ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING); ++ c--) { ++ /* Scan backwards... ++ * Read the tags and decide what to do ++ */ ++ if (yaffs2_scan_chunk(dev, bi, blk, c, ++ &found_chunks, chunk_data, ++ &hard_list, summary_available) == ++ YAFFS_FAIL) ++ alloc_failed = 1; ++ } ++ ++ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN) { ++ /* If we got this far while scanning, then the block ++ * is fully allocated. */ ++ bi->block_state = YAFFS_BLOCK_STATE_FULL; ++ } ++ ++ /* Now let's see if it was dirty */ ++ if (bi->pages_in_use == 0 && ++ !bi->has_shrink_hdr && ++ bi->block_state == YAFFS_BLOCK_STATE_FULL) { ++ yaffs_block_became_dirty(dev, blk); ++ } ++ } ++ ++ yaffs_skip_rest_of_block(dev); ++ ++ if (alt_block_index) ++ vfree(block_index); ++ else ++ kfree(block_index); ++ ++ /* Ok, we've done all the scanning. ++ * Fix up the hard link chains. ++ * We have scanned all the objects, now it's time to add these ++ * hardlinks. ++ */ ++ yaffs_link_fixup(dev, &hard_list); ++ ++ yaffs_release_temp_buffer(dev, chunk_data); ++ ++ if (alloc_failed) ++ return YAFFS_FAIL; ++ ++ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards ends"); ++ ++ return YAFFS_OK; ++} +diff --git a/fs/yaffs2/yaffs_yaffs2.h b/fs/yaffs2/yaffs_yaffs2.h +new file mode 100755 +index 00000000..2363bfd8 +--- /dev/null ++++ b/fs/yaffs2/yaffs_yaffs2.h +@@ -0,0 +1,39 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YAFFS_YAFFS2_H__ ++#define __YAFFS_YAFFS2_H__ ++ ++#include "yaffs_guts.h" ++ ++void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev); ++void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev); ++void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev, ++ struct yaffs_block_info *bi); ++void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no, ++ struct yaffs_block_info *bi); ++int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi); ++u32 yaffs2_find_refresh_block(struct yaffs_dev *dev); ++int yaffs2_checkpt_required(struct yaffs_dev *dev); ++int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev); ++ ++void yaffs2_checkpt_invalidate(struct yaffs_dev *dev); ++int yaffs2_checkpt_save(struct yaffs_dev *dev); ++int yaffs2_checkpt_restore(struct yaffs_dev *dev); ++ ++int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size); ++int yaffs2_scan_backwards(struct yaffs_dev *dev); ++ ++#endif +diff --git a/fs/yaffs2/yportenv.h b/fs/yaffs2/yportenv.h +new file mode 100755 +index 00000000..666d909b +--- /dev/null ++++ b/fs/yaffs2/yportenv.h +@@ -0,0 +1,82 @@ ++/* ++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. ++ * ++ * Copyright (C) 2002-2011 Aleph One Ltd. ++ * for Toby Churchill Ltd and Brightstar Engineering ++ * ++ * Created by Charles Manning <charles@aleph1.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License version 2.1 as ++ * published by the Free Software Foundation. ++ * ++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. ++ */ ++ ++#ifndef __YPORTENV_H__ ++#define __YPORTENV_H__ ++ ++/* ++ * Define the MTD version in terms of Linux Kernel versions ++ * This allows yaffs to be used independantly of the kernel ++ * as well as with it. ++ */ ++ ++#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) ++ ++#ifdef YAFFS_OUT_OF_TREE ++#include "moduleconfig.h" ++#endif ++ ++#include <linux/version.h> ++#define MTD_VERSION_CODE LINUX_VERSION_CODE ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) ++#include <linux/config.h> ++#endif ++#include <linux/version.h> ++#include <linux/kernel.h> ++#include <linux/mm.h> ++#include <linux/sched.h> ++#include <linux/string.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++#include <linux/xattr.h> ++#include <linux/list.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/stat.h> ++#include <linux/sort.h> ++#include <linux/bitops.h> ++ ++/* These type wrappings are used to support Unicode names in WinCE. */ ++#define YCHAR char ++#define YUCHAR unsigned char ++#define _Y(x) x ++ ++#define YAFFS_LOSTNFOUND_NAME "lost+found" ++#define YAFFS_LOSTNFOUND_PREFIX "obj" ++ ++ ++#define YAFFS_ROOT_MODE 0755 ++#define YAFFS_LOSTNFOUND_MODE 0700 ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) ++#define Y_CURRENT_TIME CURRENT_TIME.tv_sec ++#define Y_TIME_CONVERT(x) (x).tv_sec ++#else ++#define Y_CURRENT_TIME CURRENT_TIME ++#define Y_TIME_CONVERT(x) (x) ++#endif ++ ++#define compile_time_assertion(assertion) \ ++ ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; }) ++ ++ ++#define yaffs_trace(msk, fmt, ...) do { \ ++ if (yaffs_trace_mask & (msk)) \ ++ printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \ ++} while (0) ++ ++ ++#endif +diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h +old mode 100644 +new mode 100755 +index c5813c87..2a47560b +--- a/include/crypto/if_alg.h ++++ b/include/crypto/if_alg.h +@@ -41,6 +41,7 @@ struct af_alg_completion { + struct af_alg_control { + struct af_alg_iv *iv; + int op; ++ struct af_alg_usr_def usr_def; + }; + + struct af_alg_type { +diff --git a/include/linux/clk.h b/include/linux/clk.h +index 1d37f42a..f49e434e 100644 +--- a/include/linux/clk.h ++++ b/include/linux/clk.h +@@ -64,6 +64,11 @@ int clk_enable(struct clk *clk); + */ + void clk_disable(struct clk *clk); + ++/* ++ * clk_reset ++ */ ++void clk_reset(struct clk *clk); ++ + /** + * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. + * This is only valid once the clock source has been enabled. +@@ -155,4 +160,6 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id); + int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, + struct device *dev); + ++void clk_change_parent(struct clk *clk, int select); ++ + #endif +diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h +new file mode 100644 +index 00000000..efee4937 +--- /dev/null ++++ b/include/linux/compiler-gcc5.h +@@ -0,0 +1,67 @@ ++#ifndef __LINUX_COMPILER_H ++#error "Please don't include <linux/compiler-gcc5.h> directly, include <linux/compiler.h> instead." ++#endif ++ ++#define __used __attribute__((__used__)) ++#define __must_check __attribute__((warn_unused_result)) ++#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) ++ ++/* Mark functions as cold. gcc will assume any path leading to a call ++ to them will be unlikely. This means a lot of manual unlikely()s ++ are unnecessary now for any paths leading to the usual suspects ++ like BUG(), printk(), panic() etc. [but let's keep them for now for ++ older compilers] ++ ++ Early snapshots of gcc 4.3 don't support this and we can't detect this ++ in the preprocessor, but we can live with this because they're unreleased. ++ Maketime probing would be overkill here. ++ ++ gcc also has a __attribute__((__hot__)) to move hot functions into ++ a special section, but I don't see any sense in this right now in ++ the kernel context */ ++#define __cold __attribute__((__cold__)) ++ ++#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) ++ ++#ifndef __CHECKER__ ++# define __compiletime_warning(message) __attribute__((warning(message))) ++# define __compiletime_error(message) __attribute__((error(message))) ++#endif /* __CHECKER__ */ ++ ++/* ++ * Mark a position in code as unreachable. This can be used to ++ * suppress control flow warnings after asm blocks that transfer ++ * control elsewhere. ++ * ++ * Early snapshots of gcc 4.5 don't support this and we can't detect ++ * this in the preprocessor, but we can live with this because they're ++ * unreleased. Really, we need to have autoconf for the kernel. ++ */ ++#define unreachable() __builtin_unreachable() ++ ++/* Mark a function definition as prohibited from being cloned. */ ++#define __noclone __attribute__((__noclone__)) ++ ++/* ++ * Tell the optimizer that something else uses this function or variable. ++ */ ++#define __visible __attribute__((externally_visible)) ++ ++/* ++ * GCC 'asm goto' miscompiles certain code sequences: ++ * ++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 ++ * ++ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. ++ * ++ * (asm goto is automatically volatile - the naming reflects this.) ++ */ ++#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) ++ ++#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP ++#define __HAVE_BUILTIN_BSWAP32__ ++#define __HAVE_BUILTIN_BSWAP64__ ++#define __HAVE_BUILTIN_BSWAP16__ ++#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ ++ ++#define KASAN_ABI_VERSION 4 +diff --git a/include/linux/crypto.h b/include/linux/crypto.h +old mode 100644 +new mode 100755 +index a6a7a1c8..7e57baed +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -24,6 +24,7 @@ + #include <linux/slab.h> + #include <linux/string.h> + #include <linux/uaccess.h> ++#include <linux/if_alg.h> + + /* + * Algorithm masks and types. +@@ -329,6 +330,8 @@ struct ablkcipher_tfm { + + unsigned int ivsize; + unsigned int reqsize; ++ /*add usr self data..*/ ++ struct af_alg_usr_def usr_def; + }; + + struct aead_tfm { +@@ -607,6 +610,15 @@ static inline unsigned int crypto_ablkcipher_ivsize( + return crypto_ablkcipher_crt(tfm)->ivsize; + } + ++ ++ ++static inline struct af_alg_usr_def *crypto_ablkcipher_usr_def( ++ struct crypto_ablkcipher *tfm) ++{ ++ return &crypto_ablkcipher_crt(tfm)->usr_def; ++} ++ ++ + static inline unsigned int crypto_ablkcipher_blocksize( + struct crypto_ablkcipher *tfm) + { +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index eee7adde..adff3291 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -18,12 +18,16 @@ + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +-#ifndef DMAENGINE_H +-#define DMAENGINE_H ++#ifndef LINUX_DMAENGINE_H ++#define LINUX_DMAENGINE_H + + #include <linux/device.h> + #include <linux/uio.h> +-#include <linux/dma-mapping.h> ++#include <linux/bug.h> ++#include <linux/scatterlist.h> ++#include <linux/bitmap.h> ++#include <linux/types.h> ++#include <asm/page.h> + + /** + * typedef dma_cookie_t - an opaque DMA cookie +@@ -31,8 +35,8 @@ + * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code + */ + typedef s32 dma_cookie_t; +-#define DMA_MIN_COOKIE 1 +-#define DMA_MAX_COOKIE INT_MAX ++#define DMA_MIN_COOKIE 1 ++#define DMA_MAX_COOKIE INT_MAX + + #define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0) + +@@ -44,10 +48,10 @@ typedef s32 dma_cookie_t; + * @DMA_ERROR: transaction failed + */ + enum dma_status { +- DMA_SUCCESS, +- DMA_IN_PROGRESS, +- DMA_PAUSED, +- DMA_ERROR, ++ DMA_SUCCESS, ++ DMA_IN_PROGRESS, ++ DMA_PAUSED, ++ DMA_ERROR, + }; + + /** +@@ -57,23 +61,105 @@ enum dma_status { + * automatically set as dma devices are registered. + */ + enum dma_transaction_type { +- DMA_MEMCPY, +- DMA_XOR, +- DMA_PQ, +- DMA_XOR_VAL, +- DMA_PQ_VAL, +- DMA_MEMSET, +- DMA_INTERRUPT, +- DMA_SG, +- DMA_PRIVATE, +- DMA_ASYNC_TX, +- DMA_SLAVE, +- DMA_CYCLIC, ++ DMA_MEMCPY, ++ DMA_XOR, ++ DMA_PQ, ++ DMA_XOR_VAL, ++ DMA_PQ_VAL, ++ DMA_MEMSET, ++ DMA_INTERRUPT, ++ DMA_SG, ++ DMA_PRIVATE, ++ DMA_ASYNC_TX, ++ DMA_SLAVE, ++ DMA_CYCLIC, ++ DMA_INTERLEAVE, ++/* last transaction type for creation of the capabilities mask */ ++ DMA_TX_TYPE_END, + }; + +-/* last transaction type for creation of the capabilities mask */ +-#define DMA_TX_TYPE_END (DMA_CYCLIC + 1) ++/** ++ * enum dma_transfer_direction - dma transfer mode and direction indicator ++ * @DMA_MEM_TO_MEM: Async/Memcpy mode ++ * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device ++ * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory ++ * @DMA_DEV_TO_DEV: Slave mode & From Device to Device ++ */ ++enum dma_transfer_direction { ++ DMA_MEM_TO_MEM, ++ DMA_MEM_TO_DEV, ++ DMA_DEV_TO_MEM, ++ DMA_DEV_TO_DEV, ++ DMA_TRANS_NONE, ++}; ++ ++/** ++ * Interleaved Transfer Request ++ * ---------------------------- ++ * A chunk is collection of contiguous bytes to be transfered. ++ * The gap(in bytes) between two chunks is called inter-chunk-gap(ICG). ++ * ICGs may or maynot change between chunks. ++ * A FRAME is the smallest series of contiguous {chunk,icg} pairs, ++ * that when repeated an integral number of times, specifies the transfer. ++ * A transfer template is specification of a Frame, the number of times ++ * it is to be repeated and other per-transfer attributes. ++ * ++ * Practically, a client driver would have ready a template for each ++ * type of transfer it is going to need during its lifetime and ++ * set only 'src_start' and 'dst_start' before submitting the requests. ++ * ++ * ++ * | Frame-1 | Frame-2 | ~ | Frame-'numf' | ++ * |====....==.===...=...|====....==.===...=...| ~ |====....==.===...=...| ++ * ++ * == Chunk size ++ * ... ICG ++ */ ++ ++/** ++ * struct data_chunk - Element of scatter-gather list that makes a frame. ++ * @size: Number of bytes to read from source. ++ * size_dst := fn(op, size_src), so doesn't mean much for destination. ++ * @icg: Number of bytes to jump after last src/dst address of this ++ * chunk and before first src/dst address for next chunk. ++ * Ignored for dst(assumed 0), if dst_inc is true and dst_sgl is false. ++ * Ignored for src(assumed 0), if src_inc is true and src_sgl is false. ++ */ ++struct data_chunk { ++ size_t size; ++ size_t icg; ++}; + ++/** ++ * struct dma_interleaved_template - Template to convey DMAC the transfer pattern ++ * and attributes. ++ * @src_start: Bus address of source for the first chunk. ++ * @dst_start: Bus address of destination for the first chunk. ++ * @dir: Specifies the type of Source and Destination. ++ * @src_inc: If the source address increments after reading from it. ++ * @dst_inc: If the destination address increments after writing to it. ++ * @src_sgl: If the 'icg' of sgl[] applies to Source (scattered read). ++ * Otherwise, source is read contiguously (icg ignored). ++ * Ignored if src_inc is false. ++ * @dst_sgl: If the 'icg' of sgl[] applies to Destination (scattered write). ++ * Otherwise, destination is filled contiguously (icg ignored). ++ * Ignored if dst_inc is false. ++ * @numf: Number of frames in this template. ++ * @frame_size: Number of chunks in a frame i.e, size of sgl[]. ++ * @sgl: Array of {chunk,icg} pairs that make up a frame. ++ */ ++struct dma_interleaved_template { ++ dma_addr_t src_start; ++ dma_addr_t dst_start; ++ enum dma_transfer_direction dir; ++ bool src_inc; ++ bool dst_inc; ++ bool src_sgl; ++ bool dst_sgl; ++ size_t numf; ++ size_t frame_size; ++ struct data_chunk sgl[0]; ++}; + + /** + * enum dma_ctrl_flags - DMA flags to augment operation preparation, +@@ -86,9 +172,9 @@ enum dma_transaction_type { + * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s) + * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s) + * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single +- * (if not set, do the source dma-unmapping as page) ++ * (if not set, do the source dma-unmapping as page) + * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single +- * (if not set, do the destination dma-unmapping as page) ++ * (if not set, do the destination dma-unmapping as page) + * @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q + * @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P + * @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as +@@ -98,16 +184,16 @@ enum dma_transaction_type { + * on the result of this operation + */ + enum dma_ctrl_flags { +- DMA_PREP_INTERRUPT = (1 << 0), +- DMA_CTRL_ACK = (1 << 1), +- DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2), +- DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3), +- DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4), +- DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5), +- DMA_PREP_PQ_DISABLE_P = (1 << 6), +- DMA_PREP_PQ_DISABLE_Q = (1 << 7), +- DMA_PREP_CONTINUE = (1 << 8), +- DMA_PREP_FENCE = (1 << 9), ++ DMA_PREP_INTERRUPT = (1 << 0), ++ DMA_CTRL_ACK = (1 << 1), ++ DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2), ++ DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3), ++ DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4), ++ DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5), ++ DMA_PREP_PQ_DISABLE_P = (1 << 6), ++ DMA_PREP_PQ_DISABLE_Q = (1 << 7), ++ DMA_PREP_CONTINUE = (1 << 8), ++ DMA_PREP_FENCE = (1 << 9), + }; + + /** +@@ -125,19 +211,19 @@ enum dma_ctrl_flags { + * into external start mode. + */ + enum dma_ctrl_cmd { +- DMA_TERMINATE_ALL, +- DMA_PAUSE, +- DMA_RESUME, +- DMA_SLAVE_CONFIG, +- FSLDMA_EXTERNAL_START, ++ DMA_TERMINATE_ALL, ++ DMA_PAUSE, ++ DMA_RESUME, ++ DMA_SLAVE_CONFIG, ++ FSLDMA_EXTERNAL_START, + }; + + /** + * enum sum_check_bits - bit position of pq_check_flags + */ + enum sum_check_bits { +- SUM_CHECK_P = 0, +- SUM_CHECK_Q = 1, ++ SUM_CHECK_P = 0, ++ SUM_CHECK_Q = 1, + }; + + /** +@@ -146,8 +232,8 @@ enum sum_check_bits { + * @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise + */ + enum sum_check_flags { +- SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P), +- SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q), ++ SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P), ++ SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q), + }; + + +@@ -164,15 +250,16 @@ typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t; + */ + + struct dma_chan_percpu { +- /* stats */ +- unsigned long memcpy_count; +- unsigned long bytes_transferred; ++ /* stats */ ++ unsigned long memcpy_count; ++ unsigned long bytes_transferred; + }; + + /** + * struct dma_chan - devices supply DMA channels, clients use them + * @device: ptr to the dma device who supplies this channel, always !%NULL + * @cookie: last cookie value returned to client ++ * @completed_cookie: last completed cookie for this channel + * @chan_id: channel ID for sysfs + * @dev: class device for sysfs + * @device_node: used to add this to the device chan list +@@ -182,18 +269,19 @@ struct dma_chan_percpu { + * @private: private data for certain client-channel associations + */ + struct dma_chan { +- struct dma_device *device; +- dma_cookie_t cookie; +- +- /* sysfs */ +- int chan_id; +- struct dma_chan_dev *dev; +- +- struct list_head device_node; +- struct dma_chan_percpu __percpu *local; +- int client_count; +- int table_count; +- void *private; ++ struct dma_device *device; ++ dma_cookie_t cookie; ++ dma_cookie_t completed_cookie; ++ ++ /* sysfs */ ++ int chan_id; ++ struct dma_chan_dev *dev; ++ ++ struct list_head device_node; ++ struct dma_chan_percpu __percpu *local; ++ int client_count; ++ int table_count; ++ void *private; + }; + + /** +@@ -204,10 +292,10 @@ struct dma_chan { + * @idr_ref - reference count to gate release of dma_device dev_id + */ + struct dma_chan_dev { +- struct dma_chan *chan; +- struct device device; +- int dev_id; +- atomic_t *idr_ref; ++ struct dma_chan *chan; ++ struct device device; ++ int dev_id; ++ atomic_t *idr_ref; + }; + + /** +@@ -215,11 +303,11 @@ struct dma_chan_dev { + * device, source or target buses + */ + enum dma_slave_buswidth { +- DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, +- DMA_SLAVE_BUSWIDTH_1_BYTE = 1, +- DMA_SLAVE_BUSWIDTH_2_BYTES = 2, +- DMA_SLAVE_BUSWIDTH_4_BYTES = 4, +- DMA_SLAVE_BUSWIDTH_8_BYTES = 8, ++ DMA_SLAVE_BUSWIDTH_UNDEFINED = 0, ++ DMA_SLAVE_BUSWIDTH_1_BYTE = 1, ++ DMA_SLAVE_BUSWIDTH_2_BYTES = 2, ++ DMA_SLAVE_BUSWIDTH_4_BYTES = 4, ++ DMA_SLAVE_BUSWIDTH_8_BYTES = 8, + }; + + /** +@@ -247,6 +335,12 @@ enum dma_slave_buswidth { + * may or may not be applicable on memory sources. + * @dst_maxburst: same as src_maxburst but for destination target + * mutatis mutandis. ++ * @device_fc: Flow Controller Settings. Only valid for slave channels. Fill ++ * with 'true' if peripheral should be flow controller. Direction will be ++ * selected at Runtime. ++ * @slave_id: Slave requester id. Only valid for slave channels. The dma ++ * slave peripheral will have unique id as dma requester which need to be ++ * pass as slave config. + * + * This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. +@@ -266,18 +360,20 @@ enum dma_slave_buswidth { + * struct, if applicable. + */ + struct dma_slave_config { +- enum dma_data_direction direction; +- dma_addr_t src_addr; +- dma_addr_t dst_addr; +- enum dma_slave_buswidth src_addr_width; +- enum dma_slave_buswidth dst_addr_width; +- u32 src_maxburst; +- u32 dst_maxburst; ++ enum dma_transfer_direction direction; ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ enum dma_slave_buswidth src_addr_width; ++ enum dma_slave_buswidth dst_addr_width; ++ u32 src_maxburst; ++ u32 dst_maxburst; ++ bool device_fc; ++ unsigned int slave_id; + }; + + static inline const char *dma_chan_name(struct dma_chan *chan) + { +- return dev_name(&chan->dev->device); ++ return dev_name(&chan->dev->device); + } + + void dma_chan_cleanup(struct kref *kref); +@@ -300,9 +396,9 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param); + * struct dma_async_tx_descriptor - async transaction descriptor + * ---dma generic offload fields--- + * @cookie: tracking cookie for this transaction, set to -EBUSY if +- * this tx is sitting on a dependency list ++ * this tx is sitting on a dependency list + * @flags: flags to augment operation preparation, control completion, and +- * communicate status ++ * communicate status + * @phys: physical address of the descriptor + * @chan: target channel for this operation + * @tx_submit: set the prepared descriptor(s) to be executed by the engine +@@ -314,17 +410,17 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param); + * @lock: protect the parent and next pointers + */ + struct dma_async_tx_descriptor { +- dma_cookie_t cookie; +- enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ +- dma_addr_t phys; +- struct dma_chan *chan; +- dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); +- dma_async_tx_callback callback; +- void *callback_param; ++ dma_cookie_t cookie; ++ enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ ++ dma_addr_t phys; ++ struct dma_chan *chan; ++ dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); ++ dma_async_tx_callback callback; ++ void *callback_param; + #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +- struct dma_async_tx_descriptor *next; +- struct dma_async_tx_descriptor *parent; +- spinlock_t lock; ++ struct dma_async_tx_descriptor *next; ++ struct dma_async_tx_descriptor *parent; ++ spinlock_t lock; + #endif + }; + +@@ -337,7 +433,7 @@ static inline void txd_unlock(struct dma_async_tx_descriptor *txd) + } + static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) + { +- BUG(); ++ BUG(); + } + static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) + { +@@ -347,42 +443,42 @@ static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) + } + static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) + { +- return NULL; ++ return NULL; + } + static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) + { +- return NULL; ++ return NULL; + } + + #else + static inline void txd_lock(struct dma_async_tx_descriptor *txd) + { +- spin_lock_bh(&txd->lock); ++ spin_lock_bh(&txd->lock); + } + static inline void txd_unlock(struct dma_async_tx_descriptor *txd) + { +- spin_unlock_bh(&txd->lock); ++ spin_unlock_bh(&txd->lock); + } + static inline void txd_chain(struct dma_async_tx_descriptor *txd, struct dma_async_tx_descriptor *next) + { +- txd->next = next; +- next->parent = txd; ++ txd->next = next; ++ next->parent = txd; + } + static inline void txd_clear_parent(struct dma_async_tx_descriptor *txd) + { +- txd->parent = NULL; ++ txd->parent = NULL; + } + static inline void txd_clear_next(struct dma_async_tx_descriptor *txd) + { +- txd->next = NULL; ++ txd->next = NULL; + } + static inline struct dma_async_tx_descriptor *txd_parent(struct dma_async_tx_descriptor *txd) + { +- return txd->parent; ++ return txd->parent; + } + static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descriptor *txd) + { +- return txd->next; ++ return txd->next; + } + #endif + +@@ -392,13 +488,13 @@ static inline struct dma_async_tx_descriptor *txd_next(struct dma_async_tx_descr + * @last: last completed DMA cookie + * @used: last issued DMA cookie (i.e. the one in progress) + * @residue: the remaining number of bytes left to transmit +- * on the selected transfer for states DMA_IN_PROGRESS and +- * DMA_PAUSED if this is implemented in the driver, else 0 ++ * on the selected transfer for states DMA_IN_PROGRESS and ++ * DMA_PAUSED if this is implemented in the driver, else 0 + */ + struct dma_tx_state { +- dma_cookie_t last; +- dma_cookie_t used; +- u32 residue; ++ dma_cookie_t last; ++ dma_cookie_t used; ++ u32 residue; + }; + + /** +@@ -417,7 +513,7 @@ struct dma_tx_state { + * @dev_id: unique device ID + * @dev: struct device reference for dma mapping api + * @device_alloc_chan_resources: allocate resources and return the +- * number of allocated descriptors ++ * number of allocated descriptors + * @device_free_chan_resources: release DMA channel's resources + * @device_prep_dma_memcpy: prepares a memcpy operation + * @device_prep_dma_xor: prepares a xor operation +@@ -428,179 +524,247 @@ struct dma_tx_state { + * @device_prep_dma_interrupt: prepares an end of chain interrupt operation + * @device_prep_slave_sg: prepares a slave dma operation + * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio. +- * The function takes a buffer of size buf_len. The callback function will +- * be called after period_len bytes have been transferred. ++ * The function takes a buffer of size buf_len. The callback function will ++ * be called after period_len bytes have been transferred. ++ * @device_prep_interleaved_dma: Transfer expression in a generic way. + * @device_control: manipulate all pending operations on a channel, returns +- * zero or error code ++ * zero or error code + * @device_tx_status: poll for transaction completion, the optional +- * txstate parameter can be supplied with a pointer to get a +- * struct with auxiliary transfer status information, otherwise the call +- * will just return a simple status code ++ * txstate parameter can be supplied with a pointer to get a ++ * struct with auxiliary transfer status information, otherwise the call ++ * will just return a simple status code + * @device_issue_pending: push pending transactions to hardware + */ + struct dma_device { + +- unsigned int chancnt; +- unsigned int privatecnt; +- struct list_head channels; +- struct list_head global_node; +- dma_cap_mask_t cap_mask; +- unsigned short max_xor; +- unsigned short max_pq; +- u8 copy_align; +- u8 xor_align; +- u8 pq_align; +- u8 fill_align; +- #define DMA_HAS_PQ_CONTINUE (1 << 15) +- +- int dev_id; +- struct device *dev; +- +- int (*device_alloc_chan_resources)(struct dma_chan *chan); +- void (*device_free_chan_resources)(struct dma_chan *chan); +- +- struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( +- struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, +- size_t len, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_xor)( +- struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, +- unsigned int src_cnt, size_t len, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( +- struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, +- size_t len, enum sum_check_flags *result, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_pq)( +- struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, +- unsigned int src_cnt, const unsigned char *scf, +- size_t len, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( +- struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, +- unsigned int src_cnt, const unsigned char *scf, size_t len, +- enum sum_check_flags *pqres, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_memset)( +- struct dma_chan *chan, dma_addr_t dest, int value, size_t len, +- unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( +- struct dma_chan *chan, unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_sg)( +- struct dma_chan *chan, +- struct scatterlist *dst_sg, unsigned int dst_nents, +- struct scatterlist *src_sg, unsigned int src_nents, +- unsigned long flags); +- +- struct dma_async_tx_descriptor *(*device_prep_slave_sg)( +- struct dma_chan *chan, struct scatterlist *sgl, +- unsigned int sg_len, enum dma_data_direction direction, +- unsigned long flags); +- struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( +- struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, +- size_t period_len, enum dma_data_direction direction); +- int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, +- unsigned long arg); +- +- enum dma_status (*device_tx_status)(struct dma_chan *chan, +- dma_cookie_t cookie, +- struct dma_tx_state *txstate); +- void (*device_issue_pending)(struct dma_chan *chan); ++ unsigned int chancnt; ++ unsigned int privatecnt; ++ struct list_head channels; ++ struct list_head global_node; ++ dma_cap_mask_t cap_mask; ++ unsigned short max_xor; ++ unsigned short max_pq; ++ u8 copy_align; ++ u8 xor_align; ++ u8 pq_align; ++ u8 fill_align; ++ #define DMA_HAS_PQ_CONTINUE (1 << 15) ++ ++ int dev_id; ++ struct device *dev; ++ ++ int (*device_alloc_chan_resources)(struct dma_chan *chan); ++ void (*device_free_chan_resources)(struct dma_chan *chan); ++ ++ struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( ++ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_xor)( ++ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, ++ unsigned int src_cnt, size_t len, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( ++ struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, ++ size_t len, enum sum_check_flags *result, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_pq)( ++ struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, ++ unsigned int src_cnt, const unsigned char *scf, ++ size_t len, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( ++ struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, ++ unsigned int src_cnt, const unsigned char *scf, size_t len, ++ enum sum_check_flags *pqres, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_memset)( ++ struct dma_chan *chan, dma_addr_t dest, int value, size_t len, ++ unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)( ++ struct dma_chan *chan, unsigned long flags); ++ struct dma_async_tx_descriptor *(*device_prep_dma_sg)( ++ struct dma_chan *chan, ++ struct scatterlist *dst_sg, unsigned int dst_nents, ++ struct scatterlist *src_sg, unsigned int src_nents, ++ unsigned long flags); ++ ++ struct dma_async_tx_descriptor *(*device_prep_slave_sg)( ++ struct dma_chan *chan, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context); ++ struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context); ++ struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( ++ struct dma_chan *chan, struct dma_interleaved_template *xt, ++ unsigned long flags); ++ int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ++ unsigned long arg); ++ ++ enum dma_status (*device_tx_status)(struct dma_chan *chan, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate); ++ void (*device_issue_pending)(struct dma_chan *chan); + }; + + static inline int dmaengine_device_control(struct dma_chan *chan, +- enum dma_ctrl_cmd cmd, +- unsigned long arg) ++ enum dma_ctrl_cmd cmd, ++ unsigned long arg) + { +- return chan->device->device_control(chan, cmd, arg); ++ if (chan->device->device_control) ++ return chan->device->device_control(chan, cmd, arg); ++ ++ return -ENOSYS; + } + + static inline int dmaengine_slave_config(struct dma_chan *chan, +- struct dma_slave_config *config) ++ struct dma_slave_config *config) ++{ ++ return dmaengine_device_control(chan, DMA_SLAVE_CONFIG, ++ (unsigned long)config); ++} ++ ++static inline bool is_slave_direction(enum dma_transfer_direction direction) ++{ ++ return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single( ++ struct dma_chan *chan, dma_addr_t buf, size_t len, ++ enum dma_transfer_direction dir, unsigned long flags) ++{ ++ struct scatterlist sg; ++ sg_init_table(&sg, 1); ++ sg_dma_address(&sg) = buf; ++ sg_dma_len(&sg) = len; ++ ++ return chan->device->device_prep_slave_sg(chan, &sg, 1, ++ dir, flags, NULL); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_transfer_direction dir, unsigned long flags) + { +- return dmaengine_device_control(chan, DMA_SLAVE_CONFIG, +- (unsigned long)config); ++ return chan->device->device_prep_slave_sg(chan, sgl, sg_len, ++ dir, flags, NULL); ++} ++ ++#ifdef CONFIG_RAPIDIO_DMA_ENGINE ++struct rio_dma_ext; ++static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( ++ struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, ++ enum dma_transfer_direction dir, unsigned long flags, ++ struct rio_dma_ext *rio_ext) ++{ ++ return chan->device->device_prep_slave_sg(chan, sgl, sg_len, ++ dir, flags, rio_ext); ++} ++#endif ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction dir, ++ unsigned long flags) ++{ ++ return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, ++ period_len, dir, flags, NULL); ++} ++ ++static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( ++ struct dma_chan *chan, struct dma_interleaved_template *xt, ++ unsigned long flags) ++{ ++ return chan->device->device_prep_interleaved_dma(chan, xt, flags); + } + + static inline int dmaengine_terminate_all(struct dma_chan *chan) + { +- return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); ++ return dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0); + } + + static inline int dmaengine_pause(struct dma_chan *chan) + { +- return dmaengine_device_control(chan, DMA_PAUSE, 0); ++ return dmaengine_device_control(chan, DMA_PAUSE, 0); + } + + static inline int dmaengine_resume(struct dma_chan *chan) + { +- return dmaengine_device_control(chan, DMA_RESUME, 0); ++ return dmaengine_device_control(chan, DMA_RESUME, 0); ++} ++ ++static inline enum dma_status dmaengine_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ return chan->device->device_tx_status(chan, cookie, state); + } + + static inline dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + { +- return desc->tx_submit(desc); ++ return desc->tx_submit(desc); + } + + static inline bool dmaengine_check_align(u8 align, size_t off1, size_t off2, size_t len) + { +- size_t mask; +- +- if (!align) +- return true; +- mask = (1 << align) - 1; +- if (mask & (off1 | off2 | len)) +- return false; +- return true; ++ size_t mask; ++ ++ if (!align) ++ return true; ++ mask = (1 << align) - 1; ++ if (mask & (off1 | off2 | len)) ++ return false; ++ return true; + } + + static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1, +- size_t off2, size_t len) ++ size_t off2, size_t len) + { +- return dmaengine_check_align(dev->copy_align, off1, off2, len); ++ return dmaengine_check_align(dev->copy_align, off1, off2, len); + } + + static inline bool is_dma_xor_aligned(struct dma_device *dev, size_t off1, +- size_t off2, size_t len) ++ size_t off2, size_t len) + { +- return dmaengine_check_align(dev->xor_align, off1, off2, len); ++ return dmaengine_check_align(dev->xor_align, off1, off2, len); + } + + static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1, +- size_t off2, size_t len) ++ size_t off2, size_t len) + { +- return dmaengine_check_align(dev->pq_align, off1, off2, len); ++ return dmaengine_check_align(dev->pq_align, off1, off2, len); + } + + static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1, +- size_t off2, size_t len) ++ size_t off2, size_t len) + { +- return dmaengine_check_align(dev->fill_align, off1, off2, len); ++ return dmaengine_check_align(dev->fill_align, off1, off2, len); + } + + static inline void + dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue) + { +- dma->max_pq = maxpq; +- if (has_pq_continue) +- dma->max_pq |= DMA_HAS_PQ_CONTINUE; ++ dma->max_pq = maxpq; ++ if (has_pq_continue) ++ dma->max_pq |= DMA_HAS_PQ_CONTINUE; + } + + static inline bool dmaf_continue(enum dma_ctrl_flags flags) + { +- return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE; ++ return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE; + } + + static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags) + { +- enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P; ++ enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P; + +- return (flags & mask) == mask; ++ return (flags & mask) == mask; + } + + static inline bool dma_dev_has_pq_continue(struct dma_device *dma) + { +- return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; ++ return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; + } + + static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma) + { +- return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; ++ return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; + } + + /* dma_maxpq - reduce maxpq in the face of continued operations +@@ -618,13 +782,13 @@ static inline unsigned short dma_dev_to_maxpq(struct dma_device *dma) + */ + static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) + { +- if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) +- return dma_dev_to_maxpq(dma); +- else if (dmaf_p_disabled_continue(flags)) +- return dma_dev_to_maxpq(dma) - 1; +- else if (dmaf_continue(flags)) +- return dma_dev_to_maxpq(dma) - 3; +- BUG(); ++ if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) ++ return dma_dev_to_maxpq(dma); ++ else if (dmaf_p_disabled_continue(flags)) ++ return dma_dev_to_maxpq(dma) - 1; ++ else if (dmaf_continue(flags)) ++ return dma_dev_to_maxpq(dma) - 3; ++ BUG(); + } + + /* --- public DMA engine API --- */ +@@ -642,8 +806,8 @@ static inline void dmaengine_put(void) + #endif + + #ifdef CONFIG_NET_DMA +-#define net_dmaengine_get() dmaengine_get() +-#define net_dmaengine_put() dmaengine_put() ++#define net_dmaengine_get() dmaengine_get() ++#define net_dmaengine_put() dmaengine_put() + #else + static inline void net_dmaengine_get(void) + { +@@ -654,8 +818,8 @@ static inline void net_dmaengine_put(void) + #endif + + #ifdef CONFIG_ASYNC_TX_DMA +-#define async_dmaengine_get() dmaengine_get() +-#define async_dmaengine_put() dmaengine_put() ++#define async_dmaengine_get() dmaengine_get() ++#define async_dmaengine_put() dmaengine_put() + #ifndef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH + #define async_dma_find_channel(type) dma_find_channel(DMA_ASYNC_TX) + #else +@@ -671,80 +835,64 @@ static inline void async_dmaengine_put(void) + static inline struct dma_chan * + async_dma_find_channel(enum dma_transaction_type type) + { +- return NULL; ++ return NULL; + } + #endif /* CONFIG_ASYNC_TX_DMA */ + + dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, +- void *dest, void *src, size_t len); ++ void *dest, void *src, size_t len); + dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, +- struct page *page, unsigned int offset, void *kdata, size_t len); ++ struct page *page, unsigned int offset, void *kdata, size_t len); + dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan, +- struct page *dest_pg, unsigned int dest_off, struct page *src_pg, +- unsigned int src_off, size_t len); ++ struct page *dest_pg, unsigned int dest_off, struct page *src_pg, ++ unsigned int src_off, size_t len); + void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, +- struct dma_chan *chan); ++ struct dma_chan *chan); + + static inline void async_tx_ack(struct dma_async_tx_descriptor *tx) + { +- tx->flags |= DMA_CTRL_ACK; ++ tx->flags |= DMA_CTRL_ACK; + } + + static inline void async_tx_clear_ack(struct dma_async_tx_descriptor *tx) + { +- tx->flags &= ~DMA_CTRL_ACK; ++ tx->flags &= ~DMA_CTRL_ACK; + } + + static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx) + { +- return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; +-} +- +-#define first_dma_cap(mask) __first_dma_cap(&(mask)) +-static inline int __first_dma_cap(const dma_cap_mask_t *srcp) +-{ +- return min_t(int, DMA_TX_TYPE_END, +- find_first_bit(srcp->bits, DMA_TX_TYPE_END)); +-} +- +-#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask)) +-static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp) +-{ +- return min_t(int, DMA_TX_TYPE_END, +- find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1)); ++ return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK; + } + + #define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask)) + static inline void + __dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) + { +- set_bit(tx_type, dstp->bits); ++ set_bit(tx_type, dstp->bits); + } + + #define dma_cap_clear(tx, mask) __dma_cap_clear((tx), &(mask)) + static inline void + __dma_cap_clear(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp) + { +- clear_bit(tx_type, dstp->bits); ++ clear_bit(tx_type, dstp->bits); + } + + #define dma_cap_zero(mask) __dma_cap_zero(&(mask)) + static inline void __dma_cap_zero(dma_cap_mask_t *dstp) + { +- bitmap_zero(dstp->bits, DMA_TX_TYPE_END); ++ bitmap_zero(dstp->bits, DMA_TX_TYPE_END); + } + + #define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask)) + static inline int + __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) + { +- return test_bit(tx_type, srcp->bits); ++ return test_bit(tx_type, srcp->bits); + } + + #define for_each_dma_cap_mask(cap, mask) \ +- for ((cap) = first_dma_cap(mask); \ +- (cap) < DMA_TX_TYPE_END; \ +- (cap) = next_dma_cap((cap), (mask))) ++ for_each_set_bit(cap, mask.bits, DMA_TX_TYPE_END) + + /** + * dma_async_issue_pending - flush pending transactions to HW +@@ -755,11 +903,9 @@ __dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp) + */ + static inline void dma_async_issue_pending(struct dma_chan *chan) + { +- chan->device->device_issue_pending(chan); ++ chan->device->device_issue_pending(chan); + } + +-#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan) +- + /** + * dma_async_is_tx_complete - poll for transaction completion + * @chan: DMA channel +@@ -772,72 +918,76 @@ static inline void dma_async_issue_pending(struct dma_chan *chan) + * the status of multiple cookies without re-checking hardware state. + */ + static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, +- dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) ++ dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + { +- struct dma_tx_state state; +- enum dma_status status; +- +- status = chan->device->device_tx_status(chan, cookie, &state); +- if (last) +- *last = state.last; +- if (used) +- *used = state.used; +- return status; ++ struct dma_tx_state state; ++ enum dma_status status; ++ ++ status = chan->device->device_tx_status(chan, cookie, &state); ++ if (last) ++ *last = state.last; ++ if (used) ++ *used = state.used; ++ return status; + } + +-#define dma_async_memcpy_complete(chan, cookie, last, used)\ +- dma_async_is_tx_complete(chan, cookie, last, used) +- + /** + * dma_async_is_complete - test a cookie against chan state + * @cookie: transaction identifier to test status of + * @last_complete: last know completed transaction + * @last_used: last cookie value handed out + * +- * dma_async_is_complete() is used in dma_async_memcpy_complete() ++ * dma_async_is_complete() is used in dma_async_is_tx_complete() + * the test logic is separated for lightweight testing of multiple cookies + */ + static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, +- dma_cookie_t last_complete, dma_cookie_t last_used) ++ dma_cookie_t last_complete, dma_cookie_t last_used) + { +- if (last_complete <= last_used) { +- if ((cookie <= last_complete) || (cookie > last_used)) +- return DMA_SUCCESS; +- } else { +- if ((cookie <= last_complete) && (cookie > last_used)) +- return DMA_SUCCESS; +- } +- return DMA_IN_PROGRESS; ++ if (last_complete <= last_used) { ++ if ((cookie <= last_complete) || (cookie > last_used)) ++ return DMA_SUCCESS; ++ } else { ++ if ((cookie <= last_complete) && (cookie > last_used)) ++ return DMA_SUCCESS; ++ } ++ return DMA_IN_PROGRESS; + } + + static inline void + dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used, u32 residue) + { +- if (st) { +- st->last = last; +- st->used = used; +- st->residue = residue; +- } ++ if (st) { ++ st->last = last; ++ st->used = used; ++ st->residue = residue; ++ } + } + + enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); + #ifdef CONFIG_DMA_ENGINE + enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); + void dma_issue_pending_all(void); +-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param); ++struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, ++ dma_filter_fn fn, void *fn_param); ++struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); + void dma_release_channel(struct dma_chan *chan); + #else + static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) + { +- return DMA_SUCCESS; ++ return DMA_SUCCESS; + } + static inline void dma_issue_pending_all(void) + { + } +-static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, +- dma_filter_fn fn, void *fn_param) ++static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, ++ dma_filter_fn fn, void *fn_param) + { +- return NULL; ++ return NULL; ++} ++static inline struct dma_chan *dma_request_slave_channel(struct device *dev, ++ const char *name) ++{ ++ return NULL; + } + static inline void dma_release_channel(struct dma_chan *chan) + { +@@ -850,28 +1000,45 @@ int dma_async_device_register(struct dma_device *device); + void dma_async_device_unregister(struct dma_device *device); + void dma_run_dependencies(struct dma_async_tx_descriptor *tx); + struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); ++struct dma_chan *net_dma_find_channel(void); + #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y) ++#define dma_request_slave_channel_compat(mask, x, y, dev, name) \ ++ __dma_request_slave_channel_compat(&(mask), x, y, dev, name) ++ ++static inline struct dma_chan ++*__dma_request_slave_channel_compat(const dma_cap_mask_t *mask, ++ dma_filter_fn fn, void *fn_param, ++ struct device *dev, char *name) ++{ ++ struct dma_chan *chan; ++ ++ chan = dma_request_slave_channel(dev, name); ++ if (chan) ++ return chan; ++ ++ return __dma_request_channel(mask, fn, fn_param); ++} + + /* --- Helper iov-locking functions --- */ + + struct dma_page_list { +- char __user *base_address; +- int nr_pages; +- struct page **pages; ++ char __user *base_address; ++ int nr_pages; ++ struct page **pages; + }; + + struct dma_pinned_list { +- int nr_iovecs; +- struct dma_page_list page_list[0]; ++ int nr_iovecs; ++ struct dma_page_list page_list[0]; + }; + + struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len); + void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list); + + dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, +- struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len); ++ struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len); + dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov, +- struct dma_pinned_list *pinned_list, struct page *page, +- unsigned int offset, size_t len); ++ struct dma_pinned_list *pinned_list, struct page *page, ++ unsigned int offset, size_t len); + + #endif /* DMAENGINE_H */ +diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h +deleted file mode 100644 +index 4bfe0a2f..00000000 +--- a/include/linux/dw_dmac.h ++++ /dev/null +@@ -1,139 +0,0 @@ +-/* +- * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on +- * AVR32 systems.) +- * +- * Copyright (C) 2007 Atmel Corporation +- * Copyright (C) 2010-2011 ST Microelectronics +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-#ifndef DW_DMAC_H +-#define DW_DMAC_H +- +-#include <linux/dmaengine.h> +- +-/** +- * struct dw_dma_platform_data - Controller configuration parameters +- * @nr_channels: Number of channels supported by hardware (max 8) +- * @is_private: The device channels should be marked as private and not for +- * by the general purpose DMA channel allocator. +- */ +-struct dw_dma_platform_data { +- unsigned int nr_channels; +- bool is_private; +-#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ +-#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ +- unsigned char chan_allocation_order; +-#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ +-#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ +- unsigned char chan_priority; +-}; +- +-/** +- * enum dw_dma_slave_width - DMA slave register access width. +- * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses +- * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses +- * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses +- */ +-enum dw_dma_slave_width { +- DW_DMA_SLAVE_WIDTH_8BIT, +- DW_DMA_SLAVE_WIDTH_16BIT, +- DW_DMA_SLAVE_WIDTH_32BIT, +-}; +- +-/* bursts size */ +-enum dw_dma_msize { +- DW_DMA_MSIZE_1, +- DW_DMA_MSIZE_4, +- DW_DMA_MSIZE_8, +- DW_DMA_MSIZE_16, +- DW_DMA_MSIZE_32, +- DW_DMA_MSIZE_64, +- DW_DMA_MSIZE_128, +- DW_DMA_MSIZE_256, +-}; +- +-/* flow controller */ +-enum dw_dma_fc { +- DW_DMA_FC_D_M2M, +- DW_DMA_FC_D_M2P, +- DW_DMA_FC_D_P2M, +- DW_DMA_FC_D_P2P, +- DW_DMA_FC_P_P2M, +- DW_DMA_FC_SP_P2P, +- DW_DMA_FC_P_M2P, +- DW_DMA_FC_DP_P2P, +-}; +- +-/** +- * struct dw_dma_slave - Controller-specific information about a slave +- * +- * @dma_dev: required DMA master device +- * @tx_reg: physical address of data register used for +- * memory-to-peripheral transfers +- * @rx_reg: physical address of data register used for +- * peripheral-to-memory transfers +- * @reg_width: peripheral register width +- * @cfg_hi: Platform-specific initializer for the CFG_HI register +- * @cfg_lo: Platform-specific initializer for the CFG_LO register +- * @src_master: src master for transfers on allocated channel. +- * @dst_master: dest master for transfers on allocated channel. +- * @src_msize: src burst size. +- * @dst_msize: dest burst size. +- * @fc: flow controller for DMA transfer +- */ +-struct dw_dma_slave { +- struct device *dma_dev; +- dma_addr_t tx_reg; +- dma_addr_t rx_reg; +- enum dw_dma_slave_width reg_width; +- u32 cfg_hi; +- u32 cfg_lo; +- u8 src_master; +- u8 dst_master; +- u8 src_msize; +- u8 dst_msize; +- u8 fc; +-}; +- +-/* Platform-configurable bits in CFG_HI */ +-#define DWC_CFGH_FCMODE (1 << 0) +-#define DWC_CFGH_FIFO_MODE (1 << 1) +-#define DWC_CFGH_PROTCTL(x) ((x) << 2) +-#define DWC_CFGH_SRC_PER(x) ((x) << 7) +-#define DWC_CFGH_DST_PER(x) ((x) << 11) +- +-/* Platform-configurable bits in CFG_LO */ +-#define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ +-#define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) +-#define DWC_CFGL_LOCK_CH_XACT (2 << 12) +-#define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ +-#define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14) +-#define DWC_CFGL_LOCK_BUS_XACT (2 << 14) +-#define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ +-#define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ +-#define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ +-#define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ +- +-/* DMA API extensions */ +-struct dw_cyclic_desc { +- struct dw_desc **desc; +- unsigned long periods; +- void (*period_callback)(void *param); +- void *period_callback_param; +-}; +- +-struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan, +- dma_addr_t buf_addr, size_t buf_len, size_t period_len, +- enum dma_data_direction direction); +-void dw_dma_cyclic_free(struct dma_chan *chan); +-int dw_dma_cyclic_start(struct dma_chan *chan); +-void dw_dma_cyclic_stop(struct dma_chan *chan); +- +-dma_addr_t dw_dma_get_src_addr(struct dma_chan *chan); +- +-dma_addr_t dw_dma_get_dst_addr(struct dma_chan *chan); +- +-#endif /* DW_DMAC_H */ +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index a6c652ef..e6490786 100644 +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -512,6 +512,7 @@ struct i2c_msg { + __u16 flags; + #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ + #define I2C_M_RD 0x0001 /* read data, from slave to master */ ++#define I2C_M_SPERATE_MSG 0x8000 /* every msg with stop use I2C_RDWR*/ + #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +diff --git a/include/linux/if_alg.h b/include/linux/if_alg.h +old mode 100644 +new mode 100755 +index 0f9acce5..bd6deb8f +--- a/include/linux/if_alg.h ++++ b/include/linux/if_alg.h +@@ -28,11 +28,38 @@ struct af_alg_iv { + __u8 iv[0]; + }; + ++#define MAX_EX_KEY_MAP_SIZE 8 ++struct ex_key_map { ++__u32 crypto_key_no; ++__u32 ex_mem_entry; ++} ; ++ ++struct ex_key_map_para { ++__u32 map_size; ++struct ex_key_map map[MAX_EX_KEY_MAP_SIZE]; ++} ; ++ ++struct crypto_adv_info { ++struct ex_key_map_para ex_key_para; ++}; ++struct af_alg_usr_def { ++#define CRYPTO_CPU_SET_KEY (1<<0) ++#define CRYPTO_EX_MEM_SET_KEY (1<<1) ++#define CRYPTO_EX_MEM_INDEP_POWER (1<<2) ++/*bit 8~ex mem bit field..*/ ++#define CRYPTO_EX_MEM_SWITCH_KEY (1<<8) ++/*if set ex mem set switch key..then parse below..*/ ++#define CRYPTO_EX_MEM_4_ENTRY_1_KEY (1<<9) ++__u32 mode; ++/*if key_flag set efuse...then parse the para below...*/ ++struct crypto_adv_info adv; ++}; ++ + /* Socket options */ + #define ALG_SET_KEY 1 + #define ALG_SET_IV 2 + #define ALG_SET_OP 3 +- ++#define ALG_USR_DEF 8 + /* Operations */ + #define ALG_OP_DECRYPT 0 + #define ALG_OP_ENCRYPT 1 +diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h +index bdd7ceeb..52040142 100644 +--- a/include/linux/mmc/dw_mmc.h ++++ b/include/linux/mmc/dw_mmc.h +@@ -14,6 +14,12 @@ + #ifndef _LINUX_MMC_DW_MMC_H_ + #define _LINUX_MMC_DW_MMC_H_ + ++#include <linux/scatterlist.h> ++#include <linux/compiler.h> ++#include <linux/types.h> ++#include <linux/io.h> ++#include <linux/mmc/host.h> ++ + #define MAX_MCI_SLOTS 2 + + enum dw_mci_state { +@@ -117,6 +123,8 @@ struct dw_mci { + + /* DMA interface members*/ + int use_dma; ++ int using_dma; ++ unsigned int prev_blksz; + + dma_addr_t sg_dma; + void *sg_cpu; +@@ -154,6 +162,9 @@ struct dw_mci { + u32 quirks; + + struct regulator *vmmc; /* Power regulator */ ++ ++ int dma_data_mapped; ++ int data_error_flag; + }; + + /* DMA ops for Internal/External DMAC interface */ +@@ -200,7 +211,7 @@ struct dw_mci_board { + /* delay in mS before detecting cards after interrupt */ + u32 detect_delay_ms; + +- int (*init)(u32 slot_id, irq_handler_t , void *); ++ int (*init)(u32 slot_id,void* irq_handler_t , void *); + int (*get_ro)(u32 slot_id); + int (*get_cd)(u32 slot_id); + int (*get_ocr)(u32 slot_id); +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index 1ee44244..413992a3 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -281,6 +281,8 @@ struct mmc_host { + + struct dentry *debugfs_root; + ++ unsigned int rescan_count; ++ + unsigned long private[0] ____cacheline_aligned; + }; + +diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h +index 245cdace..573ed64b 100644 +--- a/include/linux/mmc/sdio.h ++++ b/include/linux/mmc/sdio.h +@@ -72,6 +72,7 @@ + #define SDIO_CCCR_REV_1_00 0 /* CCCR/FBR Version 1.00 */ + #define SDIO_CCCR_REV_1_10 1 /* CCCR/FBR Version 1.10 */ + #define SDIO_CCCR_REV_1_20 2 /* CCCR/FBR Version 1.20 */ ++#define SDIO_CCCR_REV_3_00 3 /* to support SDIO 3.0 (luoc) */ + + #define SDIO_SDIO_REV_1_00 0 /* SDIO Spec Version 1.00 */ + #define SDIO_SDIO_REV_1_10 1 /* SDIO Spec Version 1.10 */ +diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h +index 57cc0e63..ec2c889b 100644 +--- a/include/linux/mtd/bbm.h ++++ b/include/linux/mtd/bbm.h +@@ -101,10 +101,28 @@ struct nand_bbt_descr { + /* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */ + #define NAND_BBT_SCANBYTE1AND6 0x00100000 + /* The nand_bbt_descr was created dynamicaly and must be freed */ +-#define NAND_BBT_DYNAMICSTRUCT 0x00200000 ++/*#define NAND_BBT_DYNAMICSTRUCT 0x00200000*/ ++/* ++ * Use a flash based bad block table. By default, OOB identifier is saved in ++ * OOB area. This option is passed to the default bad block table function. ++ */ ++#define NAND_BBT_USE_FLASH 0x00020000 ++ + /* The bad block table does not OOB for marker */ + #define NAND_BBT_NO_OOB 0x00400000 + ++/* ++ * Do not write new bad block markers to OOB; useful, e.g., when ECC covers ++ * entire spare area. Must be used with NAND_BBT_USE_FLASH. ++ */ ++#define NAND_BBT_NO_OOB_BBM 0x00800000 ++/* ++ * Flag set by nand_create_default_bbt_descr(), marking that the nand_bbt_descr ++ * was allocated dynamicaly and must be freed in nand_release(). Has no meaning ++ * in nand_chip.bbt_options. ++ */ ++#define NAND_BBT_DYNAMICSTRUCT 0x80000000 ++ + /* The maximum number of blocks to scan for a bbt */ + #define NAND_BBT_SCAN_MAXBLOCKS 4 + +diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h +index 2541fb84..3541097b 100644 +--- a/include/linux/mtd/mtd.h ++++ b/include/linux/mtd/mtd.h +@@ -168,6 +168,15 @@ struct mtd_info { + unsigned int erasesize_mask; + unsigned int writesize_mask; + ++ /* ++ * read ops return -EUCLEAN if max number of bitflips corrected on any ++ * one region comprising an ecc step equals or exceeds this value. ++ * Settable by driver, else defaults to ecc_strength. User can override ++ * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; ++ * see Documentation/ABI/testing/sysfs-class-mtd for more detail. ++ */ ++ unsigned int bitflip_threshold; ++ + // Kernel-only stuff starts here. + const char *name; + int index; +diff --git a/include/linux/mtd/spi-nand.h b/include/linux/mtd/spi-nand.h +new file mode 100644 +index 00000000..cfa6e80c +--- /dev/null ++++ b/include/linux/mtd/spi-nand.h +@@ -0,0 +1,345 @@ ++/*- ++ * ++ * Copyright (c) 2009-2014 Micron Technology, Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Peter Pan <peterpandong at micron.com> ++ * ++ * based on mt29f_spinand.h ++ */ ++#ifndef __LINUX_MTD_SPI_NAND_H ++#define __LINUX_MTD_SPI_NAND_H ++ ++#include <linux/wait.h> ++#include <linux/spinlock.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/flashchip.h> ++ ++ ++/* ++ * Standard SPI-NAND flash commands ++ */ ++#define SPINAND_CMD_READ 0x13 ++#define SPINAND_CMD_READ_RDM 0x03 ++#define SPINAND_CMD_PROG_LOAD 0x02 ++#define SPINAND_CMD_PROG_RDM 0x84 ++#define SPINAND_CMD_PROG 0x10 ++#define SPINAND_CMD_ERASE_BLK 0xd8 ++#define SPINAND_CMD_WR_ENABLE 0x06 ++#define SPINAND_CMD_WR_DISABLE 0x04 ++#define SPINAND_CMD_READ_ID 0x9f ++#define SPINAND_CMD_RESET 0xff ++#define SPINAND_CMD_READ_REG 0x0f ++#define SPINAND_CMD_WRITE_REG 0x1f ++ ++#define SPINAND_CMD_READ_CACHE_X2 0x3b ++#define SPINAND_CMD_READ_CACHE_X4 0x6b ++#define SPINAND_CMD_READ_CACHE_DUAL 0xbb ++#define SPINAND_CMD_READ_CACHE_QUAD 0xeb ++ ++#define SPINAND_CMD_PROG_LOAD_X4 0x32 ++#define SPINAND_CMD_PROG_RDM_X4 0xC4 /*or 34*/ ++ ++/* feature registers */ ++#define REG_BLOCK_LOCK 0xa0 ++#define REG_OTP 0xb0 ++#define REG_STATUS 0xc0/* timing */ ++ ++/* status */ ++#define STATUS_OIP_MASK 0x01 ++#define STATUS_READY (0 << 0) ++#define STATUS_BUSY (1 << 0) ++ ++#define STATUS_E_FAIL_MASK 0x04 ++#define STATUS_E_FAIL (1 << 2) ++ ++#define STATUS_P_FAIL_MASK 0x08 ++#define STATUS_P_FAIL (1 << 3) ++ ++/*OTP register defines*/ ++#define OTP_ECC_MASK 0X10 ++#define OTP_ECC_ENABLE (1 << 4) ++#define OTP_ENABLE (1 << 6) ++#define OTP_LOCK (1 << 7) ++#define QE_ENABLE (1 << 0) ++ ++ ++/* block lock */ ++#define BL_ALL_LOCKED 0x38 ++#define BL_1_2_LOCKED 0x30 ++#define BL_1_4_LOCKED 0x28 ++#define BL_1_8_LOCKED 0x20 ++#define BL_1_16_LOCKED 0x18 ++#define BL_1_32_LOCKED 0x10 ++#define BL_1_64_LOCKED 0x08 ++#define BL_ALL_UNLOCKED 0 ++ ++#define SPI_NAND_ECC_SHIFT 4 ++ ++#define SPI_NAND_MT29F_ECC_MASK 3 ++#define SPI_NAND_MT29F_ECC_CORRECTED 1 ++#define SPI_NAND_MT29F_ECC_UNCORR 2 ++#define SPI_NAND_MT29F_ECC_RESERVED 3 ++#define SPI_NAND_MT29F_ECC_SHIFT 4 ++ ++#define SPI_NAND_GD5F_ECC_MASK 7 ++#define SPI_NAND_GD5F_ECC_UNCORR 7 ++#define SPI_NAND_GD5F_ECC_SHIFT 4 ++ ++struct spi_nand_onfi_params { ++ /* rev info and features block */ ++ /* 'O' 'N' 'F' 'I' */ ++ u8 sig[4]; /*0-3*/ ++ __le16 revision; /*4-5*/ ++ __le16 features; /*6-7*/ ++ __le16 opt_cmd; /*8-9*/ ++ u8 reserved0[22]; /*10-31*/ ++ ++ /* manufacturer information block */ ++ char manufacturer[12]; /*32-43*/ ++ char model[20]; /*44-63*/ ++ u8 mfr_id; /*64*/ ++ __le16 date_code; /*65-66*/ ++ u8 reserved1[13]; /*67-79*/ ++ ++ /* memory organization block */ ++ __le32 byte_per_page; /*80-83*/ ++ __le16 spare_bytes_per_page; /*84*85*/ ++ __le32 data_bytes_per_ppage; /*86-89*/ ++ __le16 spare_bytes_per_ppage; /*90-91*/ ++ __le32 pages_per_block; /*92-95*/ ++ __le32 blocks_per_lun; /*96-99*/ ++ u8 lun_count; /*100*/ ++ u8 addr_cycles; /*101*/ ++ u8 bits_per_cell; /*102*/ ++ __le16 bb_per_lun; /*103-104*/ ++ __le16 block_endurance; /*105-106*/ ++ u8 guaranteed_good_blocks; /*107*/ ++ __le16 guaranteed_block_endurance; /*108-109*/ ++ u8 programs_per_page; /*110*/ ++ u8 ppage_attr; /*111*/ ++ u8 ecc_bits; /*112*/ ++ u8 interleaved_bits; /*113*/ ++ u8 interleaved_ops; /*114*/ ++ u8 reserved2[13]; /*115-127*/ ++ ++ /* electrical parameter block */ ++ u8 io_pin_capacitance_max; /*128*/ ++ __le16 timing_mode; /*129-130*/ ++ __le16 program_cache_timing_mode; /*131-132*/ ++ __le16 t_prog; /*133-134*/ ++ __le16 t_bers; /*135-136*/ ++ __le16 t_r; /*137-138*/ ++ __le16 t_ccs; /*139-140*/ ++ u8 reserved3[23]; /*141-163*/ ++ ++ /* vendor */ ++ __le16 vendor_specific_revision; /*164-165*/ ++ u8 vendor_specific[88]; /*166-253*/ ++ ++ __le16 crc; /*254-255*/ ++} __packed; ++ ++#define ONFI_CRC_BASE 0x4F4E ++ ++#define SPINAND_MAX_ID_LEN 4 ++ ++/** ++ * struct spi_nand_chip - SPI-NAND Private Flash Chip Data ++ * @chip_lock: [INTERN] protection lock ++ * @name: name of the chip ++ * @wq: [INTERN] wait queue to sleep on if a SPI-NAND operation ++ * is in progress used instead of the per chip wait queue ++ * when a hw controller is available. ++ * @mfr_id: [BOARDSPECIFIC] manufacture id ++ * @dev_id: [BOARDSPECIFIC] device id ++ * @state: [INTERN] the current state of the SPI-NAND device ++ * @spi: [INTERN] point to spi device structure ++ * @mtd: [INTERN] point to MTD device structure ++ * @reset: [REPLACEABLE] function to reset the device ++ * @read_id: [REPLACEABLE] read manufacture id and device id ++ * @load_page: [REPLACEABLE] load page from NAND to cache ++ * @read_cache: [REPLACEABLE] read data from cache ++ * @store_cache: [REPLACEABLE] write data to cache ++ * @write_page: [REPLACEABLE] program NAND with cache data ++ * @erase_block: [REPLACEABLE] erase a given block ++ * @waitfunc: [REPLACEABLE] wait for ready. ++ * @write_enable: [REPLACEABLE] set write enable latch ++ * @get_ecc_status: [REPLACEABLE] get ecc and bitflip status ++ * @enable_ecc: [REPLACEABLE] enable on-die ecc ++ * @disable_ecc: [REPLACEABLE] disable on-die ecc ++ * @buf: [INTERN] buffer for read/write ++ * @oobbuf: [INTERN] buffer for read/write oob ++ * @pagebuf: [INTERN] holds the pagenumber which is currently in ++ * data_buf. ++ * @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is ++ * currently in data_buf. ++ * @size: [INTERN] the size of chip ++ * @block_size: [INTERN] the size of eraseblock ++ * @page_size: [INTERN] the size of page ++ * @page_spare_size: [INTERN] the size of page oob size ++ * @block_shift: [INTERN] number of address bits in a eraseblock ++ * @page_shift: [INTERN] number of address bits in a page (column ++ * address bits). ++ * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 ++ * @options: [BOARDSPECIFIC] various chip options. They can partly ++ * be set to inform nand_scan about special functionality. ++ * @ecc_strength_ds: [INTERN] ECC correctability from the datasheet. ++ * Minimum amount of bit errors per @ecc_step_ds guaranteed ++ * to be correctable. If unknown, set to zero. ++ * @ecc_step_ds: [INTERN] ECC step required by the @ecc_strength_ds, ++ * also from the datasheet. It is the recommended ECC step ++ * size, if known; if unknown, set to zero. ++ * @ecc_mask: ++ * @ecc_uncorr: ++ * @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC. ++ * @ecclayout: [BOARDSPECIFIC] ECC layout control structure ++ * See the defines for further explanation. ++ * @bbt_options: [INTERN] bad block specific options. All options used ++ * here must come from bbm.h. By default, these options ++ * will be copied to the appropriate nand_bbt_descr's. ++ * @bbt: [INTERN] bad block table pointer ++ * @badblockpos: [INTERN] position of the bad block marker in the oob ++ * area. ++ * @bbt_td: [REPLACEABLE] bad block table descriptor for flash ++ * lookup. ++ * @bbt_md: [REPLACEABLE] bad block table mirror descriptor ++ * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial ++ * bad block scan. ++ * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is ++ * supported, 0 otherwise. ++ */ ++struct spi_nand_chip { ++ spinlock_t chip_lock; ++ char *name; ++ wait_queue_head_t wq; ++ u8 dev_id_len; ++ u8 dev_id[SPINAND_MAX_ID_LEN]; ++ flstate_t state; ++ struct spi_device *spi; ++ struct mtd_info *mtd; ++ ++ int (*reset)(struct spi_nand_chip *chip); ++ int (*read_id)(struct spi_nand_chip *chip, u8 *id); ++ int (*load_page)(struct spi_nand_chip *chip, unsigned int page_addr); ++ int (*read_cache)(struct spi_nand_chip *chip, unsigned int page_addr, ++ unsigned int page_offset, size_t length, u8 *read_buf); ++ int (*store_cache)(struct spi_nand_chip *chip, unsigned int page_addr, ++ unsigned int page_offset, size_t length, u8 *write_buf); ++ int (*write_page)(struct spi_nand_chip *chip, unsigned int page_addr); ++ int (*erase_block)(struct spi_nand_chip *chip, u32 page_addr); ++ int (*waitfunc)(struct spi_nand_chip *chip, u8 *status); ++ int (*write_enable)(struct spi_nand_chip *chip); ++ void (*get_ecc_status)(struct spi_nand_chip *chip, unsigned int status, ++ unsigned int *corrected, ++ unsigned int *ecc_errors); ++ int (*enable_ecc)(struct spi_nand_chip *chip); ++ int (*disable_ecc)(struct spi_nand_chip *chip); ++ int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); ++ int (*set_qe)(struct spi_nand_chip *chip); ++ ++ u8 *buf; ++ u8 *oobbuf; ++ int pagebuf; ++ u32 pagebuf_bitflips; ++ u64 size; ++ u32 block_size; ++ u16 page_size; ++ u16 page_spare_size; ++ u8 block_shift; ++ u8 page_shift; ++ u16 page_mask; ++ u32 options; ++ u16 ecc_strength_ds; ++ u16 ecc_step_ds; ++ u8 ecc_mask; ++ u8 ecc_uncorr; ++ u8 bits_per_cell; ++ struct nand_ecclayout *ecclayout; ++ u32 bbt_options; ++ u8 *bbt; ++ int badblockpos; ++ struct nand_bbt_descr *bbt_td; ++ struct nand_bbt_descr *bbt_md; ++ struct nand_bbt_descr *badblock_pattern; ++ struct spi_nand_onfi_params onfi_params; ++ u32 qe_addr; ++ u32 qe_flag; ++ u32 qe_mask; ++ u32 multi_wire_command_length; ++}; ++ ++ ++struct spi_nand_id_info{ ++#define SPI_NAND_ID_NO_DUMMY (0xff) ++ u8 id_addr; ++ u8 id_len; ++}; ++ ++struct spi_nand_flash { ++ char *name; ++ struct spi_nand_id_info id_info; ++ u8 dev_id[SPINAND_MAX_ID_LEN]; ++ u32 page_size; ++ u32 page_spare_size; ++ u32 pages_per_blk; ++ u32 blks_per_chip; ++ u32 options; ++ u8 ecc_mask; ++ u8 ecc_uncorr; ++ struct nand_ecclayout *ecc_layout; ++ u32 qe_addr; ++ u32 qe_flag; ++ u32 qe_mask; ++ u32 multi_wire_command_length; ++}; ++ ++struct spi_nand_cmd { ++ u8 cmd; ++ u32 n_addr; /* Number of address */ ++ u8 addr[3]; /* Reg Offset */ ++ u32 n_tx; /* Number of tx bytes */ ++ u8 *tx_buf; /* Tx buf */ ++ u8 tx_nbits; ++ u32 n_rx; /* Number of rx bytes */ ++ u8 *rx_buf; /* Rx buf */ ++ u8 rx_nbits; ++}; ++ ++#define SPI_NAND_INFO(nm, mid, did, pagesz, sparesz, pg_per_blk,\ ++ blk_per_chip, opts) \ ++ { .name = (nm), .mfr_id = (mid), .dev_id = (did),\ ++ .page_size = (pagesz), .page_spare_size = (sparesz),\ ++ .pages_per_blk = (pg_per_blk), .blks_per_chip = (blk_per_chip),\ ++ .options = (opts) } ++ ++#define SPINAND_NEED_PLANE_SELECT (1 << 0) ++ ++#define SPINAND_MFR_MICRON 0x2C ++#define SPINAND_MFR_GIGADEVICE 0xC8 ++ ++int spi_nand_send_cmd(struct spi_device *spi, struct spi_nand_cmd *cmd); ++int spi_nand_read_from_cache(struct spi_nand_chip *chip, ++ u32 page_addr, u32 column, size_t len, u8 *rbuf); ++int spi_nand_read_from_cache_snor_protocol(struct spi_nand_chip *chip, ++ u32 page_addr, u32 column, size_t len, u8 *rbuf); ++int spi_nand_scan_ident(struct mtd_info *mtd); ++int spi_nand_scan_tail(struct mtd_info *mtd); ++int spi_nand_scan_ident_release(struct mtd_info *mtd); ++int spi_nand_scan_tail_release(struct mtd_info *mtd); ++int spi_nand_release(struct mtd_info *mtd); ++int __spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo, ++ int allowbbt); ++int spi_nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); ++int spi_nand_default_bbt(struct mtd_info *mtd); ++int spi_nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); ++#endif /* __LINUX_MTD_SPI_NAND_H */ ++ +diff --git a/include/linux/pwm.h b/include/linux/pwm.h +index 7c775751..31a1e273 100644 +--- a/include/linux/pwm.h ++++ b/include/linux/pwm.h +@@ -1,8 +1,13 @@ + #ifndef __LINUX_PWM_H + #define __LINUX_PWM_H + ++#include <linux/err.h> ++#include <linux/of.h> ++ + struct pwm_device; ++struct seq_file; + ++#if defined(CONFIG_PWM) || defined(CONFIG_HAVE_PWM) + /* + * pwm_request - request a PWM device + */ +@@ -27,5 +32,251 @@ int pwm_enable(struct pwm_device *pwm); + * pwm_disable - stop a PWM output toggling + */ + void pwm_disable(struct pwm_device *pwm); ++#else ++static inline struct pwm_device *pwm_request(int pwm_id, const char *label) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline void pwm_free(struct pwm_device *pwm) ++{ ++} ++ ++static inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) ++{ ++ return -EINVAL; ++} ++ ++static inline int pwm_enable(struct pwm_device *pwm) ++{ ++ return -EINVAL; ++} ++ ++static inline void pwm_disable(struct pwm_device *pwm) ++{ ++} ++#endif ++ ++struct pwm_chip; ++ ++/** ++ * enum pwm_polarity - polarity of a PWM signal ++ * @PWM_POLARITY_NORMAL: a high signal for the duration of the duty- ++ * cycle, followed by a low signal for the remainder of the pulse ++ * period ++ * @PWM_POLARITY_INVERSED: a low signal for the duration of the duty- ++ * cycle, followed by a high signal for the remainder of the pulse ++ * period ++ */ ++enum pwm_polarity { ++ PWM_POLARITY_NORMAL, ++ PWM_POLARITY_INVERSED, ++}; ++ ++enum { ++ PWMF_REQUESTED = 1 << 0, ++ PWMF_ENABLED = 1 << 1, ++}; ++ ++struct pwm_device { ++ const char *label; ++ unsigned long flags; ++ unsigned int hwpwm; ++ unsigned int pwm; ++ struct pwm_chip *chip; ++ void *chip_data; ++ ++ unsigned int period; /* in nanoseconds */ ++}; ++ ++static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) ++{ ++ if (pwm) ++ pwm->period = period; ++} ++ ++static inline unsigned int pwm_get_period(struct pwm_device *pwm) ++{ ++ return pwm ? pwm->period : 0; ++} ++ ++/* ++ * pwm_set_polarity - configure the polarity of a PWM signal ++ */ ++int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity); ++ ++/** ++ * struct pwm_ops - PWM controller operations ++ * @request: optional hook for requesting a PWM ++ * @free: optional hook for freeing a PWM ++ * @config: configure duty cycles and period length for this PWM ++ * @set_polarity: configure the polarity of this PWM ++ * @enable: enable PWM output toggling ++ * @disable: disable PWM output toggling ++ * @dbg_show: optional routine to show contents in debugfs ++ * @owner: helps prevent removal of modules exporting active PWMs ++ */ ++struct pwm_ops { ++ int (*request)(struct pwm_chip *chip, ++ struct pwm_device *pwm); ++ void (*free)(struct pwm_chip *chip, ++ struct pwm_device *pwm); ++ int (*config)(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ int duty_ns, int period_ns); ++ int (*set_polarity)(struct pwm_chip *chip, ++ struct pwm_device *pwm, ++ enum pwm_polarity polarity); ++ int (*enable)(struct pwm_chip *chip, ++ struct pwm_device *pwm); ++ void (*disable)(struct pwm_chip *chip, ++ struct pwm_device *pwm); ++#ifdef CONFIG_DEBUG_FS ++ void (*dbg_show)(struct pwm_chip *chip, ++ struct seq_file *s); ++#endif ++ struct module *owner; ++}; ++ ++/** ++ * struct pwm_chip - abstract a PWM controller ++ * @dev: device providing the PWMs ++ * @list: list node for internal use ++ * @ops: callbacks for this PWM controller ++ * @base: number of first PWM controlled by this chip ++ * @npwm: number of PWMs controlled by this chip ++ * @pwms: array of PWM devices allocated by the framework ++ * @can_sleep: must be true if the .config(), .enable() or .disable() ++ * operations may sleep ++ */ ++struct pwm_chip { ++ struct device *dev; ++ struct list_head list; ++ const struct pwm_ops *ops; ++ int base; ++ unsigned int npwm; ++ ++ struct pwm_device *pwms; ++/* ++ struct pwm_device * (*of_xlate)(struct pwm_chip *pc, ++ const struct of_phandle_args *args); ++*/ ++ unsigned int of_pwm_n_cells; ++ bool can_sleep; ++}; ++ ++#if defined(CONFIG_PWM) ++int pwm_set_chip_data(struct pwm_device *pwm, void *data); ++void *pwm_get_chip_data(struct pwm_device *pwm); ++ ++int pwmchip_add(struct pwm_chip *chip); ++int pwmchip_remove(struct pwm_chip *chip); ++struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, ++ unsigned int index, ++ const char *label); ++/* ++struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc, ++ const struct of_phandle_args *args); ++*/ ++struct pwm_device *pwm_get(struct device *dev, const char *con_id); ++struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id); ++void pwm_put(struct pwm_device *pwm); ++ ++struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id); ++struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, ++ const char *con_id); ++void devm_pwm_put(struct device *dev, struct pwm_device *pwm); ++ ++bool pwm_can_sleep(struct pwm_device *pwm); ++#else ++static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data) ++{ ++ return -EINVAL; ++} ++ ++static inline void *pwm_get_chip_data(struct pwm_device *pwm) ++{ ++ return NULL; ++} ++ ++static inline int pwmchip_add(struct pwm_chip *chip) ++{ ++ return -EINVAL; ++} ++ ++static inline int pwmchip_remove(struct pwm_chip *chip) ++{ ++ return -EINVAL; ++} ++ ++static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, ++ unsigned int index, ++ const char *label) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline struct pwm_device *pwm_get(struct device *dev, ++ const char *consumer) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline struct pwm_device *of_pwm_get(struct device_node *np, ++ const char *con_id) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline void pwm_put(struct pwm_device *pwm) ++{ ++} ++ ++static inline struct pwm_device *devm_pwm_get(struct device *dev, ++ const char *consumer) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline struct pwm_device *devm_of_pwm_get(struct device *dev, ++ struct device_node *np, ++ const char *con_id) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ ++static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm) ++{ ++} ++ ++static inline bool pwm_can_sleep(struct pwm_device *pwm) ++{ ++ return false; ++} ++#endif ++ ++struct pwm_lookup { ++ struct list_head list; ++ const char *provider; ++ unsigned int index; ++ const char *dev_id; ++ const char *con_id; ++}; ++ ++#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id) \ ++ { \ ++ .provider = _provider, \ ++ .index = _index, \ ++ .dev_id = _dev_id, \ ++ .con_id = _con_id, \ ++ } ++ ++#if defined(CONFIG_PWM) ++void pwm_add_table(struct pwm_lookup *table, size_t num); ++#else ++static inline void pwm_add_table(struct pwm_lookup *table, size_t num) ++{ ++} ++#endif + + #endif /* __LINUX_PWM_H */ +diff --git a/include/linux/rtc.h b/include/linux/rtc.h +index 93f4d035..75bae8a9 100644 +--- a/include/linux/rtc.h ++++ b/include/linux/rtc.h +@@ -18,15 +18,15 @@ + */ + + struct rtc_time { +- int tm_sec; +- int tm_min; +- int tm_hour; +- int tm_mday; +- int tm_mon; +- int tm_year; +- int tm_wday; +- int tm_yday; +- int tm_isdst; ++ int tm_sec; //0~59 ++ int tm_min; //0~59 ++ int tm_hour; //0~23 ++ int tm_mday; //1~31 ++ int tm_mon; //0~11 ++ int tm_year; //offset from 1900 ++ int tm_wday; //0~6 sunday:0 ++ int tm_yday; //offset from 1.1 0~365 ++ int tm_isdst; //??? + }; + + /* +diff --git a/drivers/spi/dw_spi.h b/include/linux/spi/dw_spi.h +similarity index 87% +rename from drivers/spi/dw_spi.h +rename to include/linux/spi/dw_spi.h +index 7a5e78d2..3bf6c7f2 100644 +--- a/drivers/spi/dw_spi.h ++++ b/include/linux/spi/dw_spi.h +@@ -4,6 +4,27 @@ + #include <linux/io.h> + #include <linux/scatterlist.h> + ++ ++#define YU_ADD_ISR_TASKLET ++ ++#ifdef CONFIG_JLINK_DEBUG ++# define DEBUG_DW_SPI0 ++ ++# ifdef DEBUG_DW_SPI0 ++# define DW_SPI0_REG_BASE (0xf0500000) ++ #define DW_SPI0_CS_REG (0xf0300000) ++ ++# else ++ #define DW_SPI_REG_BASE (0xfe400000) ++ #define DW_SPI0_CS_REG (0xfe500000) ++# endif ++ ++#else ++# define DW_SPI0_CS_REG (0xfe500000) ++#endif ++ ++ ++ + /* Bit fields in CTRLR0 */ + #define SPI_DFS_OFFSET 0 + +@@ -138,7 +159,7 @@ struct dw_spi { + u32 dma_width; + int cs_change; + irqreturn_t (*transfer_handler)(struct dw_spi *dws); +- void (*cs_control)(u32 command); ++ void (*cs_control)(struct spi_device *spi, u32 command); + + /* Dma info */ + int dma_inited; +@@ -152,9 +173,18 @@ struct dw_spi { + struct dw_spi_dma_ops *dma_ops; + void *dma_priv; /* platform relate info */ + struct pci_dev *dmac; ++ void * dma_rx_dummy; ++ void * dma_tx_dummy; + + /* Bus interface info */ + void *priv; ++ ++ ++#ifdef YU_ADD_ISR_TASKLET ++ struct tasklet_struct yu_add_isr_tasklet; ++ ++#endif ++ + #ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; + #endif +@@ -169,6 +199,10 @@ struct dw_spi { + #define dw_writew(dw, name, val) \ + __raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name)) + ++ ++#define yu_write(val,add) __raw_writel((val), (add)) ++ ++ + static inline void spi_enable_chip(struct dw_spi *dws, int enable) + { + dw_writel(dws, ssienr, (enable ? 1 : 0)); +@@ -179,17 +213,19 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div) + dw_writel(dws, baudr, div); + } + +-static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) ++static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi) + { ++ u16 cs = spi->chip_select; + if (cs > dws->num_cs) + return; + + if (dws->cs_control) +- dws->cs_control(1); ++ dws->cs_control(spi, 1); + + dw_writel(dws, ser, 1 << cs); + } + ++ + /* Disable IRQ bits */ + static inline void spi_mask_intr(struct dw_spi *dws, u32 mask) + { +@@ -218,7 +254,8 @@ struct dw_spi_chip { + u8 poll_mode; /* 0 for contoller polling mode */ + u8 type; /* SPI/SSP/Micrwire */ + u8 enable_dma; +- void (*cs_control)(u32 command); ++ void *cs_control; ++// void (*cs_control)(u32 command); + }; + + extern int dw_spi_add_host(struct dw_spi *dws); +diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h +old mode 100644 +new mode 100755 +index bb4f5fbb..01cc915e +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -29,6 +29,22 @@ + */ + extern struct bus_type spi_bus_type; + ++ ++ ++struct spi_master; ++struct _spi_advanced_info { ++ unsigned int ctl_wire_support; ++ /*add spi wire init func point...*/ ++ /*may be null*/ ++ int (*multi_wire_func_init)(struct spi_master *p_master); ++ /*change spi bus to which wire func..*/ ++ #define SPI_DATA_DIR_IN (0xaa) ++ #define SPI_DATA_DIR_OUT (0xbb) ++ #define SPI_DATA_DIR_DUOLEX (0xcc) ++ void (*change_to_1_wire)(struct spi_master *p_master); ++ void (*change_to_2_wire)(struct spi_master *p_master, unsigned int dir); ++ void (*change_to_4_wire)(struct spi_master *p_master, unsigned int dir); ++}; + /** + * struct spi_device - Master side proxy for an SPI slave device + * @dev: Driver model representation of the device. +@@ -66,6 +82,7 @@ extern struct bus_type spi_bus_type; + * variant with slightly different functionality; another might be + * information about how this particular board wires the chip's pins. + */ ++ + struct spi_device { + struct device dev; + struct spi_master *master; +@@ -90,6 +107,15 @@ struct spi_device { + void *controller_data; + char modalias[SPI_NAME_SIZE]; + ++ ++ /*add spi multi wire support..*/ ++#define ONE_WIRE_SUPPORT (1<<0) ++#define DUAL_WIRE_SUPPORT (1<<1) ++#define QUAD_WIRE_SUPPORT (1<<2) ++#define MULTI_WIRE_SUPPORT (1<<8) ++ u32 dev_open_multi_wire_flag; ++ /*add the wire support info of controller...*/ ++ struct _spi_advanced_info *p_ctl_multi_wire_info; + /* + * likely need more hooks for more protocol options affecting how + * the controller talks to each chip, like: +@@ -177,7 +203,7 @@ struct spi_driver { + int (*probe)(struct spi_device *spi); + int (*remove)(struct spi_device *spi); + void (*shutdown)(struct spi_device *spi); +- int (*suspend)(struct spi_device *spi, pm_message_t mesg); ++ int (*suspend)(struct spi_device *spi, pm_message_t mesg); + int (*resume)(struct spi_device *spi); + struct device_driver driver; + }; +@@ -307,6 +333,7 @@ struct spi_master { + + /* called on release() to free memory provided by spi_master */ + void (*cleanup)(struct spi_device *spi); ++ struct _spi_advanced_info ctl_multi_wire_info; + }; + + static inline void *spi_master_get_devdata(struct spi_master *master) +@@ -332,6 +359,32 @@ static inline void spi_master_put(struct spi_master *master) + put_device(&master->dev); + } + ++static inline struct ++_spi_advanced_info *spi_master_get_advanced_data(struct spi_master *master) ++{ ++ return &master->ctl_multi_wire_info; ++} ++ ++static inline void ++spi_dev_set_multi_data(struct spi_master *master, struct spi_device *spi_dev) ++{ ++ u32 ctl_flag; ++ u32 dev_flag; ++ ctl_flag = master->ctl_multi_wire_info.ctl_wire_support; ++ dev_flag = spi_dev->dev_open_multi_wire_flag; ++ /*if slave and ctl all support multi wire... ++ then slave open the lower support*/ ++ if ((ctl_flag & MULTI_WIRE_SUPPORT) ++ && (dev_flag & MULTI_WIRE_SUPPORT)) ++ spi_dev->dev_open_multi_wire_flag = ctl_flag & dev_flag; ++ else { ++ spi_dev->dev_open_multi_wire_flag = 0; ++ return; ++ } ++ spi_dev->p_ctl_multi_wire_info = ++ &master->ctl_multi_wire_info; ++} ++ + + /* the spi driver core manages memory for the spi_master classdev */ + extern struct spi_master * +@@ -436,15 +489,23 @@ struct spi_transfer { + const void *tx_buf; + void *rx_buf; + unsigned len; +- + dma_addr_t tx_dma; + dma_addr_t rx_dma; +- + unsigned cs_change:1; + u8 bits_per_word; + u16 delay_usecs; + u32 speed_hz; +- ++ /*add this transfer use mode.. ++#define ONE_WIRE_SUPPORT (1<<0) ++#define DUAL_WIRE_SUPPORT (1<<1) ++#define QUAD_WIRE_SUPPORT (1<<2) ++ */ ++ u32 xfer_wire_mode; ++ /* ++#define SPI_DATA_DIR_IN (0xaa) ++#define SPI_DATA_DIR_OUT (0xbb) ++ */ ++ u32 xfer_dir; + struct list_head transfer_list; + }; + +@@ -530,7 +591,8 @@ spi_transfer_del(struct spi_transfer *t) + * structures so long as you don't free them while they're in use. + */ + +-static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags) ++static inline struct spi_message ++*spi_message_alloc(unsigned ntrans, gfp_t flags) + { + struct spi_message *m; + +diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h +index 4ebaf082..dab0e66b 100644 +--- a/include/linux/usb/ch11.h ++++ b/include/linux/usb/ch11.h +@@ -18,6 +18,16 @@ + #define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) + #define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) + ++#define HUB_CHAR_LPSM 0x0003 /* Logical Power Switching Mode mask */ ++#define HUB_CHAR_COMMON_LPSM 0x0000 /* All ports power control at once */ ++#define HUB_CHAR_INDV_PORT_LPSM 0x0001 /* per-port power control */ ++#define HUB_CHAR_NO_LPSM 0x0002 /* no power switching */ ++#define HUB_CHAR_COMPOUND 0x0004 /* hub is part of a compound device */ ++ ++ ++ ++ ++ + /* + * Hub class requests + * See USB 2.0 spec Table 11-16 +@@ -54,6 +64,7 @@ + #define USB_PORT_FEAT_L1 5 /* L1 suspend */ + #define USB_PORT_FEAT_POWER 8 + #define USB_PORT_FEAT_LOWSPEED 9 /* Should never be used */ ++#define USB_PORT_FEAT_HIGHSPEED 10 + #define USB_PORT_FEAT_C_CONNECTION 16 + #define USB_PORT_FEAT_C_ENABLE 17 + #define USB_PORT_FEAT_C_SUSPEND 18 +@@ -168,6 +179,7 @@ struct usb_port_status { + #define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ + #define HUB_CHAR_COMPOUND 0x0004 /* D2 */ + #define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ ++#define HUB_CHAR_INDV_PORT_OCPM 0x0008 /* per-port Over-current reporting */ + #define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ + #define HUB_CHAR_PORTIND 0x0080 /* D7 */ + +diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h +index dd1571db..6c180f78 100644 +--- a/include/linux/usb/gadget.h ++++ b/include/linux/usb/gadget.h +@@ -16,7 +16,7 @@ + #define __LINUX_USB_GADGET_H + + #include <linux/slab.h> +- ++#include <linux/usb/ch9.h> + struct usb_ep; + + /** +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index 0097136b..7396dba9 100644 +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -19,10 +19,10 @@ + #ifndef __USB_CORE_HCD_H + #define __USB_CORE_HCD_H + +-#ifdef __KERNEL__ ++//#ifdef __KERNEL__ + + #include <linux/rwsem.h> +- ++#include <linux/usb.h> + #define MAX_TOPO_LEVEL 6 + + /* This file contains declarations of usbcore internals that are mostly +@@ -505,6 +505,11 @@ extern void usb_ep0_reinit(struct usb_device *); + /* class requests from USB 3.0 hub spec, table 10-5 */ + #define SetHubDepth (0x3000 | HUB_SET_DEPTH) + #define GetPortErrorCount (0x8000 | HUB_GET_PORT_ERR_COUNT) ++/*-------------------------------------------------------------------------*/ ++ ++/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ ++/* bleech -- resurfaced in 2.4.11 or 2.4.12 */ ++#define bitmap DeviceRemovable + + /* + * Generic bandwidth allocation constants/support +@@ -669,6 +674,6 @@ extern struct rw_semaphore ehci_cf_port_reset_rwsem; + #define USB_EHCI_LOADED 2 + extern unsigned long usb_hcds_loaded; + +-#endif /* __KERNEL__ */ ++//#endif /* __KERNEL__ */ + + #endif /* __USB_CORE_HCD_H */ +diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h +index d87f44f5..9e480472 100644 +--- a/include/linux/usb/otg.h ++++ b/include/linux/usb/otg.h +@@ -11,6 +11,12 @@ + + #include <linux/notifier.h> + ++enum usb_dr_mode { ++ USB_DR_MODE_UNKNOWN, ++ USB_DR_MODE_HOST, ++ USB_DR_MODE_PERIPHERAL, ++ USB_DR_MODE_OTG, ++}; + /* OTG defines lots of enumeration states before device reset */ + enum usb_otg_state { + OTG_STATE_UNDEFINED = 0, +diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h +index 605b0aa8..3f1c2dee 100644 +--- a/include/linux/usb/usbnet.h ++++ b/include/linux/usb/usbnet.h +@@ -33,6 +33,8 @@ struct usbnet { + wait_queue_head_t *wait; + struct mutex phy_mutex; + unsigned char suspend_count; ++ unsigned char pkt_cnt, pkt_err; ++ unsigned short rx_qlen, tx_qlen; + + /* i/o info: pipes etc */ + unsigned in, out; +@@ -69,6 +71,7 @@ struct usbnet { + # define EVENT_DEV_WAKING 6 + # define EVENT_DEV_ASLEEP 7 + # define EVENT_DEV_OPEN 8 ++# define EVENT_RX_KILL 10 + }; + + static inline struct usb_driver *driver_of(struct usb_interface *intf) +@@ -150,6 +153,10 @@ struct driver_info { + int in; /* rx endpoint */ + int out; /* tx endpoint */ + ++ /* add driver private info by zhangy ++ 2018-10-31 to fix asix rx fixup lost data */ ++ void *driver_priv; ++ + unsigned long data; /* Misc driver specific data */ + }; + +@@ -191,7 +198,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *); + enum skb_state { + illegal = 0, + tx_start, tx_done, +- rx_start, rx_done, rx_cleanup ++ rx_start, rx_done, rx_cleanup, ++ unlink_start + }; + + struct skb_data { /* skb->cb is one of these */ +diff --git a/include/linux/usb/video.h b/include/linux/usb/video.h +index 3b3b95e0..eb3eb212 100644 +--- a/include/linux/usb/video.h ++++ b/include/linux/usb/video.h +@@ -564,5 +564,75 @@ struct UVC_FRAME_MJPEG(n) { \ + __u32 dwFrameInterval[n]; \ + } __attribute__ ((packed)) + ++/* Frame Based Payload - 3.1.1. Frame Based Format Descriptor */ ++struct uvc_format_frameBased { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ __u8 bFormatIndex; ++ __u8 bNumFrameDescriptors; ++ __u8 guidFormat[16]; ++ __u8 bBitsPerPixel; ++ __u8 bDefaultFrameIndex; ++ __u8 bAspectRatioX; ++ __u8 bAspectRatioY; ++ __u8 bmInterfaceFlags; ++ __u8 bCopyProtect; ++ __u8 bVariableSize; ++} __attribute__((__packed__)); ++ ++#define UVC_DT_FORMAT_FRAMEBASED_SIZE 28 ++ ++/* Frame Based Payload - 3.1.2. Frame Based Frame Descriptor */ ++/* Replace dwFrameInterval[] with these tree lines ++ * when bFrameIntervalType = 0, which means continuous frame interval ++ * __u32 dwMinFrameInterval; ++ * __u32 dwMaxFrameInterval; ++ * __u32 dwFrameIntervalStep; ++ */ ++struct uvc_frame_frameBased { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ __u8 bFrameIndex; ++ __u8 bmCapabilities; ++ __u16 wWidth; ++ __u16 wHeight; ++ __u32 dwMinBitRate; ++ __u32 dwMaxBitRate; ++ __u32 dwDefaultFrameInterval; ++ __u8 bFrameIntervalType; ++ __u32 dwBytesPerLine; ++ __u32 dwFrameInterval[]; ++} __attribute__((__packed__)); ++ ++#define UVC_DT_FRAME_FRAMEBASED_SIZE(n) (26+4*(n)) ++ ++#define UVC_FRAME_FRAMEBASED(n) \ ++ uvc_frame_frameBased_##n ++ ++/* Replace dwFrameInterval[] with these tree lines ++ * when bFrameIntervalType = 0, which means continuous frame interval ++ * __u32 dwMinFrameInterval; ++ * __u32 dwMaxFrameInterval; ++ * __u32 dwFrameIntervalStep; ++ */ ++#define DECLARE_UVC_FRAME_FRAMEBASED(n) \ ++struct UVC_FRAME_FRAMEBASED(n) { \ ++ __u8 bLength; \ ++ __u8 bDescriptorType; \ ++ __u8 bDescriptorSubType; \ ++ __u8 bFrameIndex; \ ++ __u8 bmCapabilities; \ ++ __u16 wWidth; \ ++ __u16 wHeight; \ ++ __u32 dwMinBitRate; \ ++ __u32 dwMaxBitRate; \ ++ __u32 dwDefaultFrameInterval; \ ++ __u8 bFrameIntervalType; \ ++ __u32 dwBytesPerLine; \ ++ __u32 dwFrameInterval[n]; \ ++} __packed ++ + #endif /* __LINUX_USB_VIDEO_H */ + +diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h +index 8a4c309d..74b64cd1 100644 +--- a/include/linux/videodev2.h ++++ b/include/linux/videodev2.h +@@ -377,6 +377,7 @@ struct v4l2_pix_format { + #define V4L2_PIX_FMT_JPEG v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG */ + #define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */ + #define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 */ ++#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 */ + + /* Vendor-specific formats */ + #define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */ +@@ -1923,8 +1924,8 @@ struct v4l2_dbg_chip_ident { + /* Experimental, meant for debugging, testing and internal use. + Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined. + You must be root to use these ioctls. Never use these in applications! */ +-#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) +-#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) ++#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) ++#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) + + /* Experimental, meant for debugging, testing and internal use. + Never use this ioctl in applications! */ +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 396e8fc8..6ea76103 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -426,7 +426,8 @@ struct station_parameters { + * @STATION_INFO_RX_BITRATE: @rxrate fields are filled + * @STATION_INFO_BSS_PARAM: @bss_param filled + * @STATION_INFO_CONNECTED_TIME: @connected_time filled +- */ ++ * @STATION_INFO_ASSOC_REQ_IES: @assos_req_ies filled ++*/ + enum station_info_flags { + STATION_INFO_INACTIVE_TIME = 1<<0, + STATION_INFO_RX_BYTES = 1<<1, +@@ -443,8 +444,10 @@ enum station_info_flags { + STATION_INFO_RX_DROP_MISC = 1<<12, + STATION_INFO_SIGNAL_AVG = 1<<13, + STATION_INFO_RX_BITRATE = 1<<14, +- STATION_INFO_BSS_PARAM = 1<<15, +- STATION_INFO_CONNECTED_TIME = 1<<16 ++ STATION_INFO_BSS_PARAM = 1<<15, ++ STATION_INFO_CONNECTED_TIME = 1<<16, ++ STATION_INFO_ASSOC_REQ_IES = 1<<17 ++ + }; + + /** +@@ -536,6 +539,11 @@ struct sta_bss_parameters { + * This number should increase every time the list of stations + * changes, i.e. when a station is added or removed, so that + * userspace can tell whether it got a consistent snapshot. ++ * @assoc_req_ies: IEs from (Re)Association Request. ++ * This is used only when in AP mode with drivers that do not use ++ * user space MLME/SME implementation. The information is provided for ++ * the cfg80211_new_sta() calls to notify user space of the IEs. ++ * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. + */ + struct station_info { + u32 filled; +@@ -558,6 +566,9 @@ struct station_info { + struct sta_bss_parameters bss_param; + + int generation; ++ ++ const u8 *assoc_req_ies; ++ size_t assoc_req_ies_len; + }; + + /** +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index dd373c8e..dcb37b28 100644 +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -1,4 +1,11 @@ + ++config TEST_BOOT_TIME ++ bool "Set GPIO level for measuring boot time." ++ default n ++ help ++ This option will set GPIO 4 to level high at the beginning of ++ kernel decompressing stage. ++ + config PRINTK_TIME + bool "Show timing information on printks" + depends on PRINTK +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 46cbd28f..ef70bf94 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -185,10 +185,16 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, + prefetchw(skb); + + size = SKB_DATA_ALIGN(size); +- data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), +- gfp_mask, node); ++ size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); ++ data = kmalloc_node_track_caller(size, gfp_mask, node); + if (!data) + goto nodata; ++ ++ /* kmalloc(size) might give us more room than requested. ++ * Put skb_shared_info exactly at the end of allocated zone, ++ * to allow max possible filling before reallocation. ++ */ ++ size = SKB_WITH_OVERHEAD(ksize(data)); + prefetchw(data + size); + + /* +diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig +index 1f1ef70f..15a57575 100644 +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -1,5 +1,5 @@ + config WIRELESS_EXT +- bool ++ def_bool y + + config WEXT_CORE + def_bool y +@@ -14,7 +14,7 @@ config WEXT_SPY + bool + + config WEXT_PRIV +- bool ++ def_bool y + + config CFG80211 + tristate "cfg80211 - wireless configuration API" +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 1ac9443b..6496472e 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -2209,6 +2209,11 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, + } + nla_nest_end(msg, sinfoattr); + ++ if (sinfo->assoc_req_ies) ++ { ++ NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, ++ sinfo->assoc_req_ies); ++ } + return genlmsg_end(msg, hdr); + + nla_put_failure: +@@ -2236,6 +2241,7 @@ static int nl80211_dump_station(struct sk_buff *skb, + } + + while (1) { ++ memset(&sinfo, 0, sizeof(sinfo)); + err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, + mac_addr, &sinfo); + if (err == -ENOENT) +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 379574c3..7b0add2b 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -1759,6 +1759,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) + static void restore_regulatory_settings(bool reset_user) + { + char alpha2[2]; ++ char world_alpha2[2]; + struct reg_beacon *reg_beacon, *btmp; + struct regulatory_request *reg_request, *tmp; + LIST_HEAD(tmp_reg_req_list); +@@ -1809,11 +1810,13 @@ static void restore_regulatory_settings(bool reset_user) + + /* First restore to the basic regulatory settings */ + cfg80211_regdomain = cfg80211_world_regdom; ++ world_alpha2[0] = cfg80211_regdomain->alpha2[0]; ++ world_alpha2[1] = cfg80211_regdomain->alpha2[1]; + + mutex_unlock(®_mutex); + mutex_unlock(&cfg80211_mutex); + +- regulatory_hint_core(cfg80211_regdomain->alpha2); ++ regulatory_hint_core(world_alpha2); + + /* + * This restores the ieee80211_regdom module parameter +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index 413c5369..ba3f0c98 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -1694,7 +1694,7 @@ static void read_symbols(char *modname) + if (version) + maybe_frob_rcs_version(modname, version, info.modinfo, + version - (char *)info.hdr); +- if (version || (all_versions && !is_vmlinux(modname))) ++ if ((all_versions && !is_vmlinux(modname))) + get_src_version(modname, mod->srcversion, + sizeof(mod->srcversion)-1); + +diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig +index 885683a3..4eb638bd 100644 +--- a/sound/arm/Kconfig ++++ b/sound/arm/Kconfig +@@ -27,7 +27,26 @@ config SND_PXA2XX_LIB + + config SND_PXA2XX_LIB_AC97 + bool ++ ++config SND_FH_LIB ++ tristate ++ select SND_FH_CODEC if SND_FH_LIB_AC97 + ++config SND_FH_LIB_AC97 ++ bool ++config SND_FH_PCM ++ bool ++config SND_FH_AC97 ++ tristate "AC97 driver for the Intel FH chip" ++ ++ select SND_FH_PCM ++ select SND_AC97_CODEC ++ select SND_FH_LIB ++ select SND_FH_LIB_AC97 ++ help ++ Say Y or M if you want to support any AC97 codec attached to ++ the fh81 AC97 interface. ++ + config SND_PXA2XX_AC97 + tristate "AC97 driver for the Intel PXA2xx chip" + depends on ARCH_PXA +diff --git a/sound/arm/Makefile b/sound/arm/Makefile +index 8c0c851d..72cd341a 100644 +--- a/sound/arm/Makefile ++++ b/sound/arm/Makefile +@@ -7,10 +7,16 @@ snd-aaci-objs := aaci.o + + obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o + snd-pxa2xx-pcm-objs := pxa2xx-pcm.o ++obj-$(CONFIG_SND_FH_PCM) += snd-fh-pcm.o ++snd-fh-pcm-objs := fh_pcm.o + + obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o ++obj-$(CONFIG_SND_FH_LIB) += snd-fh-lib.o + snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o ++snd-fh-lib-y := fh-pcm-lib.o + snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o +- ++snd-fh-lib-$(CONFIG_SND_FH_LIB_AC97) += fh-ac97-lib.o + obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o ++obj-$(CONFIG_SND_FH_AC97) += snd-fh-ac97.o + snd-pxa2xx-ac97-objs := pxa2xx-ac97.o ++snd-fh-ac97-objs := fh-ac97.o +\ No newline at end of file +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 98175a09..cd9b5329 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -119,6 +119,11 @@ config SND_SOC_AC97_CODEC + tristate + select SND_AC97_CODEC + ++config SND_SOC_FH_CODEC ++ tristate ++ select SND_FH_CODEC ++ select SND_AC97_CODEC ++ + config SND_SOC_AD1836 + tristate + +@@ -222,6 +227,9 @@ config SND_SOC_STAC9766 + config SND_SOC_TLV320AIC23 + tristate + ++config SND_SOC_FSH0LS029AA ++ tristate ++ + config SND_SOC_TLV320AIC26 + tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE + depends on SPI +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index fd855840..116edc8a 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -1,5 +1,6 @@ + snd-soc-88pm860x-objs := 88pm860x-codec.o + snd-soc-ac97-objs := ac97.o ++snd-soc-fh-objs := fh.o + snd-soc-ad1836-objs := ad1836.o + snd-soc-ad193x-objs := ad193x.o + snd-soc-ad1980-objs := ad1980.o +@@ -30,6 +31,7 @@ snd-soc-spdif-objs := spdif_transciever.o + snd-soc-ssm2602-objs := ssm2602.o + snd-soc-stac9766-objs := stac9766.o + snd-soc-tlv320aic23-objs := tlv320aic23.o ++snd-soc-fsh0ls029aa-objs := fsh0ls029aa.o + snd-soc-tlv320aic26-objs := tlv320aic26.o + snd-soc-tlv320aic3x-objs := tlv320aic3x.o + snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +@@ -91,6 +93,7 @@ snd-soc-wm9090-objs := wm9090.o + + obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o + obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o ++obj-$(CONFIG_SND_SOC_FH_CODEC) += snd-soc-fh.o + obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o + obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o + obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o +@@ -122,6 +125,7 @@ obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o + obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o + obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o ++obj-$(CONFIG_SND_SOC_FSH0LS029AA) += snd-soc-fsh0ls029aa.o + obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o + obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o + obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o +diff --git a/sound/soc/codecs/fsh0ls029aa.c b/sound/soc/codecs/fsh0ls029aa.c +new file mode 100644 +index 00000000..10dec074 +--- /dev/null ++++ b/sound/soc/codecs/fsh0ls029aa.c +@@ -0,0 +1,99 @@ ++/* ++ * ad73311.c -- ALSA Soc AD73311 codec support ++ * ++ * Copyright: Analog Device Inc. ++ * Author: Cliff Cai <cliff.cai@analog.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/device.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/ac97_codec.h> ++#include <sound/initval.h> ++#include <sound/soc.h> ++ ++#include "fsh0ls029aa.h" ++static int ak4104_set_dai_fmt(){ ++ ++ return 0; ++} ++static int ak4104_hw_params(){ ++ ++ return 0; ++} ++static int ak4104_sys_params(){ ++ ++ return 0; ++} ++static struct snd_soc_dai_ops ak4101_dai_ops = { ++ .hw_params = ak4104_hw_params, ++ .set_fmt = ak4104_set_dai_fmt, ++ .set_sysclk=ak4104_sys_params, ++}; ++ ++static struct snd_soc_dai_driver ad73311_dai = { ++ .name = "fh-acodec-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, }, ++ .ops=&ak4101_dai_ops, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_ad73311; ++ ++static int ad73311_probe(struct platform_device *pdev) ++{ ++// printk("ad73311 probe \n"); ++ return snd_soc_register_codec(&pdev->dev, ++ &soc_codec_dev_ad73311, &ad73311_dai, 1); ++} ++ ++static int __devexit ad73311_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver ad73311_codec_driver = { ++ .driver = { ++ .name = "fh-acodec", ++ .owner = THIS_MODULE, ++ }, ++ ++ .probe = ad73311_probe, ++ .remove = __devexit_p(ad73311_remove), ++}; ++ ++static int __init ad73311_init(void) ++{ ++ return platform_driver_register(&ad73311_codec_driver); ++} ++module_init(ad73311_init); ++ ++static void __exit ad73311_exit(void) ++{ ++ platform_driver_unregister(&ad73311_codec_driver); ++} ++module_exit(ad73311_exit); ++ ++MODULE_DESCRIPTION("ASoC ad73311 driver"); ++MODULE_AUTHOR("Cliff Cai "); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/fsh0ls029aa.h b/sound/soc/codecs/fsh0ls029aa.h +new file mode 100644 +index 00000000..4b353eef +--- /dev/null ++++ b/sound/soc/codecs/fsh0ls029aa.h +@@ -0,0 +1,88 @@ ++/* ++ * File: sound/soc/codec/ad73311.h ++ * Based on: ++ * Author: Cliff Cai <cliff.cai@analog.com> ++ * ++ * Created: Thur Sep 25, 2008 ++ * Description: definitions for AD73311 registers ++ * ++ * ++ * Modified: ++ * Copyright 2006 Analog Devices Inc. ++ * ++ * Bugs: Enter bugs at http://blackfin.uclinux.org/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see the file COPYING, or write ++ * to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __AD73311_H__ ++#define __AD73311_H__ ++ ++#define AD_CONTROL 0x8000 ++#define AD_DATA 0x0000 ++#define AD_READ 0x4000 ++#define AD_WRITE 0x0000 ++ ++/* Control register A */ ++#define CTRL_REG_A (0 << 8) ++ ++#define REGA_MODE_PRO 0x00 ++#define REGA_MODE_DATA 0x01 ++#define REGA_MODE_MIXED 0x03 ++#define REGA_DLB 0x04 ++#define REGA_SLB 0x08 ++#define REGA_DEVC(x) ((x & 0x7) << 4) ++#define REGA_RESET 0x80 ++ ++/* Control register B */ ++#define CTRL_REG_B (1 << 8) ++ ++#define REGB_DIRATE(x) (x & 0x3) ++#define REGB_SCDIV(x) ((x & 0x3) << 2) ++#define REGB_MCDIV(x) ((x & 0x7) << 4) ++#define REGB_CEE (1 << 7) ++ ++/* Control register C */ ++#define CTRL_REG_C (2 << 8) ++ ++#define REGC_PUDEV (1 << 0) ++#define REGC_PUADC (1 << 3) ++#define REGC_PUDAC (1 << 4) ++#define REGC_PUREF (1 << 5) ++#define REGC_REFUSE (1 << 6) ++ ++/* Control register D */ ++#define CTRL_REG_D (3 << 8) ++ ++#define REGD_IGS(x) (x & 0x7) ++#define REGD_RMOD (1 << 3) ++#define REGD_OGS(x) ((x & 0x7) << 4) ++#define REGD_MUTE (1 << 7) ++ ++/* Control register E */ ++#define CTRL_REG_E (4 << 8) ++ ++#define REGE_DA(x) (x & 0x1f) ++#define REGE_IBYP (1 << 5) ++ ++/* Control register F */ ++#define CTRL_REG_F (5 << 8) ++ ++#define REGF_SEEN (1 << 5) ++#define REGF_INV (1 << 6) ++#define REGF_ALB (1 << 7) ++ ++#endif +diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig +new file mode 100644 +index 00000000..ae37a7a6 +--- /dev/null ++++ b/sound/soc/dwc/Kconfig +@@ -0,0 +1,54 @@ ++config SND_FULLHAN_SOC ++ tristate "SoC Audio for the FULLHAN System-on-Chip" ++ help ++ Say Y or M if you want to add support for codecs attached to ++ the ATMEL SSC interface. You will also need ++ to select the audio interfaces to support below. ++ ++config SND_FULLHAN_SOC_SSC ++ tristate ++ depends on SND_FULLHAN_SOC ++ help ++ Say Y or M if you want to add support for codecs the ++ ATMEL SSC interface. You will also needs to select the individual ++ machine drivers to support below. ++ ++config SND_FULLHAN_SOC_SAM9G20_WM8731 ++ tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" ++ depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \ ++ AT91_PROGRAMMABLE_CLOCKS ++ select SND_FULLHAN_SOC_SSC ++ select SND_SOC_WM8731 ++ help ++ Say Y if you want to add support for SoC audio on WM8731-based ++ AT91sam9g20 evaluation board. ++ ++config SND_FULLHAN_SOC_PLAYPAQ ++ tristate "SoC Audio support for PlayPaq with WM8510" ++ depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS ++ select SND_ATMEL_SOC_SSC ++ select SND_SOC_WM8510 ++ help ++ Say Y or M here if you want to add support for SoC audio ++ on the LRS PlayPaq. ++config SND_FH_SOC_I2S ++ tristate ++ ++ ++config SND_FULLHAN_SOC_PLAYPAQ_SLAVE ++ bool "Run CODEC on PlayPaq in slave mode" ++ depends on SND_FULLHAN_SOC_PLAYPAQ ++ default n ++ help ++ Say Y if you want to run with the AT32 SSC generating the BCLK ++ and FRAME signals on the PlayPaq. Unless you want to play ++ with the AT32 as the SSC master, you probably want to say N here, ++ as this will give you better sound quality. ++ ++config SND_FULLHAN_SOC_FH ++ tristate "SoC Audio support for fullhan-81 board" ++ select SND_FULLHAN_SOC_SSC ++ select SND_SOC_FSH0LS029AA ++ select SND_FH_SOC_I2S ++ help ++ Say Y here to support sound on fh81 board. +diff --git a/sound/soc/dwc/Makefile b/sound/soc/dwc/Makefile +new file mode 100644 +index 00000000..96f58598 +--- /dev/null ++++ b/sound/soc/dwc/Makefile +@@ -0,0 +1,20 @@ ++# AT91 Platform Support ++snd-soc-fullhan-pcm-objs := fullhan-pcm.o ++#snd-soc-fullhan_ssc_dai-objs := fh_i2s_dai.o ++ ++obj-$(CONFIG_SND_FULLHAN_SOC) += snd-soc-fullhan-pcm.o ++#obj-$(CONFIG_SND_FULLHAN_SOC_SSC) += snd-soc-fullhan_ssc_dai.o ++ ++# AT91 Machine Support ++snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o ++ ++# AT32 Machine Support ++snd-soc-playpaq-objs := playpaq_wm8510.o ++snd-soc-fh-objs := fh.o dma.o ++obj-$(CONFIG_SND_FH_SOC_I2S) += snd-soc-fh-i2s.o ++snd-soc-fh-i2s-objs := fh_i2s.o ++ ++ ++obj-$(CONFIG_SND_FULLHAN_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o ++obj-$(CONFIG_SND_FULLHAN_SOC_PLAYPAQ) += snd-soc-playpaq.o ++obj-$(CONFIG_SND_FULLHAN_SOC_FH) += snd-soc-fh.o +diff --git a/sound/soc/dwc/dma.c b/sound/soc/dwc/dma.c +new file mode 100644 +index 00000000..4dd098ce +--- /dev/null ++++ b/sound/soc/dwc/dma.c +@@ -0,0 +1,636 @@ ++ ++/******************************************* ++ * ++ * new drive add by xuww ++ * ++ * ++ * **********************************/ ++/** ++* @file ++* @brief ++* @version ++* @author xuww ++* @date ++* @note ++* ++* ++* @copy ++* ++* �˴���Ϊ�Ϻ������������˾��Ŀ���룬�κ��˼���˾δ����ɲ��ø��ƴ����������� ++* ����˾�������Ŀ����˾����һ����Ȩ���� ++* ++* <h1><center>© COPYRIGHT 2013 fullhan</center></h1> ++*/ ++/* Includes ------------------------------------------------------------------*/ ++#include "dma.h" ++#include <mach/fh_predefined.h> ++ ++#define MAX_DMA_CHANS (4) ++ ++/* Private typedef -----------------------------------------------------------*/ ++/* Private define ------------------------------------------------------------*/ ++/* Private macro -------------------------------------------------------------*/ ++/* Private variables ---------------------------------------------------------*/ ++/* Private function prototypes -----------------------------------------------*/ ++/* Private functions ---------------------------------------------------------*/ ++/******************************************************************************* ++* Function Name : Dma_GetChanStatus ++* Description : get the channel status ++* Input : nChanID :channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++int Dma_GetChanStatus( int nChanID ) ++{ ++ return (int)(GET_REG( REG_DMAC_CHAN_EN ) & ( 1 << nChanID )); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableChan ++* Description : enable channel ++* Input : nChanID :channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableChan( int nChanID ) ++{ ++ int nMask = (1 << (nChanID + 8)) | ( 1 << nChanID ); ++ ++ SET_REG_M( REG_DMAC_CHAN_EN, nMask, nMask ); ++} ++/******************************************************************************* ++* Function Name : Dma_DisableChan ++* Description : disable channel ++* Input : nChanID :channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_DisableChan( int nChanID ) ++{ ++ int nMask = ( 1 << ( nChanID + 8 ) ); ++ ++ SET_REG_M( REG_DMAC_CHAN_EN, nMask, (nMask + (1 << nChanID)) ); ++ while( GET_REG( REG_DMAC_CHAN_EN) & (1 << nChanID) ); ++} ++/******************************************************************************* ++* Function Name : Dma_ClearIsrBit ++* Description : clear the interruput bit ++* Input : iChan :channel ID nMask :unchange bit ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_ClearIsrBit( int iChan, int nMask ) ++{ ++ if( nMask & DMA_INTT_TXR) ++ SET_REG( REG_DMAC_INTCLR_TFR, 1 << iChan ); ++ if( nMask & DMA_INTT_BLOCK) ++ SET_REG( REG_DMAC_INTCLR_BLK, 1 << iChan ); ++ if( nMask & DMA_INTT_SOURCE ) ++ SET_REG( REG_DMAC_INTCLR_SRCTXR, 1 << iChan ); ++ if( nMask & DMA_INTT_DEST ) ++ SET_REG( REG_DMAC_INTCLR_DSTTXR, 1 << iChan ); ++ if( nMask & DMA_INTT_ERR ) ++ SET_REG( REG_DMAC_INTCLR_ERR, 1 << iChan ); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableIsrBit ++* Description : enable intruput bit ++* Input : iChan :channel ID nMask:unchange bit ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableIsrBit( int iChan, int nMask ) ++{ ++ int nEnable = (1 << (iChan + 8)) | (1 << iChan); ++ ++ if( nMask & DMA_INTT_TXR) ++ SET_REG_M( REG_DMAC_INTMSK_TFR, nEnable, nEnable ); ++ if( nMask & DMA_INTT_BLOCK) ++ SET_REG_M( REG_DMAC_INTMSK_BLK, nEnable, nEnable ); ++ if( nMask & DMA_INTT_SOURCE) ++ SET_REG_M( REG_DMAC_INTMSK_SRCTXR, nEnable, nEnable ); ++ if( nMask & DMA_INTT_DEST) ++ SET_REG_M( REG_DMAC_INTMSK_DSTTXR, nEnable, nEnable ); ++ if( nMask & DMA_INTT_ERR) ++ SET_REG_M( REG_DMAC_INTMSK_ERR, nEnable, nEnable ); ++ ++ SET_REG_M( REG_DMAC_CTXi(iChan), 1, 1 ); // Enable isr. ++} ++/******************************************************************************* ++* Function Name : Dma_DisableIsrBit ++* Description : disbale interruput ++* Input : iChan:channel ID nMask:unchange bit ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++ ++void Dma_DisableIsrBit( int iChan, int nMask ) ++{ ++ int nEnable = (1 << (iChan + 8)) | (1 << iChan); ++ ++ if( nMask & DMA_INTT_TXR) ++ SET_REG_M( REG_DMAC_INTCLR_TFR, 0, nEnable ); ++ if( nMask & DMA_INTT_BLOCK) ++ SET_REG_M( REG_DMAC_INTCLR_BLK, 0, nEnable ); ++ if( nMask & DMA_INTT_SOURCE) ++ SET_REG_M( REG_DMAC_INTCLR_SRCTXR, 0, nEnable ); ++ if( nMask & DMA_INTT_DEST) ++ SET_REG_M( REG_DMAC_INTCLR_DSTTXR, 0, nEnable ); ++ if( nMask & DMA_INTT_ERR) ++ SET_REG_M( REG_DMAC_INTCLR_ERR, 0, nEnable ); ++} ++/******************************************************************************* ++* Function Name : Dma_QueryISRStatus ++* Description : not use ++* Input : None ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++int Dma_QueryISRStatus( int iChan ) ++{ ++ return 0; ++} ++/******************************************************************************* ++* Function Name : Dma_ClearTfrDone ++* Description : clear tfr Done bit ++* Input : iChan:channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_ClearTfrDone(int iChan ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan) + 4, 0, 1 << 12 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetTxrSize ++* Description : set txr size ++* Input : iChan:channel ID nByes:size ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetTxrSize( int iChan, int nBytes ) ++{ ++ if( nBytes > 4095 ) ++ nBytes = 4095; ++ SET_REG_M( REG_DMAC_CTXi(iChan) + 4, (unsigned long long)nBytes, 0xfff ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcWidth ++* Description : set source width ++* Input : iChan:channel ID nWidth :fifo width ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcWidth( int iChan, int nWidth ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), nWidth << 4, 0x70 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstWidth ++* Description : set destination ++* Input : iChan:channel ID nWidth :fifo width ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstWidth( int iChan, int nWidth ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), nWidth << 1, 0xe ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcSize ++* Description : set source size ++* Input : iChan :channel ID nSize : fifo depth ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcSize( int iChan, int nSize ) // burst size ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), nSize << 14, 0x1c000 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstSize ++* Description : set destination size ++* Input : iChan :channel ID nSize : fifo depth ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstSize( int iChan, int nSize ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), nSize << 11, 0x3800 ); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableSrcBlkChain ++* Description : enable source block chain ++* Input : iChan:channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableSrcBlkChain(int iChan ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), 1 << 28, 1 << 28 ); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableDstBlkChain ++* Description : enable destinationg block chain ++* Input : iChan:channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableDstBlkChain(int iChan ) ++{ ++ SET_REG_M( REG_DMAC_CTXi(iChan), 1 << 27, 1 << 27 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetTxrType ++* Description : set txr mode ++* Input : iChan:channel ID nMode :transation mode ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetTxrType( int iChan, int nMode ) ++{ ++ if( nMode >= 0 && nMode < DMA_TTFC_INVALID ) ++ { ++ SET_REG_M( REG_DMAC_CTXi(iChan), nMode << 20, 0x7 << 20 ); ++ } ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstIncDirection ++* Description : set source address increment decrement or not change ++* Input : iChan:channel ID nDir :0 :increment 1:decrement other :not change ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcIncDirection( int iChan, int nDir ) ++{ ++ if( nDir == DMA_DIR_INC ) ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0, 0x600 ); ++ else if( nDir == DMA_DIR_DEC ) ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0x200, 0x200 ); ++ else ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0x400, 0x400 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstIncDirection ++* Description : set destination address increment decrement or not change ++* Input : iChan:channel ID nDir :0 :increment 1:decrement other :not change ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstIncDirection( int iChan, int nDir ) ++{ ++ if( nDir == DMA_DIR_INC ) ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0, 0x180 ); ++ else if( nDir == DMA_DIR_DEC ) ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0x80, 0x080 ); ++ else ++ SET_REG_M( REG_DMAC_CTXi(iChan), 0x100, 0x100 ); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableGather ++* Description : set enable gather ++* Input : iChan :channel ID bEnable :0 disable 1:enable ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableGather(int iChan, int bEnable ) ++{ ++ int v; ++ if( bEnable ) v = 1; ++ else v = 0; ++ SET_REG_M( REG_DMAC_CTXi(iChan), v << 17, 1 << 17 ); ++} ++/******************************************************************************* ++* Function Name : Dma_EnableScatter ++* Description : set enable scatter ++* Input : iChan :channel ID bEnable :0 disable 1:enable ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_EnableScatter(int iChan, int bEnable ) ++{ ++ int v = 0; ++ if( bEnable ) v = 1; ++ SET_REG_M( REG_DMAC_CTXi(iChan), v << 18, 1 << 18 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcHsMode ++* Description : set the source handshaking mode ++* Input : iChan:channe ID nMode:0 hardware 1:software ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcHsMode( int iChan, int nMode ) ++{ ++ nMode &= 0x1; ++ SET_REG_M( REG_DMAC_CFGi(iChan), nMode << 11, 1 << 11 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstHsMode ++* Description : set the destination handshaking mode ++* Input : iChan:channe ID nMode:0 hardware 1:software ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstHsMode( int iChan, int nMode ) ++{ ++ nMode &= 1; ++ SET_REG_M( REG_DMAC_CFGi(iChan), nMode << 10, 1 << 10 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetFifoMode ++* Description : set fifo request transation mode ++* Input : iChan :channel nMode :1:half fifo or 0:enough one burst ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetFifoMode( int iChan, int nMode ) ++{ ++ nMode &= 1; ++ SET_REG_M( REG_DMAC_CFGi(iChan) + 4, nMode << 1, 1 << 1 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetFlowCtrl ++* Description : set dam flow control :source or destionation ++* Input : iChan :channel ID ctrl:0: source 1:destinationg ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetFlowCtrl( int iChan, int ctrl ) ++{ ++ ctrl &= 1; ++ SET_REG_M( REG_DMAC_CFGi(iChan) + 4, ctrl, 1 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcAutoload ++* Description : set destination auto load the init address ++* Input : iChan :channel ID bEnable :enable or disable ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcAutoload(int iChan, int bEnable ) ++{ ++ int v = bEnable ? 1 : 0; ++ SET_REG_M( REG_DMAC_CFGi(iChan), v << 30, 1 << 30 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstAutoload ++* Description : set destination auto load the init address ++* Input : iChan :channel ID bEnable :enable or disable ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstAutoload(int iChan, int bEnable ) ++{ ++ int v = bEnable ? 1 : 0; ++ SET_REG_M( REG_DMAC_CFGi(iChan), v << 31, 1 << 31 ); ++} ++/******************************************************************************* ++* Function Name : Write_Regm ++* Description : write the reg mask the unchange bit ++* Input : addr: reg address value :reg value mask :unchange bit ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++static void Write_Regm( unsigned int addr, unsigned int value, unsigned int mask ) ++{ ++ unsigned int tmp = GET_REG(addr); ++ tmp &= ~mask; ++ value &= mask; ++ tmp |= value; ++ SET_REG(addr, tmp); ++} ++/******************************************************************************* ++* Function Name : Dma_SetMaxBurst ++* Description : set the max burst size ++* Input : iChan:channel ID nSize : burst size ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetMaxBurst( int iChan, int nSize ) ++{ ++ if( nSize > 1023 ) ++ nSize = 1023; ++ Write_Regm( REG_DMAC_CFGi(iChan), (nSize << 20), 0x3ff00000 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcHsPol ++* Description : set the source handshaking polatity ++* Input : iChan:channel ID nPol: polarity high or low ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcHsPol( int iChan, int nPol ) ++{ ++ nPol &= 1; ++ SET_REG_M( REG_DMAC_CFGi(iChan), nPol << 19, 1 << 19 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstHsPol ++* Description : set the destination handshaking polatity ++* Input : iChan:channel ID nPol: polarity high or low ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstHsPol( int iChan, int nPol ) ++{ ++ nPol &= 1; ++ SET_REG_M( REG_DMAC_CFGi(iChan), nPol << 18, 1 << 18 ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetLinkEntry ++* Description : enbale the link list ++* Input : iChan:channel ID nAddr :link list address ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetLinkEntry( int iChan, unsigned int nAddr ) ++{ ++ nAddr &= 0xfffffffc; ++ // force to use AHB Master 0, for this is the only AHB Master. ++ SET_REG_M( REG_DMAC_LLPi(iChan), nAddr, 0xffffffff ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcAddress ++* Description : set source address ++* Input : iChan:channel ID nAddr:destination address ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcAddress( int iChan, unsigned int nAddr ) ++{ ++ SET_REG_M( REG_DMAC_SARi(iChan), nAddr, 0xffffffff ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstAddress ++* Description : set destination address ++* Input : iChan:channel ID nAddr:destination address ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstAddress( int iChan, unsigned int nAddr ) ++{ ++ SET_REG_M( REG_DMAC_DARi(iChan), nAddr, 0xffffffff ); ++} ++/******************************************************************************* ++* Function Name : Dma_SetSrcPe ++* Description : select the hardshaking interface ++* Input : iChan:channel ID nPer:handshaking interface ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetSrcPer( int iChan, unsigned int nPer ) ++{ ++ if( nPer < DMA_HSP_INVALID ) ++ { ++ SET_REG_M( REG_DMAC_CFGi(iChan) + 4, nPer << 7, 0xf << 7 ); ++ } ++} ++/******************************************************************************* ++* Function Name : Dma_SetDstPer ++* Description : select the hardshaking interface ++* Input : iChan:channel ID nPer:handshaking interface ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_SetDstPer( int iChan, unsigned int nPer ) ++{ ++ if( nPer < DMA_HSP_INVALID ) ++ { ++ SET_REG_M( REG_DMAC_CFGi(iChan) + 4, nPer << 11, 0xf << 11 ); ++ } ++} ++/******************************************************************************* ++* Function Name : Dma_GetIsrChan ++* Description : get the status of dam interruput ++* Input : iChan :channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++unsigned int Dma_GetIsrChan(unsigned int nMask) ++{ ++ if( nMask & DMA_INTT_TXR ) ++ return GET_REG(REG_DMAC_INTSTAT_TFR); ++ if( nMask & DMA_INTT_BLOCK ) ++ return GET_REG(REG_DMAC_INTSTAT_BLK); ++ if( nMask & DMA_INTT_SOURCE ) ++ return GET_REG(REG_DMAC_INTSTAT_SRCTXR); ++ if( nMask & DMA_INTT_DEST ) ++ return GET_REG(REG_DMAC_INTSTAT_DSTTXR); ++ if( nMask & DMA_INTT_ERR ) ++ return GET_REG(REG_DMAC_INTSTAT_ERR); ++ ++ return 0; ++} ++/******************************************************************************* ++* Function Name : Dma_StartSrctfr ++* Description : dma source start transaction ++* Input : iChan:channel ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_StartSrctfr( int iChan ) ++{ ++ int nMask = 0x101 << (iChan); ++ ++ SET_REG( REG_DMAC_REQSRC, 0x101 ); ++ SET_REG( REG_DMAC_SGLREQSRC, 0x101 ); ++} ++/******************************************************************************* ++* Function Name : Dma_StartDsttfr ++* Description : destination transaction request ++* Input : iChan: channel ID ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_StartDsttfr( int iChan ) ++{ ++ int nMask = 0x101 << (iChan); ++ SET_REG( REG_DMAC_REQDST, nMask ); ++ SET_REG( REG_DMAC_SGLREQDST, nMask ); ++} ++/******************************************************************************* ++* Function Name : fh_dma_init ++* Description : dma init ++* Input : None ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void fh_dma_init() ++{ ++ Dma_Init(); ++} ++/******************************************************************************* ++* Function Name : Dma_Init ++* Description : dma init ++* Input : None ++* Output : None ++* Return : None ++* ++ *******************************************************************************/ ++void Dma_Init() ++{ ++ int i; ++ SET_REG( REG_DMAC_CFG_REG, 1 ); ++ ++ for( i = 0; i < MAX_DMA_CHANS; i ++ ) ++ { ++ Dma_DisableChan(i); ++ Dma_ClearIsrBit( i, DMA_INTT_TXR | DMA_INTT_BLOCK | DMA_INTT_SOURCE | DMA_INTT_DEST | DMA_INTT_ERR ); ++ Dma_ClearTfrDone(i); ++ Dma_SetTxrType(i, DMA_TTFC_M2P_DMAC); ++ Dma_SetSrcWidth( i, DMA_TXR_32BITS ); ++ Dma_SetSrcSize( i, DMA_BURST_8 ); ++ Dma_SetDstWidth( i, DMA_TXR_8BITS ); ++ Dma_SetDstSize( i, DMA_BURST_8 ); ++ Dma_SetSrcHsPol( i, DMA_HSPOL_ACTHIGH ); ++ Dma_SetDstHsPol( i, DMA_HSPOL_ACTHIGH ); ++ Dma_SetSrcIncDirection( i, DMA_DIR_INC ); ++ Dma_SetDstIncDirection( i, DMA_DIR_UNCHG ); ++ Dma_SetSrcHsMode( i, DMA_HSMODE_SOFTWARE ); ++ Dma_SetDstHsMode( i, DMA_HSMODE_SOFTWARE ); ++ Dma_SetMaxBurst( i, 0 ); ++ Dma_SetFifoMode( i, 0 ); ++ Dma_SetLinkEntry( i, 0 ); ++ Dma_EnableGather( i, 0 ); ++ Dma_EnableScatter( i, 0 ); ++ } ++} +diff --git a/sound/soc/dwc/dma.h b/sound/soc/dwc/dma.h +new file mode 100644 +index 00000000..81fccc3f +--- /dev/null ++++ b/sound/soc/dwc/dma.h +@@ -0,0 +1,212 @@ ++ ++/********************************* ++ * ++ * new drive add by xuww ++ * ++ * ****************************/ ++#ifndef DMA__H ++#define DMA__H ++ ++ ++#if(1) ++enum ++{ ++ DMA_INTT_TXR = 1, ++ DMA_INTT_BLOCK = 2, ++ DMA_INTT_SOURCE = 4, ++ DMA_INTT_DEST = 8, ++ DMA_INTT_ERR = 16 ++}; ++ ++enum ++{ ++ DMA_TXR_8BITS = 0, ++ DMA_TXR_16BITS = 1, ++ DMA_TXR_32BITS = 2, ++ DMA_TXR_64BITS = 3, ++ DMA_TXR_128BITS = 4, ++ DMA_TXR_256BITS = 5, ++ DMA_TXR_INVALID = 6 ++}; ++ ++enum ++{ ++ DMA_BURST_1 = 0, ++ DMA_BURST_4 = 1, ++ DMA_BURST_8 = 2, ++ DMA_BURST_16 = 3, ++ DMA_BURST_32 = 4, ++ DMA_BURST_64 = 5, ++ DMA_BURST_128 = 6, ++ DMA_BURST_256 = 7, ++ DMA_BURST_INVALID = 8 ++}; ++ ++enum ++{ ++ DMA_TTFC_M2M_DMAC, ++ DMA_TTFC_M2P_DMAC, ++ DMA_TTFC_P2M_DMAC, ++ DMA_TTFC_P2P_DMAC, ++ DMA_TTFC_P2M_PFR, ++ DMA_TTFC_P2P_PSRC, ++ DMA_TTFC_M2P_PFR, ++ DMA_TTFC_P2P_PDST, ++ DMA_TTFC_INVALID ++}; ++ ++enum ++{ ++ DMA_DIR_INC, ++ DMA_DIR_DEC, ++ DMA_DIR_UNCHG, ++ DMA_DIR_INVALID ++}; ++ ++enum ++{ ++ DMA_HSPOL_ACTHIGH, ++ DMA_HSPOL_ACTLOW ++}; ++ ++enum ++{ ++ DMA_HSMODE_HARDWARE = 0, ++ DMA_HSMODE_SOFTWARE = 1 ++}; ++ ++enum ++{ ++ DMA_HSP_SDC, ++ DMA_HSP_AIFRX, ++ DMA_HSP_AIFTX, ++ DMA_HSP_TAE, ++ DMA_HSP_I2SRX, ++ DMA_HSP_I2STX, ++ DMA_HSP_SPI0RX, ++ DMA_HSP_SPI0TX, ++ DMA_HSP_SPI1RX, ++ DMA_HSP_SPI1TX, ++ DMA_HSP_UART0RX, ++ DMA_HSP_UART0TX, ++ DMA_HSP_UART1RX, ++ DMA_HSP_UART1TX, ++ DMA_HSP_SPI2RX, ++ DMA_HSP_SPI2TX, ++ DMA_HSP_INVALID ++}; ++#endif ++#define DMAC_REG_BASE (0xfe600000) ++#define REG_DMAC_SAR_OFFSET (0x0) ++#define REG_DMAC_DAR_OFFSET (0x8) ++#define REG_DMAC_LLP_OFFSET (0x10) ++#define REG_DMAC_CTX_OFFSET (0x18) ++#define REG_DMAC_SSTAT_OFFSET (0x20) ++#define REG_DMAC_DSTAT_OFFSET (0x28) ++#define REG_DMAC_SSTATAR_OFFSET (0x30) ++#define REG_DMAC_DSTATAR_OFFSET (0x38) ++#define REG_DMAC_CFG_OFFSET (0x40) ++#define REG_DMAC_SGR_OFFSET (0x48) ++#define REG_DMAC_DSR_OFFSET (0x50) ++#define REG_DMAC_SARi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_SAR_OFFSET) ++#define REG_DMAC_DARi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_DAR_OFFSET) ++#define REG_DMAC_LLPi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_LLP_OFFSET) ++#define REG_DMAC_CTXi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_CTX_OFFSET) ++#define REG_DMAC_SSTATi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_SSTAT_OFFSET) ++#define REG_DMAC_DSTATi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_DSTAT_OFFSET) ++#define REG_DMAC_SSTATARi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_SSTATAR_OFFSET) ++#define REG_DMAC_DSTATARi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_DSTATAR_OFFSET) ++#define REG_DMAC_CFGi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_CFG_OFFSET) ++#define REG_DMAC_SGRi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_SGR_OFFSET) ++#define REG_DMAC_DSRi(n) (DMAC_REG_BASE + (n) * 0x58 + REG_DMAC_DSR_OFFSETR) ++ ++#define REG_DMAC_INTRAWTFR (DMAC_REG_BASE + 0x2c0) ++#define REG_DMAC_INTRAWBLK (DMAC_REG_BASE + 0x2c8) ++#define REG_DMAC_INTRAWSRCTXR (DMAC_REG_BASE + 0x2d0) ++#define REG_DMAC_INTRAWDSTTXR (DMAC_REG_BASE + 0x2d8) ++#define REG_DMAC_INTRAWERR (DMAC_REG_BASE + 0x2e0) ++#define REG_DMAC_INTSTAT_TFR (DMAC_REG_BASE + 0x2e8) ++#define REG_DMAC_INTSTAT_BLK (DMAC_REG_BASE + 0x2f0) ++#define REG_DMAC_INTSTAT_SRCTXR (DMAC_REG_BASE + 0x2f8) ++#define REG_DMAC_INTSTAT_DSTTXR (DMAC_REG_BASE + 0x300) ++#define REG_DMAC_INTSTAT_ERR (DMAC_REG_BASE + 0x308) ++#define REG_DMAC_INTMSK_TFR (DMAC_REG_BASE + 0x310) ++#define REG_DMAC_INTMSK_BLK (DMAC_REG_BASE + 0x318) ++#define REG_DMAC_INTMSK_SRCTXR (DMAC_REG_BASE + 0x320) ++#define REG_DMAC_INTMSK_DSTTXR (DMAC_REG_BASE + 0x328) ++#define REG_DMAC_INTMSK_ERR (DMAC_REG_BASE + 0x330) ++#define REG_DMAC_INTCLR_TFR (DMAC_REG_BASE + 0x338) ++#define REG_DMAC_INTCLR_BLK (DMAC_REG_BASE + 0x340) ++#define REG_DMAC_INTCLR_SRCTXR (DMAC_REG_BASE + 0x348) ++#define REG_DMAC_INTCLR_DSTTXR (DMAC_REG_BASE + 0x350) ++#define REG_DMAC_INTCLR_ERR (DMAC_REG_BASE + 0x358) ++#define REG_DMAC_INT_STATUS_ALL (DMAC_REG_BASE + 0x360) ++ ++#define REG_DMAC_REQSRC (DMAC_REG_BASE + 0x368) ++#define REG_DMAC_REQDST (DMAC_REG_BASE + 0x370) ++#define REG_DMAC_SGLREQSRC (DMAC_REG_BASE + 0x378) ++#define REG_DMAC_SGLREQDST (DMAC_REG_BASE + 0x380) ++#define REG_DMAC_LSTSRC (DMAC_REG_BASE + 0x388) ++#define REG_DMAC_LSTDST (DMAC_REG_BASE + 0x390) ++#define REG_DMAC_CFG_REG (DMAC_REG_BASE + 0x398) ++#define REG_DMAC_CHAN_EN (DMAC_REG_BASE + 0x3a0) ++#define REG_DMAC_IDREG (DMAC_REG_BASE + 0x3a8) ++#define REG_DMAC_TESTREG (DMAC_REG_BASE + 0x3b0) ++#define REG_DMAC_COMPARAMS_6 (DMAC_REG_BASE + 0x3c8) ++#define REG_DMAC_COMPARAMS_5 (DMAC_REG_BASE + 0x3d0) ++#define REG_DMAC_COMPARAMS_4 (DMAC_REG_BASE + 0x3d8) ++#define REG_DMAC_COMPARAMS_3 (DMAC_REG_BASE + 0x3e0) ++#define REG_DMAC_COMPARAMS_2 (DMAC_REG_BASE + 0x3e8) ++#define REG_DMAC_COMPARAMS_1 (DMAC_REG_BASE + 0x3f0) ++#define REG_DMAC_COMP_IDREG (DMAC_REG_BASE + 0x3f8) ++int Dma_GetChanStatus( int nChanID ); ++void Dma_EnableChan( int nChanID ); ++void Dma_DisableChan( int nChanID ); ++ ++void Dma_ClearIsrBit( int iChan, int nMask ); ++void Dma_EnableIsrBit( int iChan, int nMask ); ++void Dma_DisableIsrBit( int iChan, int nMask ); ++unsigned int Dma_GetIsrChan(unsigned int nMask); ++int Dma_QueryIsrStatus( ); ++ ++void Dma_ClearTfrDone(int iChan); ++void Dma_SetTxrSize( int iChan, int nBytes ); ++void Dma_SetSrcWidth( int iChan, int nWidth ); ++void Dma_SetDstWidth( int iChan, int nWidth ); ++void Dma_SetSrcSize( int iChan, int nSize ); // burst size ++void Dma_SetDstSize( int iChan, int nSize ); ++void Dma_EnableSrcBlkChain(int iChan); ++void Dma_EnableDstBlkChain(int iChan); ++ ++void Dma_SetTxrType( int iChan, int nMode ); ++void Dma_SetSrcIncDirection( int iChan, int nDir ); ++void Dma_SetDstIncDirection( int iChan, int nDir ); ++ ++void Dma_EnableGather( int iChan, int bEnable ); ++void Dma_EnableScatter( int iChan, int bEnable); ++ ++void Dma_SetSrcHsMode( int iChan, int nMode ); ++void Dma_SetDstHsMode( int iChan, int nMode ); ++ ++void Dma_SetFifoMode( int iChan, int nMode ); ++void Dma_SetFlowCtrl( int iChan, int ctrl ); ++void Dma_SetSrcAutoload(int iChan, int bEnable ); ++void Dma_SetDstAutoload(int iChan, int bEnable ); ++void Dma_SetMaxBurst( int iChan, int nSize ); ++ ++void Dma_SetSrcHsPol( int iChan, int nPol ); ++void Dma_SetDstHsPol( int iChan, int nPol ); ++ ++void Dma_SetLinkEntry( int iChan, unsigned int nAddr ); ++void Dma_SetSrcAddress( int iChan, unsigned int nAddr ); ++void Dma_SetDstAddress( int iChan, unsigned int nAddr ); ++void Dma_SetSrcPer( int iChan, unsigned int nPer ); ++void Dma_SetDstPer( int iChan, unsigned int nPer ); ++ ++void Dma_StartSrctfr( int iChan ); ++void Dma_StartDsttfr( int iChan ); ++ ++void Dma_Init(); ++ ++#endif ++ +diff --git a/sound/soc/dwc/fh.c b/sound/soc/dwc/fh.c +new file mode 100644 +index 00000000..31b8639c +--- /dev/null ++++ b/sound/soc/dwc/fh.c +@@ -0,0 +1,240 @@ ++/* ++ * ASoC driver for Stretch s6105 IP camera platform ++ * ++ * Author: Daniel Gloeckner, <dg@emlix.com> ++ * Copyright: (C) 2009 emlix GmbH <info@emlix.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/timer.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/i2c.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/soc.h> ++ ++ ++ ++#include "fullhan-pcm.h" ++#include "fh_i2s.h" ++ ++#define S6105_CAM_CODEC_CLOCK 12288000 ++ ++static int s6105_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ int ret = 0; ++ ++ /* set codec DAI configuration */ ++ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_CBM_CFM); ++ if (ret < 0) ++ return ret; ++ /* set cpu DAI configuration */ ++ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | ++ SND_SOC_DAIFMT_NB_NF); ++ if (ret < 0) ++ return ret; ++ ++ /* set the codec system clock */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK, ++ SND_SOC_CLOCK_OUT); ++ if (ret < 0) ++ return ret; ++ return 0; ++} ++ ++static struct snd_soc_ops s6105_ops = { ++ .hw_params = s6105_hw_params, ++}; ++ ++/* s6105 machine dapm widgets */ ++static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { ++ SND_SOC_DAPM_LINE("Audio Out Differential", NULL), ++ SND_SOC_DAPM_LINE("Audio Out Stereo", NULL), ++ SND_SOC_DAPM_LINE("Audio In", NULL), ++}; ++ ++/* s6105 machine audio_mapnections to the codec pins */ ++static const struct snd_soc_dapm_route audio_map[] = { ++ /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */ ++ {"Audio Out Differential", NULL, "HPLOUT"}, ++ {"Audio Out Differential", NULL, "HPLCOM"}, ++ {"Audio Out Stereo", NULL, "HPLOUT"}, ++ {"Audio Out Stereo", NULL, "HPROUT"}, ++ ++ /* Audio In connected to LINE1L, LINE1R */ ++ {"LINE1L", NULL, "Audio In"}, ++ {"LINE1R", NULL, "Audio In"}, ++}; ++ ++static int output_type_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = 2; ++ if (uinfo->value.enumerated.item) { ++ uinfo->value.enumerated.item = 1; ++ strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT"); ++ } else { ++ strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM"); ++ } ++ return 0; ++} ++ ++static int output_type_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ ucontrol->value.enumerated.item[0] = kcontrol->private_value; ++ return 0; ++} ++ ++static int output_type_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_codec *codec = kcontrol->private_data; ++ struct snd_soc_dapm_context *dapm = &codec->dapm; ++ unsigned int val = (ucontrol->value.enumerated.item[0] != 0); ++ char *differential = "Audio Out Differential"; ++ char *stereo = "Audio Out Stereo"; ++ ++ if (kcontrol->private_value == val) ++ return 0; ++ kcontrol->private_value = val; ++ snd_soc_dapm_disable_pin(dapm, val ? differential : stereo); ++ snd_soc_dapm_sync(dapm); ++ snd_soc_dapm_enable_pin(dapm, val ? stereo : differential); ++ snd_soc_dapm_sync(dapm); ++ ++ return 1; ++} ++ ++static const struct snd_kcontrol_new audio_out_mux = { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Master Output Mux", ++ .index = 0, ++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, ++ .info = output_type_info, ++ .get = output_type_get, ++ .put = output_type_put, ++ .private_value = 1 /* default to stereo */ ++}; ++ ++/* Logic for a aic3x as connected on the s6105 ip camera ref design */ ++static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dapm_context *dapm = &codec->dapm; ++ ++ /* Add s6105 specific widgets */ ++ snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, ++ ARRAY_SIZE(aic3x_dapm_widgets)); ++ ++ /* Set up s6105 specific audio path audio_map */ ++ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); ++ ++ /* not present */ ++ snd_soc_dapm_nc_pin(dapm, "MONO_LOUT"); ++ snd_soc_dapm_nc_pin(dapm, "LINE2L"); ++ snd_soc_dapm_nc_pin(dapm, "LINE2R"); ++ ++ /* not connected */ ++ snd_soc_dapm_nc_pin(dapm, "MIC3L"); /* LINE2L on this chip */ ++ snd_soc_dapm_nc_pin(dapm, "MIC3R"); /* LINE2R on this chip */ ++ snd_soc_dapm_nc_pin(dapm, "LLOUT"); ++ snd_soc_dapm_nc_pin(dapm, "RLOUT"); ++ snd_soc_dapm_nc_pin(dapm, "HPRCOM"); ++ ++ /* always connected */ ++ snd_soc_dapm_enable_pin(dapm, "Audio In"); ++ ++ /* must correspond to audio_out_mux.private_value initializer */ ++ snd_soc_dapm_disable_pin(dapm, "Audio Out Differential"); ++ snd_soc_dapm_sync(dapm); ++ snd_soc_dapm_enable_pin(dapm, "Audio Out Stereo"); ++ ++ snd_soc_dapm_sync(dapm); ++ ++ snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); ++ ++ return 0; ++} ++ ++/* s6105 digital audio interface glue - connects codec <--> CPU */ ++static struct snd_soc_dai_link s6105_dai = { ++ .name = "TLV320AIC31", ++ .stream_name = "AIC31", ++ .cpu_dai_name = "s6000-i2s.0", ++ .codec_dai_name = "fh-acodec-hifi", ++ .platform_name = "fh-pcm-audio", ++ .codec_name = "fh-acodec", ++ .init = s6105_aic3x_init, ++ .ops = &s6105_ops, ++}; ++ ++/* s6105 audio machine driver */ ++static struct snd_soc_card snd_soc_card_s6105 = { ++ .name = "Stretch IP Camera", ++ .dai_link = &s6105_dai, ++ .num_links = 1, ++}; ++ ++static struct s6000_snd_platform_data __initdata s6105_snd_data = { ++ .wide = 0, ++ .channel_in = 0, ++ .channel_out = 1, ++ .lines_in = 1, ++ .lines_out = 1, ++ .same_rate = 1, ++}; ++ ++static struct platform_device *s6105_snd_device; ++ ++/* temporary i2c device creation until this can be moved into the machine ++ * support file. ++*/ ++static struct i2c_board_info i2c_device[] = { ++ { I2C_BOARD_INFO("tlv320aic33", 0x18), } ++}; ++ ++static int __init s6105_init(void) ++{ ++ int ret; ++ i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device)); ++ ++ s6105_snd_device = platform_device_alloc("soc-audio", -1); ++ if (!s6105_snd_device) ++ return -ENOMEM; ++ ++ platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105); ++ platform_device_add_data(s6105_snd_device, &s6105_snd_data, ++ sizeof(s6105_snd_data)); ++ ++ ret = platform_device_add(s6105_snd_device); ++ if (ret) ++ platform_device_put(s6105_snd_device); ++ ++ return ret; ++} ++ ++static void __exit s6105_exit(void) ++{ ++ platform_device_unregister(s6105_snd_device); ++} ++ ++module_init(s6105_init); ++module_exit(s6105_exit); ++ ++MODULE_AUTHOR("Daniel Gloeckner"); ++MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/dwc/fh_i2s.c b/sound/soc/dwc/fh_i2s.c +new file mode 100644 +index 00000000..8658b13a +--- /dev/null ++++ b/sound/soc/dwc/fh_i2s.c +@@ -0,0 +1,1072 @@ ++/* ++ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor ++ * ++ * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> ++ * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/device.h> ++#include <linux/slab.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/i2c.h> ++#include <linux/irqreturn.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/initval.h> ++#include <sound/soc.h> ++#include <linux/kernel.h> ++//#include <mach/asp.h> ++ ++#include "fullhan-pcm.h" ++#include "fh_i2s.h" ++ ++#define I2S_FIFO_LEN_RX 40 ++#define I2S_FIFO_LEN_TX 40 ++extern void i2s_irq_enquen(int type, u8 *buff, u8 len,u8 reset); ++/* ++ * NOTE: terminology here is confusing. ++ * ++ * - This driver supports the "Audio Serial Port" (ASP), ++ * found on dm6446, dm355, and other DaVinci chips. ++ * ++ * - But it labels it a "Multi-channel Buffered Serial Port" ++ * (McBSP) as on older chips like the dm642 ... which was ++ * backward-compatible, possibly explaining that confusion. ++ * ++ * - OMAP chips have a controller called McBSP, which is ++ * incompatible with the DaVinci flavor of McBSP. ++ * ++ * - Newer DaVinci chips have a controller called McASP, ++ * incompatible with ASP and with either McBSP. ++ * ++ * In short: this uses ASP to implement I2S, not McBSP. ++ * And it won't be the only DaVinci implemention of I2S. ++ */ ++#define DAVINCI_MCBSP_DRR_REG 0x00 ++#define DAVINCI_MCBSP_DXR_REG 0x04 ++#define DAVINCI_MCBSP_SPCR_REG 0x08 ++#define DAVINCI_MCBSP_RCR_REG 0x0c ++#define DAVINCI_MCBSP_XCR_REG 0x10 ++#define DAVINCI_MCBSP_SRGR_REG 0x14 ++#define DAVINCI_MCBSP_PCR_REG 0x24 ++ ++#define DAVINCI_MCBSP_SPCR_RRST (1 << 0) ++#define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4) ++#define DAVINCI_MCBSP_SPCR_XRST (1 << 16) ++#define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20) ++#define DAVINCI_MCBSP_SPCR_GRST (1 << 22) ++#define DAVINCI_MCBSP_SPCR_FRST (1 << 23) ++#define DAVINCI_MCBSP_SPCR_FREE (1 << 25) ++ ++#define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) ++#define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) ++#define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) ++#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) ++#define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) ++#define DAVINCI_MCBSP_RCR_RFRLEN2(v) ((v) << 24) ++#define DAVINCI_MCBSP_RCR_RPHASE BIT(31) ++ ++#define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) ++#define DAVINCI_MCBSP_XCR_XFRLEN1(v) ((v) << 8) ++#define DAVINCI_MCBSP_XCR_XDATDLY(v) ((v) << 16) ++#define DAVINCI_MCBSP_XCR_XFIG (1 << 18) ++#define DAVINCI_MCBSP_XCR_XWDLEN2(v) ((v) << 21) ++#define DAVINCI_MCBSP_XCR_XFRLEN2(v) ((v) << 24) ++#define DAVINCI_MCBSP_XCR_XPHASE BIT(31) ++ ++#define DAVINCI_MCBSP_SRGR_FWID(v) ((v) << 8) ++#define DAVINCI_MCBSP_SRGR_FPER(v) ((v) << 16) ++#define DAVINCI_MCBSP_SRGR_FSGM (1 << 28) ++#define DAVINCI_MCBSP_SRGR_CLKSM BIT(29) ++ ++#define DAVINCI_MCBSP_PCR_CLKRP (1 << 0) ++#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) ++#define DAVINCI_MCBSP_PCR_FSRP (1 << 2) ++#define DAVINCI_MCBSP_PCR_FSXP (1 << 3) ++#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7) ++#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) ++#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) ++#define DAVINCI_MCBSP_PCR_FSRM (1 << 10) ++#define DAVINCI_MCBSP_PCR_FSXM (1 << 11) ++ ++enum { ++ DAVINCI_MCBSP_WORD_8 = 0, ++ DAVINCI_MCBSP_WORD_12, ++ DAVINCI_MCBSP_WORD_16, ++ DAVINCI_MCBSP_WORD_20, ++ DAVINCI_MCBSP_WORD_24, ++ DAVINCI_MCBSP_WORD_32, ++}; ++struct my_data{ ++ struct work_struct my_work; ++ int value; ++ u8 buff; ++ u8 len; ++ void __iomem *base; ++ }; ++struct my_data *rx_md,*tx_md; ++struct work_struct rx_work_queue,tx_work_queue; ++int g_i2s_base; ++//init test data ++struct my_data *init_data(struct my_data *md,struct work_struct work_queue) ++{ ++md = (struct my_data *)kmalloc(sizeof(struct my_data),GFP_KERNEL); ++md->my_work=work_queue; ++return md; ++} ++ ++ ++static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = { ++ [SNDRV_PCM_FORMAT_S8] = 1, [SNDRV_PCM_FORMAT_S16_LE] = 2, ++ [SNDRV_PCM_FORMAT_S32_LE] = 4, }; ++ ++static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = { ++ [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8, [SNDRV_PCM_FORMAT_S16_LE ++ ] = DAVINCI_MCBSP_WORD_16, [SNDRV_PCM_FORMAT_S32_LE ++ ] = DAVINCI_MCBSP_WORD_32, }; ++ ++static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = { ++ [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE, ++ [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE, }; ++enum dma_event_q { ++ EVENTQ_0 = 0, EVENTQ_1 = 1, EVENTQ_2 = 2, EVENTQ_3 = 3, EVENTQ_DEFAULT = -1 ++}; ++struct davinci_pcm_dma_params { ++ int channel; /* sync dma channel ID */ ++ unsigned short acnt; ++ dma_addr_t dma_addr; /* device physical address for DMA */ ++ unsigned sram_size; ++ enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ ++ enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ ++ unsigned char data_type; /* xfer data type */ ++ unsigned char convert_mono_stereo; ++ unsigned int fifo_level; ++ int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after); ++}; ++struct s6000_i2s_dev { ++ dma_addr_t sifbase; ++ u8 __iomem *scbbase; ++ unsigned int wide; ++ unsigned int channel_in; ++ unsigned int channel_out; ++ unsigned int lines_in; ++ unsigned int lines_out; ++ struct s6000_pcm_dma_params dma_params; ++ int irq; ++ void __iomem *base; ++ struct clk *clk; ++ struct device *dev; ++}; ++struct davinci_mcbsp_dev { ++ struct device *dev; ++ struct davinci_pcm_dma_params dma_params; ++ void __iomem *base; ++#define MOD_DSP_A 0 ++#define MOD_DSP_B 1 ++ int mode; ++ u32 pcr; ++ struct clk *clk; ++ /* ++ * Combining both channels into 1 element will at least double the ++ * amount of time between servicing the dma channel, increase ++ * effiency, and reduce the chance of overrun/underrun. But, ++ * it will result in the left & right channels being swapped. ++ * ++ * If relabeling the left and right channels is not possible, ++ * you may want to let the codec know to swap them back. ++ * ++ * It may allow x10 the amount of time to service dma requests, ++ * if the codec is master and is using an unnecessarily fast bit clock ++ * (ie. tlvaic23b), independent of the sample rate. So, having an ++ * entire frame at once means it can be serviced at the sample rate ++ * instead of the bit clock rate. ++ * ++ * In the now unlikely case that an underrun still ++ * occurs, both the left and right samples will be repeated ++ * so that no pops are heard, and the left and right channels ++ * won't end up being swapped because of the underrun. ++ */ ++ unsigned enable_channel_combine :1; ++ ++ unsigned int fmt; ++ int clk_div; ++ int clk_input_pin; ++ bool i2s_accurate_sck; ++}; ++struct i2c_adapter *codec_i2c_adapter; ++void set_i2c_codec_adapter(struct i2c_adapter * adapter) { ++ codec_i2c_adapter = adapter; ++} ++EXPORT_SYMBOL(set_i2c_codec_adapter); ++ ++int i2c_write_codec(u8 addr, u8 data) { ++ int rval; ++ struct i2c_msg msgs[1]; ++ u8 send[2]; ++ msgs[0].len = 2; ++ msgs[0].addr = 0x1a; ++ msgs[0].flags = 0; ++ msgs[0].buf = send; ++ send[0] = addr; ++ send[1] = data; ++ rval = i2c_transfer(codec_i2c_adapter, msgs, 1); ++ return rval; ++} ++ ++static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, ++ int reg, u32 val) { ++ __raw_writel(val, dev->base + reg); ++} ++ ++static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) { ++ return __raw_readl(dev->base + reg); ++} ++ ++static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) { ++ u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP; ++ /* The clock needs to toggle to complete reset. ++ * So, fake it by toggling the clk polarity. ++ */ ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); ++} ++ ++static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, ++ struct snd_pcm_substream *substream) { ++// struct snd_soc_pcm_runtime *rtd = substream->private_data; ++// struct snd_soc_platform *platform = rtd->platform; ++// int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); ++// u32 spcr; ++// u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; ++// spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++// if (spcr & mask) { ++// /* start off disabled */ ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, ++// spcr & ~mask); ++// toggle_clock(dev, playback); ++// } ++// if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | ++// DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { ++// /* Start the sample generator */ ++// spcr |= DAVINCI_MCBSP_SPCR_GRST; ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++// } ++// ++// if (playback) { ++// /* Stop the DMA to avoid data loss */ ++// /* while the transmitter is out of reset to handle XSYNCERR */ ++// if (platform->driver->ops->trigger) { ++// int ret = platform->driver->ops->trigger(substream, ++// SNDRV_PCM_TRIGGER_STOP); ++// if (ret < 0) ++// printk(KERN_DEBUG "Playback DMA stop failed\n"); ++// } ++// ++// /* Enable the transmitter */ ++// spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++// spcr |= DAVINCI_MCBSP_SPCR_XRS SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ++ ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++// ++// /* wait for any unexpected frame sync error to occur */ ++// udelay(100); ++// ++// /* Disable the transmitter to clear any outstanding XSYNCERR */ ++// spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++// spcr &= ~DAVINCI_MCBSP_SPCR_XRST; ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++// toggle_clock(dev, playback); ++// ++// /* Restart the DMA */ ++// if (platform->driver->ops->trigger) { ++// int ret = platform->driver->ops->trigger(substream, ++// SNDRV_PCM_TRIGGER_START);2 ++// if (ret < 0) ++// printk(KERN_DEBUG "Playback DMA start failed\n"); ++// } ++// } ++// ++// /* Enable transmitter or receiver */ ++// spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++// spcr |= mask; ++// ++// if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { ++// /* Start frame sync */ ++// spcr |= DAVINCI_MCBSP_SPCR_FRST; ++// } ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++} ++ ++static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) { ++ ++// u32 spcr; ++// ++// /* Reset transmitter/receiver and sample rate/frame sync generators */ ++// spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++// spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); ++// spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST; ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++// toggle_clock(dev, playback); ++} ++ ++#define DEFAULT_BITPERSAMPLE 16 ++ ++static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, ++ unsigned int fmt) { ++// struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++// unsigned int pcr; ++// unsigned int srgr; ++// /* Attention srgr is updated by hw_params! */ ++// srgr = DAVINCI_MCBSP_SRGR_FSGM | ++// DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | ++// DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); ++// ++// dev->fmt = fmt; ++// /* set master/slave audio interface */ ++// switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++// case SND_SOC_DAIFMT_CBS_CFS: ++// /* cpu is master */ ++// pcr = DAVINCI_MCBSP_PCR_FSXM | ++// DAVINCI_MCBSP_PCR_FSRM | ++// DAVINCI_MCBSP_PCR_CLKXM | ++// DAVINCI_MCBSP_PCR_CLKRM; ++// break; ++// case SND_SOC_DAIFMT_CBM_CFS: ++// pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; ++// /* ++// * Selection of the clock input pin that is the ++// * input for the Sample Rate Generator. ++// * McBSP FSR and FSX are driven by the Sample Rate ++// * Generator. ++// */ ++// switch (dev->clk_input_pin) { ++// case MCBSP_CLKS: ++// pcr |= DAVINCI_MCBSP_PCR_CLKXM | ++// DAVINCI_MCBSP_PCR_CLKRM; ++// break; ++// case MCBSP_CLKR: ++// pcr |= DAVINCI_MCBSP_PCR_SCLKME; ++// break; ++// default: ++// dev_err(dev->dev, "bad clk_input_pin\n"); ++// return -EINVAL; ++// } ++// ++// break; ++// case SND_SOC_DAIFMT_CBM_CFM: ++// /* codec is master */ ++// pcr = 0; ++// break; ++// default: ++// printk(KERN_ERR "%s:bad master\n", __func__); ++// return -EINVAL; ++// } ++// ++// /* interface format */ ++// switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++// case SND_SOC_DAIFMT_I2S: ++// /* Davinci doesn't support TRUE I2S, but some codecs will have ++// * the left and right channels contiguous. This allows ++// * dsp_a mode to be used with an inverted normal frame clk. ++// * If your codec is master and does not have contiguous ++// * channels, then you will have sound on only one channel. ++// * Try using a different mode, or codec as slave. ++// * ++// * The TLV320AIC33 is an example of a codec where this works. ++// * It has a variable bit clock frequency allowing it to have ++// * valid data on every bit clock. ++// * ++// * The TLV320AIC23 is an example of a codec where this does not ++// * work. It has a fixed bit clock frequency with progressively ++// * more empty bit clock slots between channels as the sample ++// * rate is lowered. ++// */ ++// fmt ^= SND_SOC_DAIFMT_NB_IF; ++// case SND_SOC_DAIFMT_DSP_A: ++// dev->mode = MOD_DSP_A; ++// break; ++// case SND_SOC_DAIFMT_DSP_B: ++// dev->mode = MOD_DSP_B; ++// break; ++// default: ++// printk(KERN_ERR "%s:bad format\n", __func__); ++// return -EINVAL; ++// } ++// ++// switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++// case SND_SOC_DAIFMT_NB_NF: ++// /* CLKRP Receive clock polarity, ++// * 1 - sampled on rising edge of CLKR ++// * valid on rising edge ++// * CLKXP Transmit clock polarity, ++// * 1 - clocked on falling edge of CLKX ++// * valid on rising edge ++// * FSRP Receive frame sync pol, 0 - active high ++// * FSXP Transmit frame sync pol, 0 - active high ++// */ ++// pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP); ++// break; ++// case SND_SOC_DAIFMT_IB_IF: ++// /* CLKRP Receive clock polarity, ++// * 0 - sampled on falling edge of CLKR ++// * valid on falling edge ++// * CLKXP Transmit clock polarity, ++// * 0 - clocked on rising edge of CLKX ++// * valid on falling edge ++// * FSRP Receive frame sync pol, 1 - active low ++// * FSXP Transmit frame sync pol, 1 - active low ++// */ ++// pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); ++// break; ++// case SND_SOC_DAIFMT_NB_IF: ++// /* CLKRP Receive clock polarity, ++// * 1 - sampled on rising edge of CLKR ++// * valid on rising edge ++// * CLKXP Transmit clock polarity, ++// * 1 - clocked on falling edge of CLKX ++// * valid on rising edge ++// * FSRP Receive frame sync pol, 1 - active low ++// * FSXP Transmit frame sync pol, 1 - active low ++// */ ++// pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP | ++// DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); ++// break; ++// case SND_SOC_DAIFMT_IB_NF: ++// /* CLKRP Receive clock polarity, ++// * 0 - sampled on falling edge of CLKR ++// * valid on falling edge ++// * CLKXP Transmit clock polarity, ++// * 0 - clocked on rising edge of CLKX ++// * valid on falling edge ++// * FSRP Receive frame sync pol, 0 - active high ++// * FSXP Transmit frame sync pol, 0 - active high ++// */ ++// break; ++// default: ++// return -EINVAL; ++// } ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); ++// dev->pcr = pcr; ++// davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); ++ return 0; ++} ++ ++static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, ++ int div) { ++ ++// struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++// ++// if (div_id != DAVINCI_MCBSP_CLKGDV) ++// return -ENODEV; ++// ++// dev->clk_div = div; ++ return 0; ++} ++ ++static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { ++ ++ ++ struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); ++ struct davinci_pcm_dma_params *dma_params = &dev->dma_params; ++ struct snd_interval *i = NULL; ++ int mcbsp_word_length, master; ++ unsigned int rcr, xcr, srgr, clk_div, freq, framesize; ++ u32 spcr; ++ snd_pcm_format_t fmt; ++ unsigned element_cnt = 1; ++ ++ /* general line settings */ ++#if 0 ++ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); ++ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ++ spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++ } else { ++ spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); ++ } ++ ++ master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; ++ fmt = params_format(params); ++ mcbsp_word_length = asp_word_length[fmt]; ++ ++ switch (master) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ freq = clk_get_rate(dev->clk); ++ srgr = DAVINCI_MCBSP_SRGR_FSGM | ++ DAVINCI_MCBSP_SRGR_CLKSM; ++ srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * ++ 8 - 1); ++ if (dev->i2s_accurate_sck) { ++ clk_div = 256; ++ do { ++ framesize = (freq / (--clk_div)) / ++ params->rate_num * ++ params->rate_den; ++ }while (((framesize < 33) || (fram SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX), .formats = ++ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE), .rates = ++ (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | ++ SNDRV_PCM_RATE_8000_192000), .rate_min = 0, .rate_max = 1562500, ++ .channels_min = 2, .channels_max = 8, .buffer_bytes_max = 0x7ffffff0, ++ .period_bytes_min = 16, .period_bytes_max = 0xfffff0, .periods_min = 2, ++ .periods_max = 1024, /* no limit */ ++ .fifo_size = 0, }; ++esize > 4095)) && ++ (clk_div)); ++ clk_div--; ++ srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1); ++ } else { ++ /* symmetric waveforms */ ++ clk_div = freq / (mcbsp_word_length * 16) / ++ params->rate_num * params->rate_den; ++ srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * ++ 16 - 1); ++ } ++ clk_div &= 0xFF; ++ srgr |= clk_div; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFS: ++ srgr = DAVINCI_MCBSP_SRGR_FSGM; ++ clk_div = dev->clk_div - 1; ++ srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); ++ srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1); ++ clk_div &= 0xFF; ++ srgr |= clk_div; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ /* Clock and frame sync given from external sources */ ++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); ++ srgr = DAVINCI_MCBSP_SRGR_FSGM; ++ srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); ++ pr_debug("%s - %d FWID set: re-read srgr = %X\n", ++ __func__, __LINE__, snd_interval_value(i) - 1); ++ ++ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); ++ srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); ++ break; ++ default: ++ return -EINVAL; ++ } ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); ++ ++ rcr = DAVINCI_MCBSP_RCR_RFIG; ++ xcr = DAVINCI_MCBSP_XCR_XFIG; ++ if (dev->mode == MOD_DSP_B) { ++ rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); ++ xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); ++ } else { ++ rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); ++ xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); ++ } ++ /* Determine xfer data type */ ++ fmt = params_format(params); ++ if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) { ++ printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); ++ return -EINVAL; ++ } ++ ++ if (params_channels(params) == 2) { ++ element_cnt = 2; ++ if (double_fmt[fmt] && dev->enad work_func(struct work_struct *work) ++ { ++ printk("%s \n",__FUNCTION__);ble_channel_combine) { ++ element_cnt = 1; ++ fmt = double_fmt[fmt]; ++ } ++ switch (master) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0); ++ xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0); ++ rcr |= DAVINCI_MCBSP_RCR_RPHASE; ++ xcr |= DAVINCI_MCBSP_XCR_XPHASE; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ case SND_SOC_DAIFMT_CBM_CFS: ++ rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); ++ xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++// dma_params->acnt = dma_params->data_type = data_type[fmt]; ++// dma_params->fifo_level = 0; ++ mcbsp_word_length = asp_word_length[fmt]; ++ ++ switch (master) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); ++ xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ case SND_SOC_DAIFMT_CBM_CFS: ++ rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); ++ xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | ++ DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); ++ xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | ++ DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); ++ else ++ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); ++ ++ pr_debug("%s - %d srgr=%X\n", __func__, __LINE__, srgr); ++ pr_debug("%s - %d xcr=%X\n", __func__, __LINE__, xcr); ++ pr_debug("%s - %d rcr=%X\n", __func__, __LINE__, rcr); ++#endif ++ ++ ++ return 0; ++} ++ ++static int davinci_i2s_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) { ++ ++// struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); ++// int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); ++// davinci_mcbsp_stop(dev, playback); ++ return 0; ++} ++static struct { ++ spinlock_t lock; ++ void __iomem *regs; ++ struct clk *clk; ++ unsigned long in_use; ++ unsigned long next_heartbeat; ++ struct timer_list timer; ++ int expect_close; ++} dw_i2s; ++#define I2S_IOCTL_BASE 'W' ++#define I2S_GETSUPPORT _IOR(I2S_IOCTL_BASE, 3, int) ++typedef unsigned short UINT16; ++typedef unsigned int uint32; ++//#define BASEADDR_I2S_REG dw_i2s.regs ++#define OFFSET_I2S_IER 0x0000 ++#define OFFSET_I2S_IRER 0x0004 ++#define OFFSET_I2S_ITER 0x0008 ++#define OFFSET_I2S_CER 0x000c ++#define OFFSET_I2S_CCR 0x0010 ++#define OFFSET_I2S_RXFFR 0x0014 ++#define OFFSET_I2S_TXFFR 0x0018 ++#define OFFSET_I2S_LRBR0 0x0020 ++#define OFFSET_I2S_LRBR1 0x0060 ++#define OFFSET_I2S_LRBR2 0x00A0 ++#define OFFSET_I2S_LRBR3 0x00E0 ++#define OFFSET_I2S_LTHR0 0x0020 ++#define OFFSET_I2S_LTHR1 0x0060 ++#define OFFSET_I2S_LTHR2 0x00A0 ++#define OFFSET_I2S_LTHR3 0x00E0 ++#define OFFSET_I2S_RRBR0 0x0024 ++#define OFFSET_I2S_RRBR1 0x0064 ++#define OFFSET_I2S_RRBR2 0x00A4 ++#define OFFSET_I2S_RRBR3 0x00E4 ++#define OFFSET_I2S_RTHR0 0x0024 ++#define OFFSET_I2S_RTHR1 0x0064 ++#define OFFSET_I2S_RTHR2 0x00A4 ++#define OFFSET_I2S_RTHR3 0x00E4 ++#define OFFSET_I2S_RER0 0x0028 ++#define OFFSET_I2S_RER1 0x0068 ++#define OFFSET_I2S_RER2 0x00A8 ++#define OFFSET_I2S_RER3 0x00E8 ++#define OFFSET_I2S_TER0 0x002C ++#define OFFSET_I2S_TER1 0x006C ++#define OFFSET_I2S_TER2 0x00AC ++#define OFFSET_I2S_TER3 0x00EC ++#define OFFSET_I2S_RCR0 0x0030 ++#define OFFSET_I2S_RCR1 0x0070 ++#define OFFSET_I2S_RCR2 0x00B0 ++#define OFFSET_I2S_RCR3 0x00F0 ++#define OFFSET_I2S_TCR0 0x0034 ++#define OFFSET_I2S_TCR1 0x0074 ++#define OFFSET_I2S_TCR2 0x00B4 ++#define OFFSET_I2S_TCR3 0x00F4 ++#define OFFSET_I2S_ISR0 0x0038 ++#define OFFSET_I2S_ISR1 0x0078 ++#define OFFSET_I2S_ISR2 0x00B8 ++#define OFFSET_I2S_ISR3 0x00F8 ++#define OFFSET_I2S_IMR0 0x003C ++#define OFFSET_I2S_IMR1 0x007C ++#define OFFSET_I2S_IMR2 0x00BC ++#define OFFSET_I2S_IMR3 0x00FC ++#define OFFSET_I2S_ROR0 0x0040 ++#define OFFSET_I2S_ROR1 0x0080 ++#define OFFSET_I2S_ROR2 0x00C0 ++#define OFFSET_I2S_ROR3 0x0100 ++#define OFFSET_I2S_TOR0 0x0044 ++#define OFFSET_I2S_TOR1 0x0084 ++#define OFFSET_I2S_TOR2 0x00C4 ++#define OFFSET_I2S_TOR3 0x0104 ++#define OFFSET_I2S_RFCR0 0x0048 ++#define OFFSET_I2S_RFCR1 0x0088 ++#define OFFSET_I2S_RFCR2 0x00C8 ++#define OFFSET_I2S_RFCR3 0x0108 ++#define OFFSET_I2S_TFCR0 0x004C ++#define OFFSET_I2S_TFCR1 0x008C ++#define OFFSET_I2S_TFCR2 0x00CC ++#define OFFSET_I2S_TFCR3 0x010C ++#define OFFSET_I2S_RFF0 0x0050 ++#define OFFSET_I2S_RFF1 0x0090 ++#define OFFSET_I2S_RFF2 0x00D4 ++#define OFFSET_I2S_RFF3 0x0110 ++#define OFFSET_I2S_TFF0 0x0054 ++#define OFFSET_I2S_TFF1 0x0094 ++#define OFFSET_I2S_TFF2 0x00D4 ++#define OFFSET_I2S_TFF3 0x0114 ++#define OFFSET_I2S_RXDMA 0x01C0 ++#define OFFSET_I2S_RRXDMA 0x01C4 ++#define OFFSET_I2S_TXDMA 0x01C8 ++#define OFFSET_I2S_RTXDMA 0x01CC ++#define OFFSET_I2S_COMP_PARAM_2 0x01f0 ++#define OFFSET_I2S_COMP_PARAM_1 0x01f4 ++#define OFFSET_I2S_COMP_VERSION 0x01f8 ++#define OFFSET_I2S_COMP_TYPE 0x01fc ++#define RESOLUTION12 ++#define write_reg(addr,reg) (*((volatile uint32 *)(addr)))=(uint32)(reg) ++#define read_reg(addr) (*((volatile uint32 *)(addr))) ++static int dw_i2s_action(void * base,int channel) { ++ ++ int data, rx_data_right, rx_data_left,temp; ++ unsigned int i2s_base; ++ i2s_base = base; ++ temp = read_reg(OFFSET_I2S_IMR0 + i2s_base); ++ if (SNDRV_PCM_STREAM_PLAYBACK == channel) { ++ write_reg(OFFSET_I2S_TCR0 + i2s_base, 0x4); ++ write_reg(OFFSET_I2S_TFCR0 + i2s_base, 0x10); ++ write_reg(OFFSET_I2S_ITER + i2s_base, 0x01); ++ write_reg(OFFSET_I2S_TXFFR + i2s_base, 1); ++ temp &=~(1<<4); ++ temp |= (1<<1); ++ temp |= (1<<5); ++ write_reg(OFFSET_I2S_TER0 + i2s_base, 1); ++ ++ } else { ++ write_reg(OFFSET_I2S_IRER + i2s_base, 0x01); ++ write_reg(OFFSET_I2S_RCR0 + i2s_base, 0x4); ++ write_reg(OFFSET_I2S_RFCR0 + i2s_base, I2S_FIFO_LEN_RX); ++ write_reg(OFFSET_I2S_RXFFR + i2s_base, 1); ++ temp &=~(1<<0); ++ temp |= (1<<1); ++ temp |= (1<<5); ++ write_reg(OFFSET_I2S_RER0 + i2s_base, 1); ++ ++ } ++ write_reg(OFFSET_I2S_IMR0 + i2s_base, temp); //interrupt mask ++} ++ ++static void codec_config(void) ++{ ++ i2c_write_codec(0x0, 0x44);//set 8K sample ++ i2c_write_codec(0x9, 0x2); ++ i2c_write_codec(0x4, 0x10); ++ i2c_write_codec(0x1, 0x3c); ++ i2c_write_codec(0x5, 0x5); ++ i2c_write_codec(0x7, 0xe6); ++ i2c_write_codec(0x2, 0x14); ++ i2c_write_codec(0x8, 0x38); ++ i2c_write_codec(0xf, 0x1b); ++ i2c_write_codec(0x10, 0x1b); ++} ++ ++static int s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel) { ++ ++ dw_i2s_action(dev->base,channel); ++ return 0; ++} ++static void s6000_i2s_start(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); ++ s6000_i2s_start_channel(dev, substream->stream); ++ ++} ++static int s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel) { ++ int temp,i; ++ temp = read_reg(OFFSET_I2S_IMR0 + dev->base); ++ if (SNDRV_PCM_STREAM_PLAYBACK == channel) { ++ write_reg(OFFSET_I2S_TER0 + dev->base, 0); ++ temp |=(1<<4); ++ temp |= (1<<1); ++ temp |= (1<<5); ++ write_reg(OFFSET_I2S_IMR0 + dev->base,temp); //interrupt mask ++ ++ ++ } else { ++ write_reg(OFFSET_I2S_RER0 + dev->base, 0); ++ temp |=(1<<0); ++ temp |= (1<<1); ++ temp |= (1<<5); ++ write_reg(OFFSET_I2S_IMR0 + dev->base,temp); //interrupt mask ++ ++ } ++ return 0; ++ ++} ++static void s6000_i2s_stop(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); ++ s6000_i2s_stop_channel(dev, substream->stream); ++} ++static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ int after) { ++ int ret = 0; ++ int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ s6000_i2s_start(substream); ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ // if (!after) ++ s6000_i2s_stop(substream); ++ break; ++ } ++ return 0; ++} ++ ++static int davinci_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) { ++// struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); ++// ++// snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); ++ return 0; ++} ++ ++static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) { ++// struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); ++// int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); ++// davinci_mcbsp_stop(dev, playback); ++} ++ ++#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 ++ ++static struct snd_soc_dai_ops davinci_i2s_dai_ops = { .startup = ++ davinci_i2s_startup, .shutdown = davinci_i2s_shutdown, .prepare = ++ davinci_i2s_prepare, .trigger = davinci_i2s_trigger, .hw_params = ++ davinci_i2s_hw_params, .set_fmt = davinci_i2s_set_dai_fmt, .set_clkdiv = ++ davinci_i2s_dai_set_clkdiv, ++ ++}; ++int s6000_i2s_dai_probe(struct snd_soc_dai *dai) { ++ ++ struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ struct s6000_snd_platform_data *pdata = dai->dev->platform_data; ++ dai->capture_dma_data = &dev->dma_params; ++ dai->playback_dma_data = &dev->dma_params; ++ dev->dma_params.trigger = davinci_i2s_trigger; ++// dev->wide = pdata->wide; ++// dev->channel_in = pdata->channel_in; ++// dev->channel_out = pdata->channel_out; ++// dev->lines_in = pdata->lines_in; ++// dev->lines_out = pdata->lines_out; ++ dev->dma_params.sif_in = 0xf0901c0; ++ dev->dma_params.sif_out = 0xf0901c8; ++ return 0; ++ ++} ++static struct snd_soc_dai_driver davinci_i2s_dai = { .probe = ++ s6000_i2s_dai_probe, .playback = { .channels_min = 2, .channels_max = 2, ++ .rates = DAVINCI_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, ++ .capture = { .channels_min = 2, .channels_max = 2, .rates = ++ DAVINCI_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .ops = ++ &davinci_i2s_dai_ops, ++ ++}; ++//work queue funtion ++ ++ ++ void capture_work_func(struct work_struct *work) ++{ ++ uint32 count_data,i,audio_data,temp; ++ uint32 buff[I2S_FIFO_LEN_RX]; ++ for(count_data=0;count_data<I2S_FIFO_LEN_RX;count_data++) { ++ audio_data = read_reg(OFFSET_I2S_RRBR0 + g_i2s_base); ++ i = read_reg(OFFSET_I2S_LRBR0 + g_i2s_base); ++ buff[count_data] = audio_data; ++ } ++ i2s_irq_enquen(SNDRV_PCM_STREAM_CAPTURE,(u8 *)buff,count_data<<2,0); ++ temp = read_reg(OFFSET_I2S_IMR0 + g_i2s_base); ++ temp &=~(1<<0); ++ write_reg(OFFSET_I2S_IMR0 + g_i2s_base,temp); ++} ++ void playback_work_func(struct work_struct *work) ++{ ++ uint32 count_data,temp; ++ uint32 buff[I2S_FIFO_LEN_TX]; ++ i2s_irq_enquen(SNDRV_PCM_STREAM_PLAYBACK,(u8 *)buff,I2S_FIFO_LEN_TX<<2,0); ++ for(count_data=0;count_data<I2S_FIFO_LEN_TX;count_data++) { ++ write_reg(OFFSET_I2S_RTHR0 + g_i2s_base,buff[count_data]); ++ write_reg(OFFSET_I2S_LTHR0 + g_i2s_base,buff[count_data]); ++ } ++ temp = read_reg(OFFSET_I2S_IMR0 + g_i2s_base); ++ temp &=~(1<<4); ++ write_reg(OFFSET_I2S_IMR0 + g_i2s_base,temp); ++} ++ ++static irqreturn_t davinci_i2s_irq(int irq, void *data) { ++ uint32 irq_data,temp; ++ struct s6000_i2s_dev *fdev = data; ++ irq_data = read_reg(OFFSET_I2S_ISR0 + fdev->base); ++ temp = read_reg(OFFSET_I2S_IMR0 + fdev->base); ++ if ( (irq_data & 0x10)&&( !(temp&(1<<4))) ) { ++ temp |= (1<<4); ++ write_reg(OFFSET_I2S_IMR0 + fdev->base,temp); ++ schedule_work(&tx_md->my_work); ++ //playback_work_func(&tx_md->my_work); ++ } ++ if ( (irq_data & 0x01)&&( !(temp&(1<<0))) ) { ++ temp|= (1<<0); ++ write_reg(OFFSET_I2S_IMR0 +fdev->base,temp); ++ schedule_work(&rx_md->my_work); ++ //capture_work_func(&rx_md->my_work); ++ } ++ return IRQ_HANDLED; ++ } ++ ++static void i2s_config(void) ++{ ++ write_reg(OFFSET_I2S_IER + g_i2s_base, 0x01);//i2s enable ++ write_reg(OFFSET_I2S_CCR + g_i2s_base, 0x8); ++ write_reg(OFFSET_I2S_CER + g_i2s_base, 0x01); ++} ++ static int davinci_i2s_probe(struct platform_device *pdev) { ++ struct snd_platform_data *pdata = pdev->dev.platform_data; ++ struct s6000_i2s_dev *dev; ++ struct resource *mem, *ioarea, *res; ++ ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ int ret; ++ ++ rx_md=init_data(rx_md,rx_work_queue); ++ INIT_WORK(&rx_md->my_work,capture_work_func); ++ //rx_wq=create_singlethread_workqueue("capture_workqueue"); ++ tx_md = init_data(tx_md,tx_work_queue); ++ INIT_WORK(&tx_md->my_work,playback_work_func); ++ //tx_wq=create_singlethread_workqueue("capture_workqueue"); ++ //queue_work(wq,&md->my_work); ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) { ++ printk("i2s platform get resource err\n"); ++ dev_err(&pdev->dev, "no mem resource?\n"); ++ return -ENODEV; ++ } ++ ++ ioarea = request_mem_region(mem->start, resource_size(mem), pdev->name); ++ if (!ioarea) { ++ printk("i2s request mem region err\n"); ++ dev_err(&pdev->dev, "McBSP region already claimed\n"); ++ return -EBUSY; ++ } ++ ++ dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL); ++ if (!dev) { ++ printk("i2s kzalloc err \n"); ++ ret = -ENOMEM; ++ goto err_release_region; ++ } ++ dev->irq = platform_get_irq(pdev, 0); ++ int rc; ++ rc = request_irq(dev->irq, davinci_i2s_irq, ++ IRQF_DISABLED, pdev->name, dev); ++ if (rc) { ++ printk("request irq err \n"); ++ free_irq(dev->irq, dev); ++ } ++ ++ dev->base = ioremap(mem->start, resource_size(mem)); ++ g_i2s_base = dev->base; ++ rx_md->base =dev->base; ++ tx_md->base = rx_md->base; ++ if (!dev->base) { ++ dev_err(&pdev->dev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_release_clk; ++ } ++ ++ dev->dev = &pdev->dev; ++ ++ dev_set_drvdata(&pdev->dev, dev); ++ ++ ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); ++ if (ret != 0) ++ goto err_iounmap; ++ ++ codec_config(); ++ i2s_config(); ++ ++ return 0; ++ ++ err_iounmap: iounmap(dev->base); ++ err_release_clk: clk_disable(dev->clk); ++ clk_put(dev->clk); ++ err_free_mem: kfree(dev); ++ err_release_region: ++ release_mem_region(mem->start, resource_size(mem)); ++ ++ return ret; ++ } ++ ++ static int davinci_i2s_remove(struct platform_device *pdev) { ++ struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); ++ struct resource *mem; ++ ++ snd_soc_unregister_dai(&pdev->dev); ++// clk_disable(dev->clk); ++// clk_put(dev->clk); ++// dev->clk = NULL; ++ kfree(dev); ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(mem->start, resource_size(mem)); ++ ++ return 0; ++ } ++ ++ static struct platform_driver davinci_mcbsp_driver = { ++ .probe =davinci_i2s_probe, ++ .remove = davinci_i2s_remove, ++ .driver = { ++ .name = ++ "s6000-i2s", .owner = THIS_MODULE, ++ }, ++ }; ++ ++static int __init davinci_i2s_init(void) ++{ ++ return platform_driver_register(&davinci_mcbsp_driver); ++} ++ module_init(davinci_i2s_init); ++ ++static void __exit davinci_i2s_exit(void) ++{ ++ platform_driver_unregister(&davinci_mcbsp_driver); ++} ++ module_exit(davinci_i2s_exit); ++ ++ MODULE_AUTHOR("Vladimir Barinov"); ++ MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); ++ MODULE_LICENSE("GPL"); +diff --git a/sound/soc/dwc/fh_i2s.h b/sound/soc/dwc/fh_i2s.h +new file mode 100644 +index 00000000..86aa1921 +--- /dev/null ++++ b/sound/soc/dwc/fh_i2s.h +@@ -0,0 +1,23 @@ ++/* ++ * ALSA SoC I2S Audio Layer for the Stretch s6000 family ++ * ++ * Author: Daniel Gloeckner, <dg@emlix.com> ++ * Copyright: (C) 2009 emlix GmbH <info@emlix.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _S6000_I2S_H ++#define _S6000_I2S_H ++ ++struct s6000_snd_platform_data { ++ int lines_in; ++ int lines_out; ++ int channel_in; ++ int channel_out; ++ int wide; ++ int same_rate; ++}; ++#endif +diff --git a/sound/soc/dwc/fh_i2s_dai.c b/sound/soc/dwc/fh_i2s_dai.c +new file mode 100644 +index 00000000..28f8ea67 +--- /dev/null ++++ b/sound/soc/dwc/fh_i2s_dai.c +@@ -0,0 +1,1003 @@ ++/* ++ * ALSA SoC McASP Audio Layer for TI DAVINCI processor ++ * ++ * Multi-channel Audio Serial Port Driver ++ * ++ * Author: Nirmal Pandey <n-pandey@ti.com>, ++ * Suresh Rajashekara <suresh.r@ti.com> ++ * Steve Chen <schen@.mvista.com> ++ * ++ * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com> ++ * Copyright: (C) 2009 Texas Instruments, India ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/device.h> ++#include <linux/slab.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++ ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/initval.h> ++#include <sound/soc.h> ++ ++#include "fullhan-pcm.h" ++#include "fh_i2s_dai.h" ++ ++/* ++ * McASP register definitions ++ */ ++#define DAVINCI_MCASP_PID_REG 0x00 ++#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 ++ ++#define DAVINCI_MCASP_PFUNC_REG 0x10 ++#define DAVINCI_MCASP_PDIR_REG 0x14 ++#define DAVINCI_MCASP_PDOUT_REG 0x18 ++#define DAVINCI_MCASP_PDSET_REG 0x1c ++ ++#define DAVINCI_MCASP_PDCLR_REG 0x20 ++ ++#define DAVINCI_MCASP_TLGC_REG 0x30 ++#define DAVINCI_MCASP_TLMR_REG 0x34 ++ ++#define DAVINCI_MCASP_GBLCTL_REG 0x44 ++#define DAVINCI_MCASP_AMUTE_REG 0x48 ++#define DAVINCI_MCASP_LBCTL_REG 0x4c ++ ++#define DAVINCI_MCASP_TXDITCTL_REG 0x50 ++ ++#define DAVINCI_MCASP_GBLCTLR_REG 0x60 ++#define DAVINCI_MCASP_RXMASK_REG 0x64 ++#define DAVINCI_MCASP_RXFMT_REG 0x68 ++#define DAVINCI_MCASP_RXFMCTL_REG 0x6c ++ ++#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 ++#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 ++#define DAVINCI_MCASP_RXTDM_REG 0x78 ++#define DAVINCI_MCASP_EVTCTLR_REG 0x7c ++ ++#define DAVINCI_MCASP_RXSTAT_REG 0x80 ++#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 ++#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 ++#define DAVINCI_MCASP_REVTCTL_REG 0x8c ++ ++#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 ++#define DAVINCI_MCASP_TXMASK_REG 0xa4 ++#define DAVINCI_MCASP_TXFMT_REG 0xa8 ++#define DAVINCI_MCASP_TXFMCTL_REG 0xac ++ ++#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 ++#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 ++#define DAVINCI_MCASP_TXTDM_REG 0xb8 ++#define DAVINCI_MCASP_EVTCTLX_REG 0xbc ++ ++#define DAVINCI_MCASP_TXSTAT_REG 0xc0 ++#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 ++#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 ++#define DAVINCI_MCASP_XEVTCTL_REG 0xcc ++ ++/* Left(even TDM Slot) Channel Status Register File */ ++#define DAVINCI_MCASP_DITCSRA_REG 0x100 ++/* Right(odd TDM slot) Channel Status Register File */ ++#define DAVINCI_MCASP_DITCSRB_REG 0x118 ++/* Left(even TDM slot) User Data Register File */ ++#define DAVINCI_MCASP_DITUDRA_REG 0x130 ++/* Right(odd TDM Slot) User Data Register File */ ++#define DAVINCI_MCASP_DITUDRB_REG 0x148 ++ ++/* Serializer n Control Register */ ++#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 ++#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ ++ (n << 2)) ++ ++/* Transmit Buffer for Serializer n */ ++#define DAVINCI_MCASP_TXBUF_REG 0x200 ++/* Receive Buffer for Serializer n */ ++#define DAVINCI_MCASP_RXBUF_REG 0x280 ++ ++/* McASP FIFO Registers */ ++#define DAVINCI_MCASP_WFIFOCTL (0x1010) ++#define DAVINCI_MCASP_WFIFOSTS (0x1014) ++#define DAVINCI_MCASP_RFIFOCTL (0x1018) ++#define DAVINCI_MCASP_RFIFOSTS (0x101C) ++ ++/* ++ * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management ++ * Register Bits ++ */ ++#define MCASP_FREE BIT(0) ++#define MCASP_SOFT BIT(1) ++ ++/* ++ * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits ++ */ ++#define AXR(n) (1<<n) ++#define PFUNC_AMUTE BIT(25) ++#define ACLKX BIT(26) ++#define AHCLKX BIT(27) ++#define AFSX BIT(28) ++#define ACLKR BIT(29) ++#define AHCLKR BIT(30) ++#define AFSR BIT(31) ++ ++/* ++ * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits ++ */ ++#define AXR(n) (1<<n) ++#define PDIR_AMUTE BIT(25) ++#define ACLKX BIT(26) ++#define AHCLKX BIT(27) ++#define AFSX BIT(28) ++#define ACLKR BIT(29) ++#define AHCLKR BIT(30) ++#define AFSR BIT(31) ++ ++/* ++ * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits ++ */ ++#define DITEN BIT(0) /* Transmit DIT mode enable/disable */ ++#define VA BIT(2) ++#define VB BIT(3) ++ ++/* ++ * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits ++ */ ++#define TXROT(val) (val) ++#define TXSEL BIT(3) ++#define TXSSZ(val) (val<<4) ++#define TXPBIT(val) (val<<8) ++#define TXPAD(val) (val<<13) ++#define TXORD BIT(15) ++#define FSXDLY(val) (val<<16) ++ ++/* ++ * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits ++ */ ++#define RXROT(val) (val) ++#define RXSEL BIT(3) ++#define RXSSZ(val) (val<<4) ++#define RXPBIT(val) (val<<8) ++#define RXPAD(val) (val<<13) ++#define RXORD BIT(15) ++#define FSRDLY(val) (val<<16) ++ ++/* ++ * DAVINCI_MCASP_TXFMCTL_REG - Transmit Frame Control Register Bits ++ */ ++#define FSXPOL BIT(0) ++#define AFSXE BIT(1) ++#define FSXDUR BIT(4) ++#define FSXMOD(val) (val<<7) ++ ++/* ++ * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits ++ */ ++#define FSRPOL BIT(0) ++#define AFSRE BIT(1) ++#define FSRDUR BIT(4) ++#define FSRMOD(val) (val<<7) ++ ++/* ++ * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits ++ */ ++#define ACLKXDIV(val) (val) ++#define ACLKXE BIT(5) ++#define TX_ASYNC BIT(6) ++#define ACLKXPOL BIT(7) ++ ++/* ++ * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits ++ */ ++#define ACLKRDIV(val) (val) ++#define ACLKRE BIT(5) ++#define RX_ASYNC BIT(6) ++#define ACLKRPOL BIT(7) ++ ++/* ++ * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control ++ * Register Bits ++ */ ++#define AHCLKXDIV(val) (val) ++#define AHCLKXPOL BIT(14) ++#define AHCLKXE BIT(15) ++ ++/* ++ * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control ++ * Register Bits ++ */ ++#define AHCLKRDIV(val) (val) ++#define AHCLKRPOL BIT(14) ++#define AHCLKRE BIT(15) ++ ++/* ++ * DAVINCI_MCASP_XRSRCTL_BASE_REG - Serializer Control Register Bits ++ */ ++#define MODE(val) (val) ++#define DISMOD (val)(val<<2) ++#define TXSTATE BIT(4) ++#define RXSTATE BIT(5) ++ ++/* ++ * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits ++ */ ++#define LBEN BIT(0) ++#define LBORD BIT(1) ++#define LBGENMODE(val) (val<<2) ++ ++/* ++ * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration ++ */ ++#define TXTDMS(n) (1<<n) ++ ++/* ++ * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration ++ */ ++#define RXTDMS(n) (1<<n) ++ ++/* ++ * DAVINCI_MCASP_GBLCTL_REG - Global Control Register Bits ++ */ ++#define RXCLKRST BIT(0) /* Receiver Clock Divider Reset */ ++#define RXHCLKRST BIT(1) /* Receiver High Frequency Clock Divider */ ++#define RXSERCLR BIT(2) /* Receiver Serializer Clear */ ++#define RXSMRST BIT(3) /* Receiver State Machine Reset */ ++#define RXFSRST BIT(4) /* Frame Sync Generator Reset */ ++#define TXCLKRST BIT(8) /* Transmitter Clock Divider Reset */ ++#define TXHCLKRST BIT(9) /* Transmitter High Frequency Clock Divider*/ ++#define TXSERCLR BIT(10) /* Transmit Serializer Clear */ ++#define TXSMRST BIT(11) /* Transmitter State Machine Reset */ ++#define TXFSRST BIT(12) /* Frame Sync Generator Reset */ ++ ++/* ++ * DAVINCI_MCASP_AMUTE_REG - Mute Control Register Bits ++ */ ++#define MUTENA(val) (val) ++#define MUTEINPOL BIT(2) ++#define MUTEINENA BIT(3) ++#define MUTEIN BIT(4) ++#define MUTER BIT(5) ++#define MUTEX BIT(6) ++#define MUTEFSR BIT(7) ++#define MUTEFSX BIT(8) ++#define MUTEBADCLKR BIT(9) ++#define MUTEBADCLKX BIT(10) ++#define MUTERXDMAERR BIT(11) ++#define MUTETXDMAERR BIT(12) ++ ++/* ++ * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits ++ */ ++#define RXDATADMADIS BIT(0) ++ ++/* ++ * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits ++ */ ++#define TXDATADMADIS BIT(0) ++ ++/* ++ * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits ++ */ ++#define FIFO_ENABLE BIT(16) ++#define NUMEVT_MASK (0xFF << 8) ++#define NUMDMA_MASK (0xFF) ++ ++#define DAVINCI_MCASP_NUM_SERIALIZER 16 ++ ++static inline void mcasp_set_bits(void __iomem *reg, u32 val) ++{ ++ __raw_writel(__raw_readl(reg) | val, reg); ++} ++ ++static inline void mcasp_clr_bits(void __iomem *reg, u32 val) ++{ ++ __raw_writel((__raw_readl(reg) & ~(val)), reg); ++} ++ ++static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask) ++{ ++ __raw_writel((__raw_readl(reg) & ~mask) | val, reg); ++} ++ ++static inline void mcasp_set_reg(void __iomem *reg, u32 val) ++{ ++ __raw_writel(val, reg); ++} ++ ++static inline u32 mcasp_get_reg(void __iomem *reg) ++{ ++ return (unsigned int)__raw_readl(reg); ++} ++ ++static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val) ++{ ++// int i = 0; ++// ++// mcasp_set_bits(regs, val); ++// ++// /* programming GBLCTL needs to read back from GBLCTL and verfiy */ ++// /* loop count is to avoid the lock-up */ ++// for (i = 0; i < 1000; i++) { ++// if ((mcasp_get_reg(regs) & val) == val) ++// break; ++// } ++// ++// if (i == 1000 && ((mcasp_get_reg(regs) & val) != val)) ++// printk(KERN_ERR "GBLCTL write error\n"); ++} ++ ++static void mcasp_start_rx(struct davinci_audio_dev *dev) ++{ ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); ++// ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); ++// ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); ++} ++ ++static void mcasp_start_tx(struct davinci_audio_dev *dev) ++{ ++// u8 offset = 0, i; ++// u32 cnt; ++// ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); ++// ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); ++// mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); ++// for (i = 0; i < dev->num_serializer; i++) { ++// if (dev->serial_dir[i] == TX_MODE) { ++// offset = i; ++// break; ++// } ++// } ++// ++// /* wait for TX ready */ ++// cnt = 0; ++// while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & ++// TXSTATE) && (cnt < 100000)) ++// cnt++; ++// ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); ++} ++ ++static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) ++{ ++// if (stream == SNDRV_PCM_STREAM_PLAYBACK) { ++// if (dev->txnumevt) /* enable FIFO */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, ++// FIFO_ENABLE); ++// mcasp_start_tx(dev); ++// } else { ++// if (dev->rxnumevt) /* enable FIFO */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, ++// FIFO_ENABLE); ++// mcasp_start_rx(dev); ++// } ++} ++ ++static void mcasp_stop_rx(struct davinci_audio_dev *dev) ++{ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); ++} ++ ++static void mcasp_stop_tx(struct davinci_audio_dev *dev) ++{ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); ++} ++ ++static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) ++{ ++// if (stream == SNDRV_PCM_STREAM_PLAYBACK) { ++// if (dev->txnumevt) /* disable FIFO */ ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, ++// FIFO_ENABLE); ++// mcasp_stop_tx(dev); ++// } else { ++// if (dev->rxnumevt) /* disable FIFO */ ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, ++// FIFO_ENABLE); ++// mcasp_stop_rx(dev); ++// } ++} ++ ++static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, ++ unsigned int fmt) ++{ ++// struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++// void __iomem *base = dev->base; ++// ++// switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++// case SND_SOC_DAIFMT_CBS_CFS: ++// /* codec is clock and frame slave */ ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); ++// mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); ++// ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); ++// mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); ++// ++// mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ++// ACLKX | AHCLKX | AFSX); ++// break; ++// case SND_SOC_DAIFMT_CBM_CFS: ++// /* codec is clock master and frame slave */ ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); ++// mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); ++// mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, ++// ACLKX | ACLKR); ++// mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ++// AFSX | AFSR); ++// break; ++// case SND_SOC_DAIFMT_CBM_CFM: ++// /* codec is clock and frame master */ ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); ++// mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); ++// mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, ++// ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR); ++// break; ++// ++// default: ++// return -EINVAL; ++// } ++// ++// switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++// case SND_SOC_DAIFMT_IB_NF: ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); ++// mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); ++// ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); ++// mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); ++// break; ++// ++// case SND_SOC_DAIFMT_NB_IF: ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); ++// mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); ++// mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); ++// break; ++// ++// case SND_SOC_DAIFMT_IB_IF: ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); ++// mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); ++// ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); ++// mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); ++// break; ++// ++// case SND_SOC_DAIFMT_NB_NF: ++// mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); ++// mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); ++// ++// mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); ++// mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); ++// break; ++// ++// default: ++// return -EINVAL; ++// } ++ ++ return 0; ++} ++ ++static int davinci_config_channel_size(struct davinci_audio_dev *dev, ++ int channel_size) ++{ ++// u32 fmt = 0; ++// u32 mask, rotate; ++// ++// switch (channel_size) { ++// case DAVINCI_AUDIO_WORD_8: ++// fmt = 0x03; ++// rotate = 6; ++// mask = 0x000000ff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_12: ++// fmt = 0x05; ++// rotate = 5; ++// mask = 0x00000fff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_16: ++// fmt = 0x07; ++// rotate = 4; ++// mask = 0x0000ffff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_20: ++// fmt = 0x09; ++// rotate = 3; ++// mask = 0x000fffff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_24: ++// fmt = 0x0B; ++// rotate = 2; ++// mask = 0x00ffffff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_28: ++// fmt = 0x0D; ++// rotate = 1; ++// mask = 0x0fffffff; ++// break; ++// ++// case DAVINCI_AUDIO_WORD_32: ++// fmt = 0x0F; ++// rotate = 0; ++// mask = 0xffffffff; ++// break; ++// ++// default: ++// return -EINVAL; ++// } ++// ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, ++// RXSSZ(fmt), RXSSZ(0x0F)); ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, ++// TXSSZ(fmt), TXSSZ(0x0F)); ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate), ++// TXROT(7)); ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate), ++// RXROT(7)); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask); ++// ++// return 0; ++} ++ ++static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) ++{ ++// int i; ++// u8 tx_ser = 0; ++// u8 rx_ser = 0; ++// ++// /* Default configuration */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); ++// ++// /* All PINS as McASP */ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); ++// ++// if (stream == SNDRV_PCM_STREAM_PLAYBACK) { ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, ++// TXDATADMADIS); ++// } else { ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, ++// RXDATADMADIS); ++// } ++// ++// for (i = 0; i < dev->num_serializer; i++) { ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), ++// dev->serial_dir[i]); ++// if (dev->serial_dir[i] == TX_MODE) { ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, ++// AXR(i)); ++// tx_ser++; ++// } else if (dev->serial_dir[i] == RX_MODE) { ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, ++// AXR(i)); ++// rx_ser++; ++// } ++// } ++// ++// if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { ++// if (dev->txnumevt * tx_ser > 64) ++// dev->txnumevt = 1; ++// ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, ++// NUMDMA_MASK); ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, ++// ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); ++// } ++// ++// if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { ++// if (dev->rxnumevt * rx_ser > 64) ++// dev->rxnumevt = 1; ++// ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, ++// NUMDMA_MASK); ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, ++// ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); ++// } ++} ++ ++static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) ++{ ++// int i, active_slots; ++// u32 mask = 0; ++// ++// active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; ++// for (i = 0; i < active_slots; i++) ++// mask |= (1 << i); ++// ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); ++// ++// if (stream == SNDRV_PCM_STREAM_PLAYBACK) { ++// /* bit stream is MSB first with no delay */ ++// /* DSP_B mode */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, ++// AHCLKXE); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); ++// ++// if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, ++// FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); ++// else ++// printk(KERN_ERR "playback tdm slot %d not supported\n", ++// dev->tdm_slots); ++// ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); ++// } else { ++// /* bit stream is MSB first with no delay */ ++// /* DSP_B mode */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, ++// AHCLKRE); ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); ++// ++// if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32)) ++// mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, ++// FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); ++// else ++// printk(KERN_ERR "capture tdm slot %d not supported\n", ++// dev->tdm_slots); ++// ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); ++// } ++} ++ ++/* S/PDIF */ ++static void davinci_hw_dit_param(struct davinci_audio_dev *dev) ++{ ++// /* Set the PDIR for Serialiser as output */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); ++// ++// /* TXMASK for 24 bits */ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); ++// ++// /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 ++// and LSB first */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, ++// TXROT(6) | TXSSZ(15)); ++// ++// /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, ++// AFSXE | FSXMOD(0x180)); ++// ++// /* Set the TX tdm : for all the slots */ ++// mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); ++// ++// /* Set the TX clock controls : div = 1 and internal */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, ++// ACLKXE | TX_ASYNC); ++// ++// mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); ++// ++// /* Only 44100 and 48000 are valid, both have the same setting */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); ++// ++// /* Enable the DIT */ ++// mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); ++} ++ ++static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *cpu_dai) ++{ ++// struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++// struct davinci_pcm_dma_params *dma_params = ++// &dev->dma_params[substream->stream]; ++// int word_length; ++// u8 fifo_level; ++// ++// davinci_hw_common_param(dev, substream->stream); ++// if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++// fifo_level = dev->txnumevt; ++// else ++// fifo_level = dev->rxnumevt; ++// ++// if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) ++// davinci_hw_dit_param(dev); ++// else ++// davinci_hw_param(dev, substream->stream); ++// ++// switch (params_format(params)) { ++// case SNDRV_PCM_FORMAT_S8: ++// dma_params->data_type = 1; ++// word_length = DAVINCI_AUDIO_WORD_8; ++// break; ++// ++// case SNDRV_PCM_FORMAT_S16_LE: ++// dma_params->data_type = 2; ++// word_length = DAVINCI_AUDIO_WORD_16; ++// break; ++// ++// case SNDRV_PCM_FORMAT_S32_LE: ++// dma_params->data_type = 4; ++// word_length = DAVINCI_AUDIO_WORD_32; ++// break; ++// ++// default: ++// printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); ++// return -EINVAL; ++// } ++// ++// if (dev->version == MCASP_VERSION_2 && !fifo_level) ++// dma_params->acnt = 4; ++// else ++// dma_params->acnt = dma_params->data_type; ++// ++// dma_params->fifo_level = fifo_level; ++// davinci_config_channel_size(dev, word_length); ++ ++ return 0; ++} ++ ++static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, ++ int cmd, struct snd_soc_dai *cpu_dai) ++{ ++ struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); ++ int ret = 0; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ if (!dev->clk_active) { ++ clk_enable(dev->clk); ++ dev->clk_active = 1; ++ } ++ davinci_mcasp_start(dev, substream->stream); ++ break; ++ ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ davinci_mcasp_stop(dev, substream->stream); ++ if (dev->clk_active) { ++ clk_disable(dev->clk); ++ dev->clk_active = 0; ++ } ++ ++ break; ++ ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ davinci_mcasp_stop(dev, substream->stream); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int davinci_mcasp_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ //snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); ++ return 0; ++} ++ ++static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { ++ .startup = davinci_mcasp_startup, ++ .trigger = davinci_mcasp_trigger, ++ .hw_params = davinci_mcasp_hw_params, ++ .set_fmt = davinci_mcasp_set_dai_fmt, ++ ++}; ++ ++static struct snd_soc_dai_driver davinci_mcasp_dai[] = { ++ { ++ .name = "davinci-mcasp.0", ++ .playback = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = DAVINCI_MCASP_RATES, ++ .formats = SNDRV_PCM_FMTBIT_S8 | ++ SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ }, ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = DAVINCI_MCASP_RATES, ++ .formats = SNDRV_PCM_FMTBIT_S8 | ++ SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ }, ++ .ops = &davinci_mcasp_dai_ops, ++ ++ }, ++ { ++ "davinci-mcasp.1", ++ .playback = { ++ .channels_min = 1, ++ .channels_max = 384, ++ .rates = DAVINCI_MCASP_RATES, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .ops = &davinci_mcasp_dai_ops, ++ }, ++ ++}; ++ ++static int davinci_mcasp_probe(struct platform_device *pdev) ++{ ++ struct davinci_pcm_dma_params *dma_data; ++ struct resource *mem, *ioarea, *res; ++ struct snd_platform_data *pdata; ++ struct davinci_audio_dev *dev; ++ int ret = 0; ++ ++ dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) { ++ dev_err(&pdev->dev, "no mem resource?\n"); ++ ret = -ENODEV; ++ goto err_release_data; ++ } ++ ++ ioarea = request_mem_region(mem->start, ++ resource_size(mem), pdev->name); ++ if (!ioarea) { ++ dev_err(&pdev->dev, "Audio region already claimed\n"); ++ ret = -EBUSY; ++ goto err_release_data; ++ } ++ ++ pdata = pdev->dev.platform_data; ++ dev->clk = clk_get(&pdev->dev, NULL); ++ if (IS_ERR(dev->clk)) { ++ ret = -ENODEV; ++ goto err_release_region; ++ } ++ ++ clk_enable(dev->clk); ++ dev->clk_active = 1; ++ ++ dev->base = ioremap(mem->start, resource_size(mem)); ++ if (!dev->base) { ++ dev_err(&pdev->dev, "ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_release_clk; ++ } ++ ++// dev->op_mode = pdata->op_mode; ++// dev->tdm_slots = pdata->tdm_slots; ++// dev->num_serializer = pdata->num_serializer; ++// dev->serial_dir = pdata->serial_dir; ++// dev->codec_fmt = pdata->codec_fmt; ++// dev->version = pdata->version; ++// dev->txnumevt = pdata->txnumevt; ++// dev->rxnumevt = pdata->rxnumevt; ++ ++// dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; ++// dma_data->asp_chan_q = pdata->asp_chan_q; ++// dma_data->ram_chan_q = pdata->ram_chan_q; ++// dma_data->sram_size = pdata->sram_size_playback; ++// dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + ++// mem->start); ++ ++ /* first TX, then RX */ ++// res = platform_get_resource(pdev, IORESOURCE_DMA, 0); ++// if (!res) { ++// dev_err(&pdev->dev, "no DMA resource\n"); ++// ret = -ENODEV; ++// goto err_iounmap; ++// } ++ ++// dma_data->channel = res->start; ++// ++// dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; ++// dma_data->asp_chan_q = pdata->asp_chan_q; ++// dma_data->ram_chan_q = pdata->ram_chan_q; ++// dma_data->sram_size = pdata->sram_size_capture; ++// dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + ++// mem->start); ++ ++// res = platform_get_resource(pdev, IORESOURCE_DMA, 1); ++// if (!res) { ++// dev_err(&pdev->dev, "no DMA resource\n"); ++// ret = -ENODEV; ++// goto err_iounmap; ++// } ++ ++// dma_data->channel = res->start; ++ dev_set_drvdata(&pdev->dev, dev); ++ ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[0]); ++ ++ if (ret != 0) ++ goto err_iounmap; ++ return 0; ++ ++err_iounmap: ++ iounmap(dev->base); ++err_release_clk: ++ clk_disable(dev->clk); ++ clk_put(dev->clk); ++err_release_region: ++ release_mem_region(mem->start, resource_size(mem)); ++err_release_data: ++ kfree(dev); ++ ++ return ret; ++} ++ ++static int davinci_mcasp_remove(struct platform_device *pdev) ++{ ++ struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); ++ struct resource *mem; ++ ++ snd_soc_unregister_dai(&pdev->dev); ++ clk_disable(dev->clk); ++ clk_put(dev->clk); ++ dev->clk = NULL; ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ release_mem_region(mem->start, resource_size(mem)); ++ ++ kfree(dev); ++ ++ return 0; ++} ++ ++static struct platform_driver davinci_mcasp_driver = { ++ .probe = davinci_mcasp_probe, ++ .remove = davinci_mcasp_remove, ++ .driver = { ++ .name = "davinci-mcasp", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init davinci_mcasp_init(void) ++{ ++ return platform_driver_register(&davinci_mcasp_driver); ++} ++module_init(davinci_mcasp_init); ++ ++static void __exit davinci_mcasp_exit(void) ++{ ++ platform_driver_unregister(&davinci_mcasp_driver); ++} ++module_exit(davinci_mcasp_exit); ++ ++MODULE_AUTHOR("Steve Chen"); ++MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/sound/soc/dwc/fh_i2s_dai.h b/sound/soc/dwc/fh_i2s_dai.h +new file mode 100644 +index 00000000..5b2f207b +--- /dev/null ++++ b/sound/soc/dwc/fh_i2s_dai.h +@@ -0,0 +1,59 @@ ++/* ++ * ALSA SoC McASP Audio Layer for TI DAVINCI processor ++ * ++ * MCASP related definitions ++ * ++ * Author: Nirmal Pandey <n-pandey@ti.com>, ++ * Suresh Rajashekara <suresh.r@ti.com> ++ * Steve Chen <schen@.mvista.com> ++ * ++ * Copyright: (C) 2009 MontaVista Software, Inc., <source@mvista.com> ++ * Copyright: (C) 2009 Texas Instruments, India ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef DAVINCI_MCASP_H ++#define DAVINCI_MCASP_H ++ ++#include <linux/io.h> ++//#include <mach/asp.h> ++#include "fullhan-pcm.h" ++ ++#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 ++#define DAVINCI_MCASP_I2S_DAI 0 ++#define DAVINCI_MCASP_DIT_DAI 1 ++ ++enum { ++ DAVINCI_AUDIO_WORD_8 = 0, ++ DAVINCI_AUDIO_WORD_12, ++ DAVINCI_AUDIO_WORD_16, ++ DAVINCI_AUDIO_WORD_20, ++ DAVINCI_AUDIO_WORD_24, ++ DAVINCI_AUDIO_WORD_32, ++ DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */ ++}; ++ ++struct davinci_audio_dev { ++ //struct davinci_pcm_dma_params dma_params[2]; ++ void __iomem *base; ++ int sample_rate; ++ struct clk *clk; ++ unsigned int codec_fmt; ++ u8 clk_active; ++ ++ /* McASP specific data */ ++ int tdm_slots; ++ u8 op_mode; ++ u8 num_serializer; ++ u8 *serial_dir; ++ u8 version; ++ ++ /* McASP FIFO related */ ++ u8 txnumevt; ++ u8 rxnumevt; ++}; ++ ++#endif /* DAVINCI_MCASP_H */ +diff --git a/sound/soc/dwc/fullhan-pcm.c b/sound/soc/dwc/fullhan-pcm.c +new file mode 100644 +index 00000000..bd57e863 +--- /dev/null ++++ b/sound/soc/dwc/fullhan-pcm.c +@@ -0,0 +1,555 @@ ++/* ++ * ALSA PCM interface for the Stetch s6000 family ++ * ++ * Author: Daniel Gloeckner, <dg@emlix.com> ++ * Copyright: (C) 2009 emlix GmbH <info@emlix.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/dma-mapping.h> ++#include <linux/interrupt.h> ++#include <linux/kthread.h> ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <linux/delay.h> ++#include <linux/completion.h> ++#include <asm/dma.h> ++//#include <variant/dmac.h> ++#include "dma.h" ++#include "fullhan-pcm.h" ++ ++#define S6_PCM_PREALLOCATE_SIZE (96 * 1024) ++#define S6_PCM_PREALLOCATE_MAX (2048 * 1024) ++ ++ ++struct snd_pcm_substream *capture_substream,*play_substream; ++ ++ ++ ++static struct snd_pcm_hardware s6000_pcm_hardware = { .info = ++ (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX), .formats = ++ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE), .rates = ++ (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_5512 | ++ SNDRV_PCM_RATE_8000_192000), .rate_min = 0, .rate_max = 1562500, ++ .channels_min = 2, .channels_max = 8, .buffer_bytes_max = 0x7ffffff0, ++ .period_bytes_min = 16, .period_bytes_max = 0xfffff0, .periods_min = 2, ++ .periods_max = 1024, /* no limit */ ++ .fifo_size = 0, }; ++ ++struct s6000_runtime_data { ++ spinlock_t lock; ++ int period; /* current DMA period */ ++ int pos; ++}; ++ ++ ++void test_dma_copy(unsigned int src, unsigned int dst) { ++ Dma_SetTxrType(0, DMA_TTFC_M2M_DMAC); ++ Dma_SetSrcWidth(0, 2); ++ Dma_SetSrcSize(0, 0); ++ Dma_SetDstWidth(0, 2); // UART can only accept 8bits input ++ Dma_SetDstSize(0, 0); // burst size, UART has 16bytes FIFO, 1/2 thrl ++ Dma_SetSrcAddress(0, src); ++ Dma_SetDstAddress(0, dst); ++ Dma_SetSrcIncDirection(0, DMA_DIR_INC); ++ Dma_SetDstIncDirection(0, DMA_DIR_INC); ++ Dma_EnableIsrBit(0, DMA_INTT_BLOCK); // block finish ISR. ++ ++ Dma_SetTxrSize(0, 4); // copy 1K bytes. ++ ++ Dma_EnableChan(0); ++ ++} ++ ++static void copy_finish(struct snd_pcm_substream *substream ) { ++ snd_pcm_period_elapsed(substream); ++} ++ ++void i2s_irq_enquen(int type, u8 *buff, u8 len,u8 reset) ++{ ++ struct snd_pcm_substream *substream; ++ struct snd_pcm_runtime *runtime; ++ struct s6000_runtime_data *prtd; ++ static int rx_count = 0,tx_count = 0; ++ if (SNDRV_PCM_STREAM_PLAYBACK == type) { ++ if(reset){ ++ tx_count = 0; ++ return; ++ } ++ if (!play_substream) { ++ return; ++ } ++ substream = play_substream; ++ runtime = substream->runtime; ++ prtd = runtime->private_data; ++ memcpy(buff,runtime->dma_area+prtd->pos,len); ++ tx_count += len; ++ if (tx_count >= snd_pcm_lib_period_bytes(substream)) { ++ tx_count = 0; ++ copy_finish(substream); ++ } ++ } else { ++ if(reset){ ++ rx_count = 0; ++ return; ++ } ++ if(!capture_substream){ ++ return; ++ } ++ substream = capture_substream; ++ runtime = substream->runtime; ++ prtd = runtime->private_data; ++ memcpy(runtime->dma_area+prtd->pos,buff,len); ++ rx_count += len; ++ if (rx_count >= snd_pcm_lib_period_bytes(substream) ) { ++ rx_count = 0; ++ copy_finish(substream); ++ } ++ } ++ prtd->pos += len; ++ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) { ++ prtd->pos = 0; ++ } ++} ++EXPORT_SYMBOL(i2s_irq_enquen); ++ ++ ++static irqreturn_t s6000_pcm_irq(int irq, void *data) { ++// struct snd_pcm *pcm = data; ++// struct snd_soc_pcm_runtime *runtime = pcm->private_data; ++// struct s6000_runtime_data *prtd; ++// unsigned int has_xrun; ++// int i, ret = IRQ_NONE; ++// ++// for (i = 0; i < 2; ++i) { ++// struct snd_pcm_substream *substream = pcm->streams[i].substream; ++// struct s6000_pcm_dma_params *params = snd_soc_dai_get_dma_data( ++// runtime->cpu_dai, substream); ++// u32 channel; ++// unsigned int pending; ++// ++// if (substream == SNDRV_PCM_STREAM_PLAYBACK) ++// channel = params->dma_s6000_runtime_dataout; ++// else ++// channel = params->dma_in; ++// ++// has_xrun = params->check_xrun(runtime->cpu_dai); ++// ++// if (!channel) ++// continue; ++// ++// if (unlikely(has_xrun & (1 << i)) && substream->runtime ++// && snd_pcm_running(substream)) { ++// dev_dbg(pcm->dev, "xrun\n"); ++// snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); ++// ret = IRQ_HANDLED; ++// } ++// ++// pending = s6dmac_int_sources(DMA_MASK_DMAC(channel), ++// DMA_INDEX_CHNL(channel)); ++// ++// if (pending & 1) { ++// ret = IRQ_HANDLED; ++// if (likely(substream->runtime && snd_pcm_running(substream))) { ++// snd_pcm_period_elapsed(substream); ++// dev_dbg(pcm->dev, "period elapsed %x %x\n", ++// s6dmac_cur_src(DMA_MASK_DMAC(channel), ++// DMA_INDEX_CHNL(channel)), ++// s6dmac_cur_dst(DMA_MASK_DMAC(channel), ++// DMA_INDEX_CHNL(channel))); ++// prtd = substrcopy_finisheam->runtime->private_data; ++// spin_lock(&prtd->lock); ++// s6000_pcm_enqueue_dma(substream); ++// spin_unlock(&prtd->lock); ++// } ++// } ++// ++// if (unlikely(pending & ~7)) { ++// if (pending & (1 << 3)) ++// printk(KERN_WARNING ++// "s6000-pcm: DMA %x Underflow\n", ++// channel); ++// if (pending & (1 << 4)) ++// printk(KERN_WARNING ++// "s6000-pcm: DMA %x Overflow\n", ++// channel); ++// if (pending & 0x1e0) ++// printk(KERN_WARNING ++// "s6000-pcm: DMA %x Master Error " ++// "(mask %x)\n", ++// channel, pending >> 5); ++// ++// } ++//} ++ ++//return ret; ++} ++ ++static int s6000_pcm_start(struct snd_pcm_substream *substream) { ++ ++struct s6000_runtime_data *prtd = substream->runtime->private_data; ++struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++struct s6000_pcm_dma_params *par; ++unsigned long flags; ++int srcinc; ++u32 dma; ++par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++ ++//spin_lock_irqsave(&prtd->lock, flags); ++ ++if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ srcinc = 1; ++ dma = par->dma_out; ++} else { ++ srcinc = 0; ++ dma = par->dma_in; ++} ++ ++// s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma), ++// 1 /* priority 1 (0 is max) */, ++// 0 /* peripheral requests w/o xfer length mode */, ++// srcinc /* source address increment */, ++// srcinc^1 /* destination address increment */, ++// 0 /* chunksize 0 (skip impossible on this dma) */, ++// 0 /* source skip after chunk (impossible) */, ++// 0 /* destination skip after chunk (impossible) */, ++// 4 /* 16 byte burst size */, ++// -1 /* don't conserve bandwidth */, ++// 0 /* low watermark irq descriptor threshold */, ++// 0 /* disable hardware timestamps */, ++// 1 /* enable channel */); ++// prtd->period = 0; ++// s6000_pcm_enqueue_dma(substream); ++ ++//spin_unlock_irqrestore(&prtd->lock, flags); ++ ++return 0; ++} ++ ++static int s6000_pcm_stop(struct snd_pcm_substream *substream) { ++ struct s6000_runtime_data *prtd = substream->runtime->private_data; ++ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++ unsigned long flags; ++ capture_substream = play_substream = 0; ++// u32 channel; ++ ++// par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++// ++// if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++// channel = par->dma_out; ++// else ++// channel = par->dma_in; ++// ++// s6dmac_set_terminal_count(DMA_MASK_DMAC(channel), ++// DMA_INDEX_CHNL(channel), 0); ++// ++ ++ ++return 0; ++} ++ ++static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { ++ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++ struct s6000_pcm_dma_params *par; ++ int ret; ++ ++ par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++ ++ ret = par->trigger(substream, cmd, 0); ++ if (ret < 0) ++ return ret; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ i2s_irq_enquen(substream->stream,0,0,1); ++ ret = s6000_pcm_start(substream); ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ ret = s6000_pcm_stop(substream); ++ ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ if (ret < 0) ++ return ret; ++ ++ return par->trigger(substream, cmd, 1); ++} ++ ++static int s6000_pcm_prepare(struct snd_pcm_substream *substream) ++{ ++ return 0; ++} ++ ++ ++static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) { ++struct snd_pcm_runtime *runtime = substream->runtime; ++struct s6000_runtime_data *prtd = runtime->private_data; ++unsigned int offset; ++offset = bytes_to_frames(runtime, prtd->pos); ++if (unlikely(offset >= runtime->buffer_size)) ++ offset = 0; ++return offset; ++} ++ ++static int s6000_pcm_open(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++ struct s6000_pcm_dma_params *par; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ struct s6000_runtime_data *prtd; ++ int ret; ++ par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++ snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); ++ ret = snd_pcm_hw_constraint_step(runtime, 0, ++ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); ++ if (ret < 0) ++ return ret; ++ ret = snd_pcm_hw_constraint_step(runtime, 0, ++ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); ++ if (ret < 0) ++ return ret; ++ ret = snd_pcm_hw_constraint_integer(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS); ++ if (ret < 0) ++ return ret; ++ ++ ++ ++ ++ // if (par->same_rate) { ++ // printk("s6000 pcm open 5.0\n"); ++ // int rate; ++ // spin_lock(&par->lock); /* needed? */ ++ // rate = par->rate; ++ // spin_unlock(&par->lock); ++ // printk("s6000 pcm open 5.1\n"); ++ // if (rate != -1) { ++ // ret = snd_pcm_hw_constraint_minmax(runtime, ++ // SNDRV_PCM_HW_PARAM_RATE, ++ // rate, rate); ++ // printk("s6000 pcm open 5.2\n"); ++ // if (ret < 0) ++ // return ret; ++ // } ++ // } ++ prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL); ++ if (prtd == NULL) ++ return -ENOMEM; ++ ++ spin_lock_init(&prtd->lock); ++ prtd->period = 0; ++ prtd->pos = 0; ++ runtime->private_data = prtd; ++ /*remember to judge capture or play stream*/ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ play_substream = substream; ++ }else { ++ capture_substream = substream; ++ } ++ //irq_emulation(); ++ return 0; ++} ++ ++static int s6000_pcm_close(struct snd_pcm_substream *substream) { ++ struct s6000_runtime_data *prtd = substream->runtime->private_data; ++ unsigned long flags; ++ spin_lock_irqsave(&prtd->lock, flags); ++ kfree(prtd); ++ spin_unlock_irqrestore(&prtd->lock, flags); ++return 0; ++} ++ ++static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *hw_params) { ++struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++struct s6000_pcm_dma_params *par; ++int ret; ++ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); ++if (ret < 0) { ++ printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n"); ++ return ret; ++} ++par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++ ++ if (par->same_rate) { ++ spin_lock(&par->lock); ++ if (par->rate == -1 || ++ !(par->in_use & ~(1 << substream->stream))) { ++ par->rate = params_rate(hw_params); ++ par->in_use |= 1 << substream->stream; ++ } else if (params_rate(hw_params) != par->rate) { ++ snd_pcm_lib_free_pages(substream); ++ par->in_use &= ~(1 << substream->stream); ++ ret = -EBUSY; ++ } ++ spin_unlock(&par->lock); ++ } ++ return ret; ++} ++ ++static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) { ++ struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; ++ struct s6000_pcm_dma_params *par = ++ snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream); ++ ++ spin_lock(&par->lock); ++ par->in_use &= ~(1 << substream->stream); ++ if (!par->in_use) ++ par->rate = -1; ++ spin_unlock(&par->lock); ++ ++ return snd_pcm_lib_free_pages(substream); ++} ++int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, ++ struct vm_area_struct *vma) { ++struct snd_pcm_runtime *runtime = substream->runtime; ++return dma_mmap_writecombine(substream->pcm->card->dev, vma, runtime->dma_area, ++ runtime->dma_addr, runtime->dma_bytes); ++} ++int s6000_pcm_copy(struct snd_pcm_substream *substream, int channel, ++ snd_pcm_uframes_t pos, void __user *buf, snd_pcm_uframes_t count) { ++ ++ ++return 0; ++} ++static struct snd_pcm_ops s6000_pcm_ops = { .copy = s6000_pcm_copy, .open = ++ s6000_pcm_open, .close = s6000_pcm_close, .ioctl = snd_pcm_lib_ioctl, ++ .hw_params = s6000_pcm_hw_params, .hw_free = s6000_pcm_hw_free, .trigger = ++ s6000_pcm_trigger, .prepare = s6000_pcm_prepare, .pointer = ++ s6000_pcm_pointer, ++// .mmap=pxa2xx_pcm_mmap, ++ }; ++ ++static void s6000_pcm_free(struct snd_pcm *pcm) { ++// struct snd_soc_pcm_runtime *runtime = pcm->private_data; ++// struct s6000_pcm_dma_params *params = ++// snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream); ++// ++// free_irq(params->irq, pcm); ++// snd_pcm_lib_preallocate_free_for_all(pcm); ++} ++ ++static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32); ++static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, ++ size_t size) { ++struct snd_pcm_substream *substream = pcm->streams[stream].substream; ++struct snd_dma_buffer *buf = &substream->dma_buffer; ++ ++buf->dev.type = SNDRV_DMA_TYPE_DEV; ++buf->dev.dev = pcm->card->dev; ++buf->private_data = NULL; ++buf->area = dma_alloc_writecombine(pcm->card->dev, size, &buf->addr, ++GFP_KERNEL); ++pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, " ++ "size=%d\n", (void *) buf->area, (void *) buf->addr, size); ++ ++if (!buf->area) ++ return -ENOMEM; ++ ++buf->bytes = size; ++return 0; ++} ++static u64 davinci_pcm_dmamask = 0xffffffff; ++ ++static int s6000_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, ++ struct snd_pcm *pcm) { ++struct snd_soc_pcm_runtime *runtime = pcm->private_data; ++struct s6000_pcm_dma_params *params; ++int res; ++int ret; ++ ++#if 0 ++if (dai->driver->playback.channels_min) { ++ ret = davinci_pcm_preallocate_dma_buffer(pcm, ++ SNDRV_PCM_STREAM_PLAYBACK, ++ pcm_hardware_playback.buffer_bytes_max); ++ if (ret) ++ return ret; ++} ++ ++if (dai->driver->capture.channels_min) { ++ ret = davinci_pcm_preallocate_dma_buffer(pcm, ++ SNDRV_PCM_STREAM_CAPTURE, ++ pcm_hardware_capture.buffer_bytes_max); ++ if (ret) ++ return ret; ++} ++#endif ++params = snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream); ++if (!card->dev->dma_mask) ++ card->dev->dma_mask = &s6000_pcm_dmamask; ++if (!card->dev->coherent_dma_mask) ++ card->dev->coherent_dma_mask = DMA_BIT_MASK(32); ++ ++ ++res = snd_pcm_lib_preallocate_pages_for_all(pcm, ++SNDRV_DMA_TYPE_DEV, card->dev, ++S6_PCM_PREALLOCATE_SIZE, ++S6_PCM_PREALLOCATE_MAX); ++if (res) ++printk(KERN_WARNING "s6000-pcm: preallocation failed\n"); ++ ++ ++return 0; ++} ++ ++static struct snd_soc_platform_driver s6000_soc_platform = { .ops = ++ &s6000_pcm_ops, .pcm_new = s6000_pcm_new, .pcm_free = s6000_pcm_free, }; ++ ++static int __devinit s6000_soc_platform_probe(struct platform_device *pdev) ++{ ++void * dw; ++int err,irq; ++ ++err = request_irq(9, s6000_pcm_irq, 0, "dw_dmac", dw); ++if (err) { ++ ++ printk("pcm dma interrput err \n"); ++} ++return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform); ++} ++ ++static int __devexit s6000_soc_platform_remove(struct platform_device *pdev) ++{ ++snd_soc_unregister_platform(&pdev->dev); ++return 0; ++} ++ ++static struct platform_driver s6000_pcm_driver = { .driver = { .name = ++ "fh-pcm-audio", .owner = THIS_MODULE, }, ++ ++.probe = s6000_soc_platform_probe, .remove = __devexit_p( ++ s6000_soc_platform_remove), }; ++ ++static int __init snd_s6000_pcm_init(void) ++{ ++ ++ return platform_driver_register(&s6000_pcm_driver); ++} ++module_init(snd_s6000_pcm_init); ++ ++static void __exit snd_s6000_pcm_exit(void) ++{ ++ platform_driver_unregister(&s6000_pcm_driver); ++} ++module_exit(snd_s6000_pcm_exit); ++ ++MODULE_AUTHOR("Daniel Gloeckner"); ++MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/dwc/fullhan-pcm.h b/sound/soc/dwc/fullhan-pcm.h +new file mode 100644 +index 00000000..09d9b883 +--- /dev/null ++++ b/sound/soc/dwc/fullhan-pcm.h +@@ -0,0 +1,33 @@ ++/* ++ * ALSA PCM interface for the Stretch s6000 family ++ * ++ * Author: Daniel Gloeckner, <dg@emlix.com> ++ * Copyright: (C) 2009 emlix GmbH <info@emlix.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _S6000_PCM_H ++#define _S6000_PCM_H ++ ++struct snd_soc_dai; ++struct snd_pcm_substream; ++ ++struct s6000_pcm_dma_params { ++ unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai); ++ int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after); ++ dma_addr_t sif_in; ++ dma_addr_t sif_out; ++ u32 dma_in; ++ u32 dma_out; ++ int irq; ++ int same_rate; ++ ++ spinlock_t lock; ++ int in_use; ++ int rate; ++}; ++ ++#endif +diff --git a/tools/perf/Makefile b/tools/perf/Makefile +index c1683661..d5d628fb 100644 +--- a/tools/perf/Makefile ++++ b/tools/perf/Makefile +@@ -96,7 +96,7 @@ ifndef PERF_DEBUG + endif + + CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) +-EXTLIBS = -lpthread -lrt -lelf -lm ++EXTLIBS = -lpthread -lrt -lelf -lm -lebl -lz -ldl + ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + ALL_LDFLAGS = $(LDFLAGS) + STRIP ?= strip +diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c +index 3b9d0b80..4e93e8ce 100644 +--- a/tools/perf/util/probe-finder.c ++++ b/tools/perf/util/probe-finder.c +@@ -18,25 +18,14 @@ + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +- ++#include "util.h" + #include <sys/utsname.h> +-#include <sys/types.h> +-#include <sys/stat.h> +-#include <fcntl.h> +-#include <errno.h> +-#include <stdio.h> +-#include <unistd.h> + #include <getopt.h> +-#include <stdlib.h> +-#include <string.h> +-#include <stdarg.h> +-#include <ctype.h> + #include <dwarf-regs.h> + + #include <linux/bitops.h> + #include "event.h" + #include "debug.h" +-#include "util.h" + #include "symbol.h" + #include "probe-finder.h" + +diff --git a/usr/rootfs.cpio.gz b/usr/rootfs.cpio.gz +new file mode 100644 +index 00000000..35e40a30 +Binary files /dev/null and b/usr/rootfs.cpio.gz differ diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/10_overlayfs.v11.patch b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/10_overlayfs.v11.patch new file mode 100644 index 00000000..1dccf7b1 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/10_overlayfs.v11.patch @@ -0,0 +1,3176 @@ +--- /dev/null ++++ b/Documentation/filesystems/overlayfs.txt +@@ -0,0 +1,199 @@ ++Written by: Neil Brown <neilb@suse.de> ++ ++Overlay Filesystem ++================== ++ ++This document describes a prototype for a new approach to providing ++overlay-filesystem functionality in Linux (sometimes referred to as ++union-filesystems). An overlay-filesystem tries to present a ++filesystem which is the result over overlaying one filesystem on top ++of the other. ++ ++The result will inevitably fail to look exactly like a normal ++filesystem for various technical reasons. The expectation is that ++many use cases will be able to ignore these differences. ++ ++This approach is 'hybrid' because the objects that appear in the ++filesystem do not all appear to belong to that filesystem. In many ++cases an object accessed in the union will be indistinguishable ++from accessing the corresponding object from the original filesystem. ++This is most obvious from the 'st_dev' field returned by stat(2). ++ ++While directories will report an st_dev from the overlay-filesystem, ++all non-directory objects will report an st_dev from the lower or ++upper filesystem that is providing the object. Similarly st_ino will ++only be unique when combined with st_dev, and both of these can change ++over the lifetime of a non-directory object. Many applications and ++tools ignore these values and will not be affected. ++ ++Upper and Lower ++--------------- ++ ++An overlay filesystem combines two filesystems - an 'upper' filesystem ++and a 'lower' filesystem. When a name exists in both filesystems, the ++object in the 'upper' filesystem is visible while the object in the ++'lower' filesystem is either hidden or, in the case of directories, ++merged with the 'upper' object. ++ ++It would be more correct to refer to an upper and lower 'directory ++tree' rather than 'filesystem' as it is quite possible for both ++directory trees to be in the same filesystem and there is no ++requirement that the root of a filesystem be given for either upper or ++lower. ++ ++The lower filesystem can be any filesystem supported by Linux and does ++not need to be writable. The lower filesystem can even be another ++overlayfs. The upper filesystem will normally be writable and if it ++is it must support the creation of trusted.* extended attributes, and ++must provide valid d_type in readdir responses, at least for symbolic ++links - so NFS is not suitable. ++ ++A read-only overlay of two read-only filesystems may use any ++filesystem type. ++ ++Directories ++----------- ++ ++Overlaying mainly involved directories. If a given name appears in both ++upper and lower filesystems and refers to a non-directory in either, ++then the lower object is hidden - the name refers only to the upper ++object. ++ ++Where both upper and lower objects are directories, a merged directory ++is formed. ++ ++At mount time, the two directories given as mount options are combined ++into a merged directory: ++ ++ mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper /overlay ++ ++Then whenever a lookup is requested in such a merged directory, the ++lookup is performed in each actual directory and the combined result ++is cached in the dentry belonging to the overlay filesystem. If both ++actual lookups find directories, both are stored and a merged ++directory is created, otherwise only one is stored: the upper if it ++exists, else the lower. ++ ++Only the lists of names from directories are merged. Other content ++such as metadata and extended attributes are reported for the upper ++directory only. These attributes of the lower directory are hidden. ++ ++whiteouts and opaque directories ++-------------------------------- ++ ++In order to support rm and rmdir without changing the lower ++filesystem, an overlay filesystem needs to record in the upper filesystem ++that files have been removed. This is done using whiteouts and opaque ++directories (non-directories are always opaque). ++ ++The overlay filesystem uses extended attributes with a ++"trusted.overlay." prefix to record these details. ++ ++A whiteout is created as a symbolic link with target ++"(overlay-whiteout)" and with xattr "trusted.overlay.whiteout" set to "y". ++When a whiteout is found in the upper level of a merged directory, any ++matching name in the lower level is ignored, and the whiteout itself ++is also hidden. ++ ++A directory is made opaque by setting the xattr "trusted.overlay.opaque" ++to "y". Where the upper filesystem contains an opaque directory, any ++directory in the lower filesystem with the same name is ignored. ++ ++readdir ++------- ++ ++When a 'readdir' request is made on a merged directory, the upper and ++lower directories are each read and the name lists merged in the ++obvious way (upper is read first, then lower - entries that already ++exist are not re-added). This merged name list is cached in the ++'struct file' and so remains as long as the file is kept open. If the ++directory is opened and read by two processes at the same time, they ++will each have separate caches. A seekdir to the start of the ++directory (offset 0) followed by a readdir will cause the cache to be ++discarded and rebuilt. ++ ++This means that changes to the merged directory do not appear while a ++directory is being read. This is unlikely to be noticed by many ++programs. ++ ++seek offsets are assigned sequentially when the directories are read. ++Thus if ++ - read part of a directory ++ - remember an offset, and close the directory ++ - re-open the directory some time later ++ - seek to the remembered offset ++ ++there may be little correlation between the old and new locations in ++the list of filenames, particularly if anything has changed in the ++directory. ++ ++Readdir on directories that are not merged is simply handled by the ++underlying directory (upper or lower). ++ ++ ++Non-directories ++--------------- ++ ++Objects that are not directories (files, symlinks, device-special ++files etc.) are presented either from the upper or lower filesystem as ++appropriate. When a file in the lower filesystem is accessed in a way ++the requires write-access, such as opening for write access, changing ++some metadata etc., the file is first copied from the lower filesystem ++to the upper filesystem (copy_up). Note that creating a hard-link ++also requires copy_up, though of course creation of a symlink does ++not. ++ ++The copy_up may turn out to be unnecessary, for example if the file is ++opened for read-write but the data is not modified. ++ ++The copy_up process first makes sure that the containing directory ++exists in the upper filesystem - creating it and any parents as ++necessary. It then creates the object with the same metadata (owner, ++mode, mtime, symlink-target etc.) and then if the object is a file, the ++data is copied from the lower to the upper filesystem. Finally any ++extended attributes are copied up. ++ ++Once the copy_up is complete, the overlay filesystem simply ++provides direct access to the newly created file in the upper ++filesystem - future operations on the file are barely noticed by the ++overlay filesystem (though an operation on the name of the file such as ++rename or unlink will of course be noticed and handled). ++ ++ ++Non-standard behavior ++--------------------- ++ ++The copy_up operation essentially creates a new, identical file and ++moves it over to the old name. The new file may be on a different ++filesystem, so both st_dev and st_ino of the file may change. ++ ++Any open files referring to this inode will access the old data and ++metadata. Similarly any file locks obtained before copy_up will not ++apply to the copied up file. ++ ++On a file is opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) ++and fsetxattr(2) will fail with EROFS. ++ ++If a file with multiple hard links is copied up, then this will ++"break" the link. Changes will not be propagated to other names ++referring to the same inode. ++ ++Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory ++object in overlayfs will not contain vaid absolute paths, only ++relative paths leading up to the filesystem's root. This will be ++fixed in the future. ++ ++Some operations are not atomic, for example a crash during copy_up or ++rename will leave the filesystem in an inconsitent state. This will ++be addressed in the future. ++ ++Changes to underlying filesystems ++--------------------------------- ++ ++Offline changes, when the overlay is not mounted, are allowed to either ++the upper or the lower trees. ++ ++Changes to the underlying filesystems while part of a mounted overlay ++filesystem are not allowed. If the underlying filesystem is changed, ++the behavior of the overlay is undefined, though it will not result in ++a crash or deadlock. +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4727,6 +4727,13 @@ F: drivers/scsi/osd/ + F: include/scsi/osd_* + F: fs/exofs/ + ++OVERLAYFS FILESYSTEM ++M: Miklos Szeredi <miklos@szeredi.hu> ++L: linux-fsdevel@vger.kernel.org ++S: Supported ++F: fs/overlayfs/* ++F: Documentation/filesystems/overlayfs.txt ++ + P54 WIRELESS DRIVER + M: Christian Lamparter <chunkeey@googlemail.com> + L: linux-wireless@vger.kernel.org +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -63,6 +63,7 @@ source "fs/quota/Kconfig" + + source "fs/autofs4/Kconfig" + source "fs/fuse/Kconfig" ++source "fs/overlayfs/Kconfig" + + config CUSE + tristate "Character device in Userspace support" +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -105,6 +105,7 @@ obj-$(CONFIG_QNX4FS_FS) += qnx4/ + obj-$(CONFIG_AUTOFS4_FS) += autofs4/ + obj-$(CONFIG_ADFS_FS) += adfs/ + obj-$(CONFIG_FUSE_FS) += fuse/ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs/ + obj-$(CONFIG_UDF_FS) += udf/ + obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ + obj-$(CONFIG_OMFS_FS) += omfs/ +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -544,6 +544,13 @@ static struct dentry *ecryptfs_mount(str + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; + s->s_magic = ECRYPTFS_SUPER_MAGIC; ++ s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1; ++ ++ rc = -EINVAL; ++ if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ printk(KERN_ERR "eCryptfs: maximum fs stacking depth exceeded\n"); ++ goto out_free; ++ } + + inode = ecryptfs_get_inode(path.dentry->d_inode, s); + rc = PTR_ERR(inode); +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1492,6 +1492,23 @@ void drop_collected_mounts(struct vfsmou + release_mounts(&umount_list); + } + ++struct vfsmount *clone_private_mount(struct path *path) ++{ ++ struct vfsmount *mnt; ++ ++ if (IS_MNT_UNBINDABLE(path->mnt)) ++ return ERR_PTR(-EINVAL); ++ ++ down_read(&namespace_sem); ++ mnt = clone_mnt(path->mnt, path->dentry, CL_PRIVATE); ++ up_read(&namespace_sem); ++ if (!mnt) ++ return ERR_PTR(-ENOMEM); ++ ++ return mnt; ++} ++EXPORT_SYMBOL_GPL(clone_private_mount); ++ + int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, + struct vfsmount *root) + { +--- a/fs/open.c ++++ b/fs/open.c +@@ -666,8 +666,7 @@ static inline int __get_file_write_acces + return error; + } + +-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, +- struct file *f, ++static struct file *__dentry_open(struct path *path, struct file *f, + int (*open)(struct inode *, struct file *), + const struct cred *cred) + { +@@ -675,15 +674,16 @@ static struct file *__dentry_open(struct + struct inode *inode; + int error; + ++ path_get(path); + f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | + FMODE_PREAD | FMODE_PWRITE; + + if (unlikely(f->f_flags & O_PATH)) + f->f_mode = FMODE_PATH; + +- inode = dentry->d_inode; ++ inode = path->dentry->d_inode; + if (f->f_mode & FMODE_WRITE) { +- error = __get_file_write_access(inode, mnt); ++ error = __get_file_write_access(inode, path->mnt); + if (error) + goto cleanup_file; + if (!special_file(inode->i_mode)) +@@ -691,8 +691,7 @@ static struct file *__dentry_open(struct + } + + f->f_mapping = inode->i_mapping; +- f->f_path.dentry = dentry; +- f->f_path.mnt = mnt; ++ f->f_path = *path; + f->f_pos = 0; + file_sb_list_add(f, inode->i_sb); + +@@ -745,7 +744,7 @@ cleanup_all: + * here, so just reset the state. + */ + file_reset_write(f); +- mnt_drop_write(mnt); ++ mnt_drop_write(path->mnt); + } + } + file_sb_list_del(f); +@@ -753,8 +752,7 @@ cleanup_all: + f->f_path.mnt = NULL; + cleanup_file: + put_filp(f); +- dput(dentry); +- mntput(mnt); ++ path_put(path); + return ERR_PTR(error); + } + +@@ -780,14 +778,14 @@ cleanup_file: + struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, + int (*open)(struct inode *, struct file *)) + { ++ struct path path = { .dentry = dentry, .mnt = nd->path.mnt }; + const struct cred *cred = current_cred(); + + if (IS_ERR(nd->intent.open.file)) + goto out; + if (IS_ERR(dentry)) + goto out_err; +- nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), +- nd->intent.open.file, ++ nd->intent.open.file = __dentry_open(&path, nd->intent.open.file, + open, cred); + out: + return nd->intent.open.file; +@@ -816,10 +814,17 @@ struct file *nameidata_to_filp(struct na + + /* Has the filesystem initialised the file for us? */ + if (filp->f_path.dentry == NULL) { +- path_get(&nd->path); +- filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, +- NULL, cred); ++ struct inode *inode = nd->path.dentry->d_inode; ++ ++ if (inode->i_op->open) { ++ int flags = filp->f_flags; ++ put_filp(filp); ++ filp = inode->i_op->open(nd->path.dentry, flags, cred); ++ } else { ++ filp = __dentry_open(&nd->path, filp, NULL, cred); ++ } + } ++ + return filp; + } + +@@ -830,26 +835,45 @@ struct file *nameidata_to_filp(struct na + struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, + const struct cred *cred) + { +- int error; +- struct file *f; +- +- validate_creds(cred); ++ struct path path = { .dentry = dentry, .mnt = mnt }; ++ struct file *ret; + + /* We must always pass in a valid mount pointer. */ + BUG_ON(!mnt); + +- error = -ENFILE; ++ ret = vfs_open(&path, flags, cred); ++ path_put(&path); ++ ++ return ret; ++} ++EXPORT_SYMBOL(dentry_open); ++ ++/** ++ * vfs_open - open the file at the given path ++ * @path: path to open ++ * @flags: open flags ++ * @cred: credentials to use ++ * ++ * Open the file. If successful, the returned file will have acquired ++ * an additional reference for path. ++ */ ++struct file *vfs_open(struct path *path, int flags, const struct cred *cred) ++{ ++ struct file *f; ++ struct inode *inode = path->dentry->d_inode; ++ ++ validate_creds(cred); ++ ++ if (inode->i_op->open) ++ return inode->i_op->open(path->dentry, flags, cred); + f = get_empty_filp(); +- if (f == NULL) { +- dput(dentry); +- mntput(mnt); +- return ERR_PTR(error); +- } ++ if (f == NULL) ++ return ERR_PTR(-ENFILE); + + f->f_flags = flags; +- return __dentry_open(dentry, mnt, f, NULL, cred); ++ return __dentry_open(path, f, NULL, cred); + } +-EXPORT_SYMBOL(dentry_open); ++EXPORT_SYMBOL(vfs_open); + + static void __put_unused_fd(struct files_struct *files, unsigned int fd) + { +--- /dev/null ++++ b/fs/overlayfs/Kconfig +@@ -0,0 +1,4 @@ ++config OVERLAYFS_FS ++ tristate "Overlay filesystem support" ++ help ++ Add support for overlay filesystem. +--- /dev/null ++++ b/fs/overlayfs/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for the overlay filesystem. ++# ++ ++obj-$(CONFIG_OVERLAYFS_FS) += overlayfs.o ++ ++overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o +--- /dev/null ++++ b/fs/overlayfs/copy_up.c +@@ -0,0 +1,383 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/slab.h> ++#include <linux/file.h> ++#include <linux/splice.h> ++#include <linux/xattr.h> ++#include <linux/security.h> ++#include <linux/uaccess.h> ++#include "overlayfs.h" ++ ++#define OVL_COPY_UP_CHUNK_SIZE (1 << 20) ++ ++static int ovl_copy_up_xattr(struct dentry *old, struct dentry *new) ++{ ++ ssize_t list_size, size; ++ char *buf, *name, *value; ++ int error; ++ ++ if (!old->d_inode->i_op->getxattr || ++ !new->d_inode->i_op->getxattr) ++ return 0; ++ ++ list_size = vfs_listxattr(old, NULL, 0); ++ if (list_size <= 0) { ++ if (list_size == -EOPNOTSUPP) ++ return 0; ++ return list_size; ++ } ++ ++ buf = kzalloc(list_size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ error = -ENOMEM; ++ value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL); ++ if (!value) ++ goto out; ++ ++ list_size = vfs_listxattr(old, buf, list_size); ++ if (list_size <= 0) { ++ error = list_size; ++ goto out_free_value; ++ } ++ ++ for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { ++ size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX); ++ if (size <= 0) { ++ error = size; ++ goto out_free_value; ++ } ++ error = vfs_setxattr(new, name, value, size, 0); ++ if (error) ++ goto out_free_value; ++ } ++ ++out_free_value: ++ kfree(value); ++out: ++ kfree(buf); ++ return error; ++} ++ ++static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) ++{ ++ struct file *old_file; ++ struct file *new_file; ++ int error = 0; ++ ++ if (len == 0) ++ return 0; ++ ++ old_file = vfs_open(old, O_RDONLY, current_cred()); ++ if (IS_ERR(old_file)) ++ return PTR_ERR(old_file); ++ ++ new_file = vfs_open(new, O_WRONLY, current_cred()); ++ if (IS_ERR(new_file)) { ++ error = PTR_ERR(new_file); ++ goto out_fput; ++ } ++ ++ /* FIXME: copy up sparse files efficiently */ ++ while (len) { ++ loff_t offset = new_file->f_pos; ++ size_t this_len = OVL_COPY_UP_CHUNK_SIZE; ++ long bytes; ++ ++ if (len < this_len) ++ this_len = len; ++ ++ if (signal_pending_state(TASK_KILLABLE, current)) { ++ error = -EINTR; ++ break; ++ } ++ ++ bytes = do_splice_direct(old_file, &offset, new_file, this_len, ++ SPLICE_F_MOVE); ++ if (bytes <= 0) { ++ error = bytes; ++ break; ++ } ++ ++ len -= bytes; ++ } ++ ++ fput(new_file); ++out_fput: ++ fput(old_file); ++ return error; ++} ++ ++static char *ovl_read_symlink(struct dentry *realdentry) ++{ ++ int res; ++ char *buf; ++ struct inode *inode = realdentry->d_inode; ++ mm_segment_t old_fs; ++ ++ res = -EINVAL; ++ if (!inode->i_op->readlink) ++ goto err; ++ ++ res = -ENOMEM; ++ buf = (char *) __get_free_page(GFP_KERNEL); ++ if (!buf) ++ goto err; ++ ++ old_fs = get_fs(); ++ set_fs(get_ds()); ++ /* The cast to a user pointer is valid due to the set_fs() */ ++ res = inode->i_op->readlink(realdentry, ++ (char __user *)buf, PAGE_SIZE - 1); ++ set_fs(old_fs); ++ if (res < 0) { ++ free_page((unsigned long) buf); ++ goto err; ++ } ++ buf[res] = '\0'; ++ ++ return buf; ++ ++err: ++ return ERR_PTR(res); ++} ++ ++static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, ++ .ia_atime = stat->atime, ++ .ia_mtime = stat->mtime, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_set_mode(struct dentry *upperdentry, umode_t mode) ++{ ++ struct iattr attr = { ++ .ia_valid = ATTR_MODE, ++ .ia_mode = mode, ++ }; ++ ++ return notify_change(upperdentry, &attr); ++} ++ ++static int ovl_copy_up_locked(struct dentry *upperdir, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat, ++ const char *link) ++{ ++ int err; ++ struct path newpath; ++ umode_t mode = stat->mode; ++ ++ /* Can't properly set mode on creation because of the umask */ ++ stat->mode &= S_IFMT; ++ ++ ovl_path_upper(dentry, &newpath); ++ WARN_ON(newpath.dentry); ++ newpath.dentry = ovl_upper_create(upperdir, dentry, stat, link); ++ if (IS_ERR(newpath.dentry)) ++ return PTR_ERR(newpath.dentry); ++ ++ if (S_ISREG(stat->mode)) { ++ err = ovl_copy_up_data(lowerpath, &newpath, stat->size); ++ if (err) ++ goto err_remove; ++ } ++ ++ err = ovl_copy_up_xattr(lowerpath->dentry, newpath.dentry); ++ if (err) ++ goto err_remove; ++ ++ mutex_lock(&newpath.dentry->d_inode->i_mutex); ++ if (!S_ISLNK(stat->mode)) ++ err = ovl_set_mode(newpath.dentry, mode); ++ if (!err) ++ err = ovl_set_timestamps(newpath.dentry, stat); ++ mutex_unlock(&newpath.dentry->d_inode->i_mutex); ++ if (err) ++ goto err_remove; ++ ++ ovl_dentry_update(dentry, newpath.dentry); ++ ++ /* ++ * Easiest way to get rid of the lower dentry reference is to ++ * drop this dentry. This is neither needed nor possible for ++ * directories. ++ */ ++ if (!S_ISDIR(stat->mode)) ++ d_drop(dentry); ++ ++ return 0; ++ ++err_remove: ++ if (S_ISDIR(stat->mode)) ++ vfs_rmdir(upperdir->d_inode, newpath.dentry); ++ else ++ vfs_unlink(upperdir->d_inode, newpath.dentry); ++ ++ dput(newpath.dentry); ++ ++ return err; ++} ++ ++/* ++ * Copy up a single dentry ++ * ++ * Directory renames only allowed on "pure upper" (already created on ++ * upper filesystem, never copied up). Directories which are on lower or ++ * are merged may not be renamed. For these -EXDEV is returned and ++ * userspace has to deal with it. This means, when copying up a ++ * directory we can rely on it and ancestors being stable. ++ * ++ * Non-directory renames start with copy up of source if necessary. The ++ * actual rename will only proceed once the copy up was successful. Copy ++ * up uses upper parent i_mutex for exclusion. Since rename can change ++ * d_parent it is possible that the copy up will lock the old parent. At ++ * that point the file will have already been copied up anyway. ++ */ ++static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, ++ struct path *lowerpath, struct kstat *stat) ++{ ++ int err; ++ struct kstat pstat; ++ struct path parentpath; ++ struct dentry *upperdir; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ char *link = NULL; ++ ++ ovl_path_upper(parent, &parentpath); ++ upperdir = parentpath.dentry; ++ ++ err = vfs_getattr(parentpath.mnt, parentpath.dentry, &pstat); ++ if (err) ++ return err; ++ ++ if (S_ISLNK(stat->mode)) { ++ link = ovl_read_symlink(lowerpath->dentry); ++ if (IS_ERR(link)) ++ return PTR_ERR(link); ++ } ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_free_link; ++ ++ override_cred->fsuid = stat->uid; ++ override_cred->fsgid = stat->gid; ++ /* ++ * CAP_SYS_ADMIN for copying up extended attributes ++ * CAP_DAC_OVERRIDE for create ++ * CAP_FOWNER for chmod, timestamp update ++ * CAP_FSETID for chmod ++ * CAP_MKNOD for mknod ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ cap_raise(override_cred->cap_effective, CAP_FSETID); ++ cap_raise(override_cred->cap_effective, CAP_MKNOD); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ if (ovl_path_type(dentry) != OVL_PATH_LOWER) { ++ err = 0; ++ } else { ++ err = ovl_copy_up_locked(upperdir, dentry, lowerpath, ++ stat, link); ++ if (!err) { ++ /* Restore timestamps on parent (best effort) */ ++ ovl_set_timestamps(upperdir, &pstat); ++ } ++ } ++ ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++out_free_link: ++ if (link) ++ free_page((unsigned long) link); ++ ++ return err; ++} ++ ++int ovl_copy_up(struct dentry *dentry) ++{ ++ int err; ++ ++ err = 0; ++ while (!err) { ++ struct dentry *next; ++ struct dentry *parent; ++ struct path lowerpath; ++ struct kstat stat; ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ next = dget(dentry); ++ /* find the topmost dentry not yet copied up */ ++ for (;;) { ++ parent = dget_parent(next); ++ ++ type = ovl_path_type(parent); ++ if (type != OVL_PATH_LOWER) ++ break; ++ ++ dput(next); ++ next = parent; ++ } ++ ++ ovl_path_lower(next, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (!err) ++ err = ovl_copy_up_one(parent, next, &lowerpath, &stat); ++ ++ dput(parent); ++ dput(next); ++ } ++ ++ return err; ++} ++ ++/* Optimize by not copying up the file first and truncating later */ ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size) ++{ ++ int err; ++ struct kstat stat; ++ struct path lowerpath; ++ struct dentry *parent = dget_parent(dentry); ++ ++ err = ovl_copy_up(parent); ++ if (err) ++ goto out_dput_parent; ++ ++ ovl_path_lower(dentry, &lowerpath); ++ err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat); ++ if (err) ++ goto out_dput_parent; ++ ++ if (size < stat.size) ++ stat.size = size; ++ ++ err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); ++ ++out_dput_parent: ++ dput(parent); ++ return err; ++} +--- /dev/null ++++ b/fs/overlayfs/dir.c +@@ -0,0 +1,596 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/namei.h> ++#include <linux/xattr.h> ++#include <linux/security.h> ++#include "overlayfs.h" ++ ++static const char *ovl_whiteout_symlink = "(overlay-whiteout)"; ++ ++static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) ++{ ++ int err; ++ struct dentry *newdentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* FIXME: recheck lower dentry to see if whiteout is really needed */ ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out; ++ ++ /* ++ * CAP_SYS_ADMIN for setxattr ++ * CAP_DAC_OVERRIDE for symlink creation ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ override_cred->fsuid = 0; ++ override_cred->fsgid = 0; ++ old_cred = override_creds(override_cred); ++ ++ newdentry = lookup_one_len(dentry->d_name.name, upperdir, ++ dentry->d_name.len); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_put_cred; ++ ++ /* Just been removed within the same locked region */ ++ WARN_ON(newdentry->d_inode); ++ ++ err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink); ++ if (err) ++ goto out_dput; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ ++ err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0); ++ if (err) ++ vfs_unlink(upperdir->d_inode, newdentry); ++ ++out_dput: ++ dput(newdentry); ++out_put_cred: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++out: ++ if (err) { ++ /* ++ * There's no way to recover from failure to whiteout. ++ * What should we do? Log a big fat error and... ? ++ */ ++ printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n", ++ dentry->d_name.name); ++ } ++ ++ return err; ++} ++ ++static struct dentry *ovl_lookup_create(struct dentry *upperdir, ++ struct dentry *template) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct qstr *name = &template->d_name; ++ ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) ++ return newdentry; ++ ++ if (newdentry->d_inode) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ /* No need to check whiteout if lower parent is non-existent */ ++ err = -EEXIST; ++ if (!ovl_dentry_lower(template->d_parent)) ++ goto out_dput; ++ ++ if (!S_ISLNK(newdentry->d_inode->i_mode)) ++ goto out_dput; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput; ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = -EEXIST; ++ if (ovl_is_whiteout(newdentry)) ++ err = vfs_unlink(upperdir->d_inode, newdentry); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ if (err) ++ goto out_dput; ++ ++ dput(newdentry); ++ newdentry = lookup_one_len(name->name, upperdir, name->len); ++ if (IS_ERR(newdentry)) { ++ ovl_whiteout(upperdir, template); ++ return newdentry; ++ } ++ ++ /* ++ * Whiteout just been successfully removed, parent ++ * i_mutex is still held, there's no way the lookup ++ * could return positive. ++ */ ++ WARN_ON(newdentry->d_inode); ++ } ++ ++ return newdentry; ++ ++out_dput: ++ dput(newdentry); ++ return ERR_PTR(err); ++} ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct inode *dir = upperdir->d_inode; ++ ++ newdentry = ovl_lookup_create(upperdir, dentry); ++ if (IS_ERR(newdentry)) ++ goto out; ++ ++ switch (stat->mode & S_IFMT) { ++ case S_IFREG: ++ err = vfs_create(dir, newdentry, stat->mode, NULL); ++ break; ++ ++ case S_IFDIR: ++ err = vfs_mkdir(dir, newdentry, stat->mode); ++ break; ++ ++ case S_IFCHR: ++ case S_IFBLK: ++ case S_IFIFO: ++ case S_IFSOCK: ++ err = vfs_mknod(dir, newdentry, stat->mode, stat->rdev); ++ break; ++ ++ case S_IFLNK: ++ err = vfs_symlink(dir, newdentry, link); ++ break; ++ ++ default: ++ err = -EPERM; ++ } ++ if (err) { ++ if (ovl_dentry_is_opaque(dentry)) ++ ovl_whiteout(upperdir, dentry); ++ dput(newdentry); ++ newdentry = ERR_PTR(err); ++ } else if (WARN_ON(!newdentry->d_inode)) { ++ /* ++ * Not quite sure if non-instantiated dentry is legal or not. ++ * VFS doesn't seem to care so check and warn here. ++ */ ++ dput(newdentry); ++ newdentry = ERR_PTR(-ENOENT); ++ } ++ ++out: ++ return newdentry; ++ ++} ++ ++static int ovl_set_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for setxattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_remove_opaque(struct dentry *upperdentry) ++{ ++ int err; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* CAP_SYS_ADMIN for removexattr of "trusted" namespace */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ err = vfs_removexattr(upperdentry, ovl_opaque_xattr); ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ ++ type = ovl_path_real(dentry, &realpath); ++ err = vfs_getattr(realpath.mnt, realpath.dentry, stat); ++ if (err) ++ return err; ++ ++ stat->dev = dentry->d_sb->s_dev; ++ stat->ino = dentry->d_inode->i_ino; ++ ++ /* ++ * It's probably not worth it to count subdirs to get the ++ * correct link count. nlink=1 seems to pacify 'find' and ++ * other utilities. ++ */ ++ if (type == OVL_PATH_MERGE) ++ stat->nlink = 1; ++ ++ return 0; ++} ++ ++static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev, ++ const char *link) ++{ ++ int err; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ struct inode *inode; ++ struct kstat stat = { ++ .mode = mode, ++ .rdev = rdev, ++ }; ++ ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata); ++ if (!inode) ++ goto out; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ goto out_iput; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ ++ newdentry = ovl_upper_create(upperdir, dentry, &stat, link); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ if (ovl_dentry_is_opaque(dentry) && S_ISDIR(mode)) { ++ err = ovl_set_opaque(newdentry); ++ if (err) { ++ vfs_rmdir(upperdir->d_inode, newdentry); ++ ovl_whiteout(upperdir, dentry); ++ goto out_dput; ++ } ++ } ++ ovl_dentry_update(dentry, newdentry); ++ d_instantiate(dentry, inode); ++ inode = NULL; ++ newdentry = NULL; ++ err = 0; ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out_iput: ++ iput(inode); ++out: ++ return err; ++} ++ ++static int ovl_create(struct inode *dir, struct dentry *dentry, int mode, ++ struct nameidata *nd) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL); ++} ++ ++static int ovl_mkdir(struct inode *dir, struct dentry *dentry, int mode) ++{ ++ return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL); ++} ++ ++static int ovl_mknod(struct inode *dir, struct dentry *dentry, int mode, ++ dev_t rdev) ++{ ++ return ovl_create_object(dentry, mode, rdev, NULL); ++} ++ ++static int ovl_symlink(struct inode *dir, struct dentry *dentry, ++ const char *link) ++{ ++ return ovl_create_object(dentry, S_IFLNK, 0, link); ++} ++ ++static int ovl_do_remove(struct dentry *dentry, bool is_dir) ++{ ++ int err; ++ enum ovl_path_type type; ++ struct path realpath; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(dentry->d_parent); ++ if (err) ++ return err; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ type = ovl_path_real(dentry, &realpath); ++ if (type != OVL_PATH_LOWER) { ++ err = -ESTALE; ++ if (realpath.dentry->d_parent != upperdir) ++ goto out_d_drop; ++ ++ /* FIXME: create whiteout up front and rename to target */ ++ ++ if (is_dir) ++ err = vfs_rmdir(upperdir->d_inode, realpath.dentry); ++ else ++ err = vfs_unlink(upperdir->d_inode, realpath.dentry); ++ if (err) ++ goto out_d_drop; ++ ++ ovl_dentry_version_inc(dentry->d_parent); ++ } ++ ++ if (type != OVL_PATH_UPPER || ovl_dentry_is_opaque(dentry)) ++ err = ovl_whiteout(upperdir, dentry); ++ ++ /* ++ * Keeping this dentry hashed would mean having to release ++ * upperpath/lowerpath, which could only be done if we are the ++ * sole user of this dentry. Too tricky... Just unhash for ++ * now. ++ */ ++out_d_drop: ++ d_drop(dentry); ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ return ovl_do_remove(dentry, false); ++} ++ ++ ++static int ovl_rmdir(struct inode *dir, struct dentry *dentry) ++{ ++ int err; ++ enum ovl_path_type type; ++ ++ type = ovl_path_type(dentry); ++ if (type != OVL_PATH_UPPER) { ++ err = ovl_check_empty_and_clear(dentry, type); ++ if (err) ++ return err; ++ } ++ ++ return ovl_do_remove(dentry, true); ++} ++ ++static int ovl_link(struct dentry *old, struct inode *newdir, ++ struct dentry *new) ++{ ++ int err; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *upperdir; ++ ++ err = ovl_copy_up(old); ++ if (err) ++ goto out; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(new->d_parent); ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ newdentry = ovl_lookup_create(upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ ++ olddentry = ovl_dentry_upper(old); ++ err = vfs_link(olddentry, upperdir->d_inode, newdentry); ++ if (!err) { ++ if (WARN_ON(!newdentry->d_inode)) { ++ dput(newdentry); ++ err = -ENOENT; ++ goto out_unlock; ++ } ++ ++ ovl_dentry_version_inc(new->d_parent); ++ ovl_dentry_update(new, newdentry); ++ ++ ihold(old->d_inode); ++ d_instantiate(new, old->d_inode); ++ } else { ++ if (ovl_dentry_is_opaque(new)) ++ ovl_whiteout(upperdir, new); ++ dput(newdentry); ++ } ++out_unlock: ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++out: ++ return err; ++ ++} ++ ++static int ovl_rename(struct inode *olddir, struct dentry *old, ++ struct inode *newdir, struct dentry *new) ++{ ++ int err; ++ enum ovl_path_type old_type; ++ enum ovl_path_type new_type; ++ struct dentry *old_upperdir; ++ struct dentry *new_upperdir; ++ struct dentry *olddentry; ++ struct dentry *newdentry; ++ struct dentry *trap; ++ bool old_opaque; ++ bool new_opaque; ++ bool new_create = false; ++ bool is_dir = S_ISDIR(old->d_inode->i_mode); ++ ++ /* Don't copy up directory trees */ ++ old_type = ovl_path_type(old); ++ if (old_type != OVL_PATH_UPPER && is_dir) ++ return -EXDEV; ++ ++ if (new->d_inode) { ++ new_type = ovl_path_type(new); ++ ++ if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { ++ if (ovl_dentry_lower(old)->d_inode == ++ ovl_dentry_lower(new)->d_inode) ++ return 0; ++ } ++ if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { ++ if (ovl_dentry_upper(old)->d_inode == ++ ovl_dentry_upper(new)->d_inode) ++ return 0; ++ } ++ ++ if (new_type != OVL_PATH_UPPER && ++ S_ISDIR(new->d_inode->i_mode)) { ++ err = ovl_check_empty_and_clear(new, new_type); ++ if (err) ++ return err; ++ } ++ } else { ++ new_type = OVL_PATH_UPPER; ++ } ++ ++ err = ovl_copy_up(old); ++ if (err) ++ return err; ++ ++ err = ovl_copy_up(new->d_parent); ++ if (err) ++ return err; ++ ++ old_upperdir = ovl_dentry_upper(old->d_parent); ++ new_upperdir = ovl_dentry_upper(new->d_parent); ++ ++ trap = lock_rename(new_upperdir, old_upperdir); ++ ++ olddentry = ovl_dentry_upper(old); ++ newdentry = ovl_dentry_upper(new); ++ if (newdentry) { ++ dget(newdentry); ++ } else { ++ new_create = true; ++ newdentry = ovl_lookup_create(new_upperdir, new); ++ err = PTR_ERR(newdentry); ++ if (IS_ERR(newdentry)) ++ goto out_unlock; ++ } ++ ++ err = -ESTALE; ++ if (olddentry->d_parent != old_upperdir) ++ goto out_dput; ++ if (newdentry->d_parent != new_upperdir) ++ goto out_dput; ++ if (olddentry == trap) ++ goto out_dput; ++ if (newdentry == trap) ++ goto out_dput; ++ ++ old_opaque = ovl_dentry_is_opaque(old); ++ new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER; ++ ++ if (is_dir && !old_opaque && new_opaque) { ++ err = ovl_set_opaque(olddentry); ++ if (err) ++ goto out_dput; ++ } ++ ++ err = vfs_rename(old_upperdir->d_inode, olddentry, ++ new_upperdir->d_inode, newdentry); ++ ++ if (err) { ++ if (new_create && ovl_dentry_is_opaque(new)) ++ ovl_whiteout(new_upperdir, new); ++ if (is_dir && !old_opaque && new_opaque) ++ ovl_remove_opaque(olddentry); ++ goto out_dput; ++ } ++ ++ if (old_type != OVL_PATH_UPPER || old_opaque) ++ err = ovl_whiteout(old_upperdir, old); ++ if (is_dir && old_opaque && !new_opaque) ++ ovl_remove_opaque(olddentry); ++ ++ if (old_opaque != new_opaque) ++ ovl_dentry_set_opaque(old, new_opaque); ++ ++ ovl_dentry_version_inc(old->d_parent); ++ ovl_dentry_version_inc(new->d_parent); ++ ++out_dput: ++ dput(newdentry); ++out_unlock: ++ unlock_rename(new_upperdir, old_upperdir); ++ return err; ++} ++ ++const struct inode_operations ovl_dir_inode_operations = { ++ .lookup = ovl_lookup, ++ .mkdir = ovl_mkdir, ++ .symlink = ovl_symlink, ++ .unlink = ovl_unlink, ++ .rmdir = ovl_rmdir, ++ .rename = ovl_rename, ++ .link = ovl_link, ++ .setattr = ovl_setattr, ++ .create = ovl_create, ++ .mknod = ovl_mknod, ++ .permission = ovl_permission, ++ .getattr = ovl_dir_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; +--- /dev/null ++++ b/fs/overlayfs/inode.c +@@ -0,0 +1,384 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/slab.h> ++#include <linux/xattr.h> ++#include "overlayfs.h" ++ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr) ++{ ++ struct dentry *upperdentry; ++ int err; ++ ++ if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry)) ++ err = ovl_copy_up_truncate(dentry, attr->ia_size); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ ++ if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) ++ attr->ia_valid &= ~ATTR_MODE; ++ ++ mutex_lock(&upperdentry->d_inode->i_mutex); ++ err = notify_change(upperdentry, attr); ++ mutex_unlock(&upperdentry->d_inode->i_mutex); ++ ++ return err; ++} ++ ++static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry, ++ struct kstat *stat) ++{ ++ struct path realpath; ++ ++ ovl_path_real(dentry, &realpath); ++ return vfs_getattr(realpath.mnt, realpath.dentry, stat); ++} ++ ++int ovl_permission(struct inode *inode, int mask, unsigned int flags) ++{ ++ struct ovl_entry *oe; ++ struct dentry *alias = NULL; ++ struct inode *realinode; ++ struct dentry *realdentry; ++ bool is_upper; ++ int err; ++ ++ if (S_ISDIR(inode->i_mode)) { ++ oe = inode->i_private; ++ } else if (flags & IPERM_FLAG_RCU) { ++ return -ECHILD; ++ } else { ++ /* ++ * For non-directories find an alias and get the info ++ * from there. ++ */ ++ spin_lock(&inode->i_lock); ++ if (WARN_ON(list_empty(&inode->i_dentry))) { ++ spin_unlock(&inode->i_lock); ++ return -ENOENT; ++ } ++ alias = list_entry(inode->i_dentry.next, struct dentry, d_alias); ++ dget(alias); ++ spin_unlock(&inode->i_lock); ++ oe = alias->d_fsdata; ++ } ++ ++ realdentry = ovl_entry_real(oe, &is_upper); ++ ++ /* Careful in RCU walk mode */ ++ realinode = ACCESS_ONCE(realdentry->d_inode); ++ if (!realinode) { ++ WARN_ON(!(flags & IPERM_FLAG_RCU)); ++ err = -ENOENT; ++ goto out_dput; ++ } ++ ++ if (mask & MAY_WRITE) { ++ umode_t mode = realinode->i_mode; ++ ++ /* ++ * Writes will always be redirected to upper layer, so ++ * ignore lower layer being read-only. ++ * ++ * If the overlay itself is read-only then proceed ++ * with the permission check, don't return EROFS. ++ * This will only happen if this is the lower layer of ++ * another overlayfs. ++ * ++ * If upper fs becomes read-only after the overlay was ++ * constructed return EROFS to prevent modification of ++ * upper layer. ++ */ ++ err = -EROFS; ++ if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && ++ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) ++ goto out_dput; ++ ++ /* ++ * Nobody gets write access to an immutable file. ++ */ ++ err = -EACCES; ++ if (IS_IMMUTABLE(realinode)) ++ goto out_dput; ++ } ++ ++ if (realinode->i_op->permission) ++ err = realinode->i_op->permission(realinode, mask, flags); ++ else ++ err = generic_permission(realinode, mask, flags, ++ realinode->i_op->check_acl); ++out_dput: ++ dput(alias); ++ return err; ++} ++ ++ ++struct ovl_link_data { ++ struct dentry *realdentry; ++ void *cookie; ++}; ++ ++static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ void *ret; ++ struct dentry *realdentry; ++ struct inode *realinode; ++ ++ realdentry = ovl_dentry_real(dentry); ++ realinode = realdentry->d_inode; ++ ++ if (WARN_ON(!realinode->i_op->follow_link)) ++ return ERR_PTR(-EPERM); ++ ++ ret = realinode->i_op->follow_link(realdentry, nd); ++ if (IS_ERR(ret)) ++ return ret; ++ ++ if (realinode->i_op->put_link) { ++ struct ovl_link_data *data; ++ ++ data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL); ++ if (!data) { ++ realinode->i_op->put_link(realdentry, nd, ret); ++ return ERR_PTR(-ENOMEM); ++ } ++ data->realdentry = realdentry; ++ data->cookie = ret; ++ ++ return data; ++ } else { ++ return NULL; ++ } ++} ++ ++static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c) ++{ ++ struct inode *realinode; ++ struct ovl_link_data *data = c; ++ ++ if (!data) ++ return; ++ ++ realinode = data->realdentry->d_inode; ++ realinode->i_op->put_link(data->realdentry, nd, data->cookie); ++ kfree(data); ++} ++ ++static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ++{ ++ struct path realpath; ++ struct inode *realinode; ++ ++ ovl_path_real(dentry, &realpath); ++ realinode = realpath.dentry->d_inode; ++ ++ if (!realinode->i_op->readlink) ++ return -EINVAL; ++ ++ touch_atime(realpath.mnt, realpath.dentry); ++ ++ return realinode->i_op->readlink(realpath.dentry, buf, bufsiz); ++} ++ ++ ++static bool ovl_is_private_xattr(const char *name) ++{ ++ return strncmp(name, "trusted.overlay.", 14) == 0; ++} ++ ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ int err; ++ struct dentry *upperdentry; ++ ++ if (ovl_is_private_xattr(name)) ++ return -EPERM; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ upperdentry = ovl_dentry_upper(dentry); ++ return vfs_setxattr(upperdentry, name, value, size, flags); ++} ++ ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size) ++{ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); ++} ++ ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ++{ ++ ssize_t res; ++ int off; ++ ++ res = vfs_listxattr(ovl_dentry_real(dentry), list, size); ++ if (res <= 0 || size == 0) ++ return res; ++ ++ if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) ++ return res; ++ ++ /* filter out private xattrs */ ++ for (off = 0; off < res;) { ++ char *s = list + off; ++ size_t slen = strlen(s) + 1; ++ ++ BUG_ON(off + slen > res); ++ ++ if (ovl_is_private_xattr(s)) { ++ res -= slen; ++ memmove(s, s + slen, res - off); ++ } else { ++ off += slen; ++ } ++ } ++ ++ return res; ++} ++ ++int ovl_removexattr(struct dentry *dentry, const char *name) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ++ ovl_is_private_xattr(name)) ++ return -ENODATA; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (type == OVL_PATH_LOWER) { ++ err = vfs_getxattr(realpath.dentry, name, NULL, 0); ++ if (err < 0) ++ return err; ++ ++ err = ovl_copy_up(dentry); ++ if (err) ++ return err; ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_removexattr(realpath.dentry, name); ++} ++ ++static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, ++ struct dentry *realdentry) ++{ ++ if (type != OVL_PATH_LOWER) ++ return false; ++ ++ if (special_file(realdentry->d_inode->i_mode)) ++ return false; ++ ++ if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC)) ++ return false; ++ ++ return true; ++} ++ ++static struct file *ovl_open(struct dentry *dentry, int flags, ++ const struct cred *cred) ++{ ++ int err; ++ struct path realpath; ++ enum ovl_path_type type; ++ ++ type = ovl_path_real(dentry, &realpath); ++ if (ovl_open_need_copy_up(flags, type, realpath.dentry)) { ++ if (flags & O_TRUNC) ++ err = ovl_copy_up_truncate(dentry, 0); ++ else ++ err = ovl_copy_up(dentry); ++ if (err) ++ return ERR_PTR(err); ++ ++ ovl_path_upper(dentry, &realpath); ++ } ++ ++ return vfs_open(&realpath, flags, cred); ++} ++ ++static const struct inode_operations ovl_file_inode_operations = { ++ .setattr = ovl_setattr, ++ .permission = ovl_permission, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++ .open = ovl_open, ++}; ++ ++static const struct inode_operations ovl_symlink_inode_operations = { ++ .setattr = ovl_setattr, ++ .follow_link = ovl_follow_link, ++ .put_link = ovl_put_link, ++ .readlink = ovl_readlink, ++ .getattr = ovl_getattr, ++ .setxattr = ovl_setxattr, ++ .getxattr = ovl_getxattr, ++ .listxattr = ovl_listxattr, ++ .removexattr = ovl_removexattr, ++}; ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe) ++{ ++ struct inode *inode; ++ ++ inode = new_inode(sb); ++ if (!inode) ++ return NULL; ++ ++ mode &= S_IFMT; ++ ++ inode->i_ino = get_next_ino(); ++ inode->i_mode = mode; ++ inode->i_flags |= S_NOATIME | S_NOCMTIME; ++ ++ switch (mode) { ++ case S_IFDIR: ++ inode->i_private = oe; ++ inode->i_op = &ovl_dir_inode_operations; ++ inode->i_fop = &ovl_dir_operations; ++ break; ++ ++ case S_IFLNK: ++ inode->i_op = &ovl_symlink_inode_operations; ++ break; ++ ++ case S_IFREG: ++ case S_IFSOCK: ++ case S_IFBLK: ++ case S_IFCHR: ++ case S_IFIFO: ++ inode->i_op = &ovl_file_inode_operations; ++ break; ++ ++ default: ++ WARN(1, "illegal file type: %i\n", mode); ++ inode = NULL; ++ } ++ ++ return inode; ++ ++} +--- /dev/null ++++ b/fs/overlayfs/overlayfs.h +@@ -0,0 +1,63 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * 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. ++ */ ++ ++struct ovl_entry; ++ ++enum ovl_path_type { ++ OVL_PATH_UPPER, ++ OVL_PATH_MERGE, ++ OVL_PATH_LOWER, ++}; ++ ++extern const char *ovl_opaque_xattr; ++extern const char *ovl_whiteout_xattr; ++extern const struct dentry_operations ovl_dentry_operations; ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry); ++u64 ovl_dentry_version_get(struct dentry *dentry); ++void ovl_dentry_version_inc(struct dentry *dentry); ++void ovl_path_upper(struct dentry *dentry, struct path *path); ++void ovl_path_lower(struct dentry *dentry, struct path *path); ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); ++struct dentry *ovl_dentry_upper(struct dentry *dentry); ++struct dentry *ovl_dentry_lower(struct dentry *dentry); ++struct dentry *ovl_dentry_real(struct dentry *dentry); ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper); ++bool ovl_dentry_is_opaque(struct dentry *dentry); ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque); ++bool ovl_is_whiteout(struct dentry *dentry); ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd); ++ ++struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry, ++ struct kstat *stat, const char *link); ++ ++/* readdir.c */ ++extern const struct file_operations ovl_dir_operations; ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type); ++ ++/* inode.c */ ++int ovl_setattr(struct dentry *dentry, struct iattr *attr); ++int ovl_permission(struct inode *inode, int mask, unsigned int flags); ++int ovl_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags); ++ssize_t ovl_getxattr(struct dentry *dentry, const char *name, ++ void *value, size_t size); ++ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); ++int ovl_removexattr(struct dentry *dentry, const char *name); ++ ++struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, ++ struct ovl_entry *oe); ++/* dir.c */ ++extern const struct inode_operations ovl_dir_inode_operations; ++ ++/* copy_up.c */ ++int ovl_copy_up(struct dentry *dentry); ++int ovl_copy_up_truncate(struct dentry *dentry, loff_t size); +--- /dev/null ++++ b/fs/overlayfs/readdir.c +@@ -0,0 +1,558 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/slab.h> ++#include <linux/namei.h> ++#include <linux/file.h> ++#include <linux/xattr.h> ++#include <linux/rbtree.h> ++#include <linux/security.h> ++#include "overlayfs.h" ++ ++struct ovl_cache_entry { ++ const char *name; ++ unsigned int len; ++ unsigned int type; ++ u64 ino; ++ bool is_whiteout; ++ struct list_head l_node; ++ struct rb_node node; ++}; ++ ++struct ovl_readdir_data { ++ struct rb_root *root; ++ struct list_head *list; ++ struct list_head *middle; ++ struct dentry *dir; ++ int count; ++ int err; ++}; ++ ++struct ovl_dir_file { ++ bool is_real; ++ bool is_cached; ++ struct list_head cursor; ++ u64 cache_version; ++ struct list_head cache; ++ struct file *realfile; ++}; ++ ++static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n) ++{ ++ return container_of(n, struct ovl_cache_entry, node); ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, ++ const char *name, int len) ++{ ++ struct rb_node *node = root->rb_node; ++ int cmp; ++ ++ while (node) { ++ struct ovl_cache_entry *p = ovl_cache_entry_from_node(node); ++ ++ cmp = strncmp(name, p->name, len); ++ if (cmp > 0) ++ node = p->node.rb_right; ++ else if (cmp < 0 || len < p->len) ++ node = p->node.rb_left; ++ else ++ return p; ++ } ++ ++ return NULL; ++} ++ ++static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, ++ u64 ino, unsigned int d_type) ++{ ++ struct ovl_cache_entry *p; ++ ++ p = kmalloc(sizeof(*p) + len + 1, GFP_KERNEL); ++ if (p) { ++ char *name_copy = (char *) (p + 1); ++ memcpy(name_copy, name, len); ++ name_copy[len] = '\0'; ++ p->name = name_copy; ++ p->len = len; ++ p->type = d_type; ++ p->ino = ino; ++ p->is_whiteout = false; ++ } ++ ++ return p; ++} ++ ++static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, ++ const char *name, int len, u64 ino, ++ unsigned int d_type) ++{ ++ struct rb_node **newp = &rdd->root->rb_node; ++ struct rb_node *parent = NULL; ++ struct ovl_cache_entry *p; ++ ++ while (*newp) { ++ int cmp; ++ struct ovl_cache_entry *tmp; ++ ++ parent = *newp; ++ tmp = ovl_cache_entry_from_node(*newp); ++ cmp = strncmp(name, tmp->name, len); ++ if (cmp > 0) ++ newp = &tmp->node.rb_right; ++ else if (cmp < 0 || len < tmp->len) ++ newp = &tmp->node.rb_left; ++ else ++ return 0; ++ } ++ ++ p = ovl_cache_entry_new(name, len, ino, d_type); ++ if (p == NULL) ++ return -ENOMEM; ++ ++ list_add_tail(&p->l_node, rdd->list); ++ rb_link_node(&p->node, parent, newp); ++ rb_insert_color(&p->node, rdd->root); ++ ++ return 0; ++} ++ ++static int ovl_fill_lower(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ struct ovl_cache_entry *p; ++ ++ rdd->count++; ++ p = ovl_cache_entry_find(rdd->root, name, namelen); ++ if (p) { ++ list_move_tail(&p->l_node, rdd->middle); ++ } else { ++ p = ovl_cache_entry_new(name, namelen, ino, d_type); ++ if (p == NULL) ++ rdd->err = -ENOMEM; ++ else ++ list_add_tail(&p->l_node, rdd->middle); ++ } ++ ++ return rdd->err; ++} ++ ++static void ovl_cache_free(struct list_head *list) ++{ ++ struct ovl_cache_entry *p; ++ struct ovl_cache_entry *n; ++ ++ list_for_each_entry_safe(p, n, list, l_node) ++ kfree(p); ++ ++ INIT_LIST_HEAD(list); ++} ++ ++static int ovl_fill_upper(void *buf, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct ovl_readdir_data *rdd = buf; ++ ++ rdd->count++; ++ return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type); ++} ++ ++static inline int ovl_dir_read(struct path *realpath, ++ struct ovl_readdir_data *rdd, filldir_t filler) ++{ ++ struct file *realfile; ++ int err; ++ ++ realfile = vfs_open(realpath, O_RDONLY | O_DIRECTORY, current_cred()); ++ if (IS_ERR(realfile)) ++ return PTR_ERR(realfile); ++ ++ do { ++ rdd->count = 0; ++ rdd->err = 0; ++ err = vfs_readdir(realfile, filler, rdd); ++ if (err >= 0) ++ err = rdd->err; ++ } while (!err && rdd->count); ++ fput(realfile); ++ ++ return 0; ++} ++ ++static void ovl_dir_reset(struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ enum ovl_path_type type = ovl_path_type(file->f_path.dentry); ++ ++ if (ovl_dentry_version_get(file->f_path.dentry) != od->cache_version) { ++ list_del_init(&od->cursor); ++ ovl_cache_free(&od->cache); ++ od->is_cached = false; ++ } ++ WARN_ON(!od->is_real && type != OVL_PATH_MERGE); ++ if (od->is_real && type == OVL_PATH_MERGE) { ++ fput(od->realfile); ++ od->realfile = NULL; ++ od->is_real = false; ++ } ++} ++ ++static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd) ++{ ++ struct ovl_cache_entry *p; ++ struct dentry *dentry; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) { ++ ovl_cache_free(rdd->list); ++ return -ENOMEM; ++ } ++ ++ /* ++ * CAP_SYS_ADMIN for getxattr ++ * CAP_DAC_OVERRIDE for lookup ++ */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ old_cred = override_creds(override_cred); ++ ++ mutex_lock(&rdd->dir->d_inode->i_mutex); ++ list_for_each_entry(p, rdd->list, l_node) { ++ if (p->type != DT_LNK) ++ continue; ++ ++ dentry = lookup_one_len(p->name, rdd->dir, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ ++ p->is_whiteout = ovl_is_whiteout(dentry); ++ dput(dentry); ++ } ++ mutex_unlock(&rdd->dir->d_inode->i_mutex); ++ ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return 0; ++} ++ ++static inline int ovl_dir_read_merged(struct path *upperpath, struct path *lowerpath, ++ struct ovl_readdir_data *rdd) ++{ ++ int err; ++ struct rb_root root = RB_ROOT; ++ struct list_head middle; ++ ++ rdd->root = &root; ++ if (upperpath->dentry) { ++ rdd->dir = upperpath->dentry; ++ err = ovl_dir_read(upperpath, rdd, ovl_fill_upper); ++ if (err) ++ goto out; ++ ++ err = ovl_dir_mark_whiteouts(rdd); ++ if (err) ++ goto out; ++ } ++ /* ++ * Insert lowerpath entries before upperpath ones, this allows ++ * offsets to be reasonably constant ++ */ ++ list_add(&middle, rdd->list); ++ rdd->middle = &middle; ++ err = ovl_dir_read(lowerpath, rdd, ovl_fill_lower); ++ list_del(&middle); ++out: ++ rdd->root = NULL; ++ ++ return err; ++} ++ ++static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) ++{ ++ struct list_head *l; ++ loff_t off; ++ ++ l = od->cache.next; ++ for (off = 0; off < pos; off++) { ++ if (l == &od->cache) ++ break; ++ l = l->next; ++ } ++ list_move_tail(&od->cursor, l); ++} ++ ++static int ovl_readdir(struct file *file, void *buf, filldir_t filler) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ int res; ++ ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_readdir(od->realfile, filler, buf); ++ file->f_pos = od->realfile->f_pos; ++ ++ return res; ++ } ++ ++ if (!od->is_cached) { ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_readdir_data rdd = { .list = &od->cache }; ++ ++ ovl_path_lower(file->f_path.dentry, &lowerpath); ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ ++ res = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (res) { ++ ovl_cache_free(rdd.list); ++ return res; ++ } ++ ++ od->cache_version = ovl_dentry_version_get(file->f_path.dentry); ++ od->is_cached = true; ++ ++ ovl_seek_cursor(od, file->f_pos); ++ } ++ ++ while (od->cursor.next != &od->cache) { ++ int over; ++ loff_t off; ++ struct ovl_cache_entry *p; ++ ++ p = list_entry(od->cursor.next, struct ovl_cache_entry, l_node); ++ off = file->f_pos; ++ if (!p->is_whiteout) { ++ over = filler(buf, p->name, p->len, off, p->ino, p->type); ++ if (over) ++ break; ++ } ++ file->f_pos++; ++ list_move(&od->cursor, &p->l_node); ++ } ++ ++ return 0; ++} ++ ++static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin) ++{ ++ loff_t res; ++ struct ovl_dir_file *od = file->private_data; ++ ++ mutex_lock(&file->f_dentry->d_inode->i_mutex); ++ if (!file->f_pos) ++ ovl_dir_reset(file); ++ ++ if (od->is_real) { ++ res = vfs_llseek(od->realfile, offset, origin); ++ file->f_pos = od->realfile->f_pos; ++ } else { ++ res = -EINVAL; ++ ++ switch (origin) { ++ case SEEK_CUR: ++ offset += file->f_pos; ++ break; ++ case SEEK_SET: ++ break; ++ default: ++ goto out_unlock; ++ } ++ if (offset < 0) ++ goto out_unlock; ++ ++ if (offset != file->f_pos) { ++ file->f_pos = offset; ++ if (od->is_cached) ++ ovl_seek_cursor(od, offset); ++ } ++ res = offset; ++ } ++out_unlock: ++ mutex_unlock(&file->f_dentry->d_inode->i_mutex); ++ ++ return res; ++} ++ ++static int ovl_dir_fsync(struct file *file, int datasync) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ /* May need to reopen directory if it got copied up */ ++ if (!od->realfile) { ++ struct path upperpath; ++ ++ ovl_path_upper(file->f_path.dentry, &upperpath); ++ od->realfile = vfs_open(&upperpath, O_RDONLY, current_cred()); ++ if (IS_ERR(od->realfile)) ++ return PTR_ERR(od->realfile); ++ } ++ ++ return vfs_fsync(od->realfile, datasync); ++} ++ ++static int ovl_dir_release(struct inode *inode, struct file *file) ++{ ++ struct ovl_dir_file *od = file->private_data; ++ ++ list_del(&od->cursor); ++ ovl_cache_free(&od->cache); ++ if (od->realfile) ++ fput(od->realfile); ++ kfree(od); ++ ++ return 0; ++} ++ ++static int ovl_dir_open(struct inode *inode, struct file *file) ++{ ++ struct path realpath; ++ struct file *realfile; ++ struct ovl_dir_file *od; ++ enum ovl_path_type type; ++ ++ od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL); ++ if (!od) ++ return -ENOMEM; ++ ++ type = ovl_path_real(file->f_path.dentry, &realpath); ++ realfile = vfs_open(&realpath, file->f_flags, current_cred()); ++ if (IS_ERR(realfile)) { ++ kfree(od); ++ return PTR_ERR(realfile); ++ } ++ INIT_LIST_HEAD(&od->cache); ++ INIT_LIST_HEAD(&od->cursor); ++ od->is_cached = false; ++ od->realfile = realfile; ++ od->is_real = (type != OVL_PATH_MERGE); ++ file->private_data = od; ++ ++ return 0; ++} ++ ++const struct file_operations ovl_dir_operations = { ++ .read = generic_read_dir, ++ .open = ovl_dir_open, ++ .readdir = ovl_readdir, ++ .llseek = ovl_dir_llseek, ++ .fsync = ovl_dir_fsync, ++ .release = ovl_dir_release, ++}; ++ ++static int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) ++{ ++ int err; ++ struct path lowerpath; ++ struct path upperpath; ++ struct ovl_cache_entry *p; ++ struct ovl_readdir_data rdd = { .list = list }; ++ ++ ovl_path_upper(dentry, &upperpath); ++ ovl_path_lower(dentry, &lowerpath); ++ ++ err = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd); ++ if (err) ++ return err; ++ ++ err = 0; ++ ++ list_for_each_entry(p, list, l_node) { ++ if (p->is_whiteout) ++ continue; ++ ++ if (p->name[0] == '.') { ++ if (p->len == 1) ++ continue; ++ if (p->len == 2 && p->name[1] == '.') ++ continue; ++ } ++ err = -ENOTEMPTY; ++ break; ++ } ++ ++ return err; ++} ++ ++static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list) ++{ ++ struct path upperpath; ++ struct dentry *upperdir; ++ struct ovl_cache_entry *p; ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ int err; ++ ++ ovl_path_upper(dir, &upperpath); ++ upperdir = upperpath.dentry; ++ ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ return -ENOMEM; ++ ++ /* ++ * CAP_DAC_OVERRIDE for lookup and unlink ++ * CAP_SYS_ADMIN for setxattr of "trusted" namespace ++ * CAP_FOWNER for unlink in sticky directory ++ */ ++ cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ cap_raise(override_cred->cap_effective, CAP_FOWNER); ++ old_cred = override_creds(override_cred); ++ ++ err = vfs_setxattr(upperdir, ovl_opaque_xattr, "y", 1, 0); ++ if (err) ++ goto out_revert_creds; ++ ++ mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT); ++ list_for_each_entry(p, list, l_node) { ++ struct dentry *dentry; ++ int ret; ++ ++ if (!p->is_whiteout) ++ continue; ++ ++ dentry = lookup_one_len(p->name, upperdir, p->len); ++ if (IS_ERR(dentry)) { ++ printk(KERN_WARNING "overlayfs: failed to lookup whiteout %.*s: %li\n", p->len, p->name, PTR_ERR(dentry)); ++ continue; ++ } ++ ret = vfs_unlink(upperdir->d_inode, dentry); ++ dput(dentry); ++ if (ret) ++ printk(KERN_WARNING "overlayfs: failed to unlink whiteout %.*s: %i\n", p->len, p->name, ret); ++ } ++ mutex_unlock(&upperdir->d_inode->i_mutex); ++ ++out_revert_creds: ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ ++ return err; ++} ++ ++int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type) ++{ ++ int err; ++ LIST_HEAD(list); ++ ++ err = ovl_check_empty_dir(dentry, &list); ++ if (!err && type == OVL_PATH_MERGE) ++ err = ovl_remove_whiteouts(dentry, &list); ++ ++ ovl_cache_free(&list); ++ ++ return err; ++} +--- /dev/null ++++ b/fs/overlayfs/super.c +@@ -0,0 +1,656 @@ ++/* ++ * ++ * Copyright (C) 2011 Novell Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/namei.h> ++#include <linux/xattr.h> ++#include <linux/security.h> ++#include <linux/mount.h> ++#include <linux/slab.h> ++#include <linux/parser.h> ++#include <linux/module.h> ++#include <linux/seq_file.h> ++#include "overlayfs.h" ++ ++MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); ++MODULE_DESCRIPTION("Overlay filesystem"); ++MODULE_LICENSE("GPL"); ++ ++struct ovl_config { ++ char *lowerdir; ++ char *upperdir; ++}; ++ ++/* private information held for overlayfs's superblock */ ++struct ovl_fs { ++ struct vfsmount *upper_mnt; ++ struct vfsmount *lower_mnt; ++ /* pathnames of lower and upper dirs, for show_options */ ++ struct ovl_config config; ++}; ++ ++/* private information held for every overlayfs dentry */ ++struct ovl_entry { ++ /* ++ * Keep "double reference" on upper dentries, so that ++ * d_delete() doesn't think it's OK to reset d_inode to NULL. ++ */ ++ struct dentry *__upperdentry; ++ struct dentry *lowerdentry; ++ union { ++ struct { ++ u64 version; ++ bool opaque; ++ }; ++ struct rcu_head rcu; ++ }; ++}; ++ ++const char *ovl_whiteout_xattr = "trusted.overlay.whiteout"; ++const char *ovl_opaque_xattr = "trusted.overlay.opaque"; ++ ++ ++enum ovl_path_type ovl_path_type(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe->__upperdentry) { ++ if (oe->lowerdentry && S_ISDIR(dentry->d_inode->i_mode)) ++ return OVL_PATH_MERGE; ++ else ++ return OVL_PATH_UPPER; ++ } else { ++ return OVL_PATH_LOWER; ++ } ++} ++ ++static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) ++{ ++ struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry); ++ smp_read_barrier_depends(); ++ return upperdentry; ++} ++ ++void ovl_path_upper(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->upper_mnt; ++ path->dentry = ovl_upperdentry_dereference(oe); ++} ++ ++void ovl_path_lower(struct dentry *dentry, struct path *path) ++{ ++ struct ovl_fs *ofs = dentry->d_sb->s_fs_info; ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ path->mnt = ofs->lower_mnt; ++ path->dentry = oe->lowerdentry; ++} ++ ++enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) ++{ ++ ++ enum ovl_path_type type = ovl_path_type(dentry); ++ ++ if (type == OVL_PATH_LOWER) ++ ovl_path_lower(dentry, path); ++ else ++ ovl_path_upper(dentry, path); ++ ++ return type; ++} ++ ++struct dentry *ovl_dentry_upper(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return ovl_upperdentry_dereference(oe); ++} ++ ++struct dentry *ovl_dentry_lower(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ return oe->lowerdentry; ++} ++ ++struct dentry *ovl_dentry_real(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (!realdentry) ++ realdentry = oe->lowerdentry; ++ ++ return realdentry; ++} ++ ++struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper) ++{ ++ struct dentry *realdentry; ++ ++ realdentry = ovl_upperdentry_dereference(oe); ++ if (realdentry) { ++ *is_upper = true; ++ } else { ++ realdentry = oe->lowerdentry; ++ *is_upper = false; ++ } ++ return realdentry; ++} ++ ++bool ovl_dentry_is_opaque(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ return oe->opaque; ++} ++ ++void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ oe->opaque = opaque; ++} ++ ++void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&upperdentry->d_parent->d_inode->i_mutex)); ++ WARN_ON(oe->__upperdentry); ++ BUG_ON(!upperdentry->d_inode); ++ smp_wmb(); ++ oe->__upperdentry = dget(upperdentry); ++} ++ ++void ovl_dentry_version_inc(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ oe->version++; ++} ++ ++u64 ovl_dentry_version_get(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex)); ++ return oe->version; ++} ++ ++bool ovl_is_whiteout(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!dentry) ++ return false; ++ if (!dentry->d_inode) ++ return false; ++ if (!S_ISLNK(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_whiteout_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static bool ovl_is_opaquedir(struct dentry *dentry) ++{ ++ int res; ++ char val; ++ ++ if (!S_ISDIR(dentry->d_inode->i_mode)) ++ return false; ++ ++ res = vfs_getxattr(dentry, ovl_opaque_xattr, &val, 1); ++ if (res == 1 && val == 'y') ++ return true; ++ ++ return false; ++} ++ ++static void ovl_entry_free(struct rcu_head *head) ++{ ++ struct ovl_entry *oe = container_of(head, struct ovl_entry, rcu); ++ kfree(oe); ++} ++ ++static void ovl_dentry_release(struct dentry *dentry) ++{ ++ struct ovl_entry *oe = dentry->d_fsdata; ++ ++ if (oe) { ++ dput(oe->__upperdentry); ++ dput(oe->__upperdentry); ++ dput(oe->lowerdentry); ++ call_rcu(&oe->rcu, ovl_entry_free); ++ } ++} ++ ++const struct dentry_operations ovl_dentry_operations = { ++ .d_release = ovl_dentry_release, ++}; ++ ++static struct ovl_entry *ovl_alloc_entry(void) ++{ ++ return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL); ++} ++ ++static inline struct dentry *ovl_lookup_real(struct dentry *dir, struct qstr *name) ++{ ++ struct dentry *dentry; ++ ++ mutex_lock(&dir->d_inode->i_mutex); ++ dentry = lookup_one_len(name->name, dir, name->len); ++ mutex_unlock(&dir->d_inode->i_mutex); ++ ++ if (IS_ERR(dentry)) { ++ if (PTR_ERR(dentry) == -ENOENT) ++ dentry = NULL; ++ } else if (!dentry->d_inode) { ++ dput(dentry); ++ dentry = NULL; ++ } ++ return dentry; ++} ++ ++static int ovl_do_lookup(struct dentry *dentry) ++{ ++ struct ovl_entry *oe; ++ struct dentry *upperdir; ++ struct dentry *lowerdir; ++ struct dentry *upperdentry = NULL; ++ struct dentry *lowerdentry = NULL; ++ struct inode *inode = NULL; ++ int err; ++ ++ err = -ENOMEM; ++ oe = ovl_alloc_entry(); ++ if (!oe) ++ goto out; ++ ++ upperdir = ovl_dentry_upper(dentry->d_parent); ++ lowerdir = ovl_dentry_lower(dentry->d_parent); ++ ++ if (upperdir) { ++ upperdentry = ovl_lookup_real(upperdir, &dentry->d_name); ++ err = PTR_ERR(upperdentry); ++ if (IS_ERR(upperdentry)) ++ goto out_put_dir; ++ ++ if (lowerdir && upperdentry && ++ (S_ISLNK(upperdentry->d_inode->i_mode) || ++ S_ISDIR(upperdentry->d_inode->i_mode))) { ++ const struct cred *old_cred; ++ struct cred *override_cred; ++ ++ err = -ENOMEM; ++ override_cred = prepare_creds(); ++ if (!override_cred) ++ goto out_dput_upper; ++ ++ /* CAP_SYS_ADMIN needed for getxattr */ ++ cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); ++ old_cred = override_creds(override_cred); ++ ++ if (ovl_is_opaquedir(upperdentry)) { ++ oe->opaque = true; ++ } else if (ovl_is_whiteout(upperdentry)) { ++ dput(upperdentry); ++ upperdentry = NULL; ++ oe->opaque = true; ++ } ++ revert_creds(old_cred); ++ put_cred(override_cred); ++ } ++ } ++ if (lowerdir && !oe->opaque) { ++ lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name); ++ err = PTR_ERR(lowerdentry); ++ if (IS_ERR(lowerdentry)) ++ goto out_dput_upper; ++ } ++ ++ if (lowerdentry && upperdentry && ++ (!S_ISDIR(upperdentry->d_inode->i_mode) || ++ !S_ISDIR(lowerdentry->d_inode->i_mode))) { ++ dput(lowerdentry); ++ lowerdentry = NULL; ++ oe->opaque = true; ++ } ++ ++ if (lowerdentry || upperdentry) { ++ struct dentry *realdentry; ++ ++ realdentry = upperdentry ? upperdentry : lowerdentry; ++ err = -ENOMEM; ++ inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode, oe); ++ if (!inode) ++ goto out_dput; ++ } ++ ++ if (upperdentry) ++ oe->__upperdentry = dget(upperdentry); ++ ++ if (lowerdentry) ++ oe->lowerdentry = lowerdentry; ++ ++ dentry->d_fsdata = oe; ++ dentry->d_op = &ovl_dentry_operations; ++ d_add(dentry, inode); ++ ++ return 0; ++ ++out_dput: ++ dput(lowerdentry); ++out_dput_upper: ++ dput(upperdentry); ++out_put_dir: ++ kfree(oe); ++out: ++ return err; ++} ++ ++struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ++ struct nameidata *nd) ++{ ++ int err = ovl_do_lookup(dentry); ++ ++ if (err) ++ return ERR_PTR(err); ++ ++ return NULL; ++} ++ ++static void ovl_put_super(struct super_block *sb) ++{ ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++ ++ mntput(ufs->upper_mnt); ++ mntput(ufs->lower_mnt); ++ ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++ kfree(ufs); ++} ++ ++static int ovl_remount_fs(struct super_block *sb, int *flagsp, char *data) ++{ ++ int flags = *flagsp; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ /* When remounting rw or ro, we need to adjust the write access to the ++ * upper fs. ++ */ ++ if (((flags ^ sb->s_flags) & MS_RDONLY) == 0) ++ /* No change to readonly status */ ++ return 0; ++ ++ if (flags & MS_RDONLY) { ++ mnt_drop_write(ufs->upper_mnt); ++ return 0; ++ } else ++ return mnt_want_write(ufs->upper_mnt); ++} ++ ++/** ++ * ovl_statfs ++ * @sb: The overlayfs super block ++ * @buf: The struct kstatfs to fill in with stats ++ * ++ * Get the filesystem statistics. As writes always target the upper layer ++ * filesystem pass the statfs to the same filesystem. ++ */ ++static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct dentry *root_dentry = dentry->d_sb->s_root; ++ struct path path; ++ ovl_path_upper(root_dentry, &path); ++ ++ if (!path.dentry->d_sb->s_op->statfs) ++ return -ENOSYS; ++ return path.dentry->d_sb->s_op->statfs(path.dentry, buf); ++} ++ ++/** ++ * ovl_show_options ++ * ++ * Prints the mount options for a given superblock. ++ * Returns zero; does not fail. ++ */ ++static int ovl_show_options(struct seq_file *m, struct vfsmount *mnt) ++{ ++ struct super_block *sb = mnt->mnt_sb; ++ struct ovl_fs *ufs = sb->s_fs_info; ++ ++ seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); ++ seq_printf(m, ",upperdir=%s", ufs->config.upperdir); ++ return 0; ++} ++ ++static const struct super_operations ovl_super_operations = { ++ .put_super = ovl_put_super, ++ .remount_fs = ovl_remount_fs, ++ .statfs = ovl_statfs, ++ .show_options = ovl_show_options, ++}; ++ ++enum { ++ Opt_lowerdir, ++ Opt_upperdir, ++ Opt_err, ++}; ++ ++static const match_table_t ovl_tokens = { ++ {Opt_lowerdir, "lowerdir=%s"}, ++ {Opt_upperdir, "upperdir=%s"}, ++ {Opt_err, NULL} ++}; ++ ++static int ovl_parse_opt(char *opt, struct ovl_config *config) ++{ ++ char *p; ++ ++ config->upperdir = NULL; ++ config->lowerdir = NULL; ++ ++ while ((p = strsep(&opt, ",")) != NULL) { ++ int token; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ if (!*p) ++ continue; ++ ++ token = match_token(p, ovl_tokens, args); ++ switch (token) { ++ case Opt_upperdir: ++ kfree(config->upperdir); ++ config->upperdir = match_strdup(&args[0]); ++ if (!config->upperdir) ++ return -ENOMEM; ++ break; ++ ++ case Opt_lowerdir: ++ kfree(config->lowerdir); ++ config->lowerdir = match_strdup(&args[0]); ++ if (!config->lowerdir) ++ return -ENOMEM; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++static int ovl_fill_super(struct super_block *sb, void *data, int silent) ++{ ++ struct path lowerpath; ++ struct path upperpath; ++ struct inode *root_inode; ++ struct dentry *root_dentry; ++ struct ovl_entry *oe; ++ struct ovl_fs *ufs; ++ int err; ++ ++ err = -ENOMEM; ++ ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL); ++ if (!ufs) ++ goto out; ++ ++ err = ovl_parse_opt((char *) data, &ufs->config); ++ if (err) ++ goto out_free_ufs; ++ ++ err = -EINVAL; ++ if (!ufs->config.upperdir || !ufs->config.lowerdir) { ++ printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n"); ++ goto out_free_config; ++ } ++ ++ oe = ovl_alloc_entry(); ++ if (oe == NULL) ++ goto out_free_config; ++ ++ root_inode = ovl_new_inode(sb, S_IFDIR, oe); ++ if (!root_inode) ++ goto out_free_oe; ++ ++ err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath); ++ if (err) ++ goto out_put_root; ++ ++ err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath); ++ if (err) ++ goto out_put_upperpath; ++ ++ err = -ENOTDIR; ++ if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) || ++ !S_ISDIR(lowerpath.dentry->d_inode->i_mode)) ++ goto out_put_lowerpath; ++ ++ sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth, ++ lowerpath.mnt->mnt_sb->s_stack_depth) + 1; ++ ++ err = -EINVAL; ++ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ printk(KERN_ERR "overlayfs: maximum fs stacking depth exceeded\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ++ ufs->upper_mnt = clone_private_mount(&upperpath); ++ err = PTR_ERR(ufs->upper_mnt); ++ if (IS_ERR(ufs->upper_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone upperpath\n"); ++ goto out_put_lowerpath; ++ } ++ ++ ufs->lower_mnt = clone_private_mount(&lowerpath); ++ err = PTR_ERR(ufs->lower_mnt); ++ if (IS_ERR(ufs->lower_mnt)) { ++ printk(KERN_ERR "overlayfs: failed to clone lowerpath\n"); ++ goto out_put_upper_mnt; ++ } ++ ++ /* ++ * Make lower_mnt R/O. That way fchmod/fchown on lower file ++ * will fail instead of modifying lower fs. ++ */ ++ ufs->lower_mnt->mnt_flags |= MNT_READONLY; ++ ++ /* If the upper fs is r/o, we mark overlayfs r/o too */ ++ if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY) ++ sb->s_flags |= MS_RDONLY; ++ ++ if (!(sb->s_flags & MS_RDONLY)) { ++ err = mnt_want_write(ufs->upper_mnt); ++ if (err) ++ goto out_put_lower_mnt; ++ } ++ ++ err = -ENOMEM; ++ root_dentry = d_alloc_root(root_inode); ++ if (!root_dentry) ++ goto out_drop_write; ++ ++ mntput(upperpath.mnt); ++ mntput(lowerpath.mnt); ++ ++ oe->__upperdentry = dget(upperpath.dentry); ++ oe->lowerdentry = lowerpath.dentry; ++ ++ root_dentry->d_fsdata = oe; ++ root_dentry->d_op = &ovl_dentry_operations; ++ ++ sb->s_op = &ovl_super_operations; ++ sb->s_root = root_dentry; ++ sb->s_fs_info = ufs; ++ ++ return 0; ++ ++out_drop_write: ++ if (!(sb->s_flags & MS_RDONLY)) ++ mnt_drop_write(ufs->upper_mnt); ++out_put_lower_mnt: ++ mntput(ufs->lower_mnt); ++out_put_upper_mnt: ++ mntput(ufs->upper_mnt); ++out_put_lowerpath: ++ path_put(&lowerpath); ++out_put_upperpath: ++ path_put(&upperpath); ++out_put_root: ++ iput(root_inode); ++out_free_oe: ++ kfree(oe); ++out_free_config: ++ kfree(ufs->config.lowerdir); ++ kfree(ufs->config.upperdir); ++out_free_ufs: ++ kfree(ufs); ++out: ++ return err; ++} ++ ++static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *raw_data) ++{ ++ return mount_nodev(fs_type, flags, raw_data, ovl_fill_super); ++} ++ ++static struct file_system_type ovl_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "overlayfs", ++ .mount = ovl_mount, ++ .kill_sb = kill_anon_super, ++}; ++ ++static int __init ovl_init(void) ++{ ++ return register_filesystem(&ovl_fs_type); ++} ++ ++static void __exit ovl_exit(void) ++{ ++ unregister_filesystem(&ovl_fs_type); ++} ++ ++module_init(ovl_init); ++module_exit(ovl_exit); +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1300,6 +1300,7 @@ long do_splice_direct(struct file *in, l + + return ret; + } ++EXPORT_SYMBOL(do_splice_direct); + + static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, + struct pipe_inode_info *opipe, +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -480,6 +480,12 @@ struct iattr { + */ + #include <linux/quota.h> + ++/* ++ * Maximum number of layers of fs stack. Needs to be limited to ++ * prevent kernel stack overflow ++ */ ++#define FILESYSTEM_MAX_STACK_DEPTH 2 ++ + /** + * enum positive_aop_returns - aop return codes with specific semantics + * +@@ -1438,6 +1444,11 @@ struct super_block { + * Saved pool identifier for cleancache (-1 means none) + */ + int cleancache_poolid; ++ ++ /* ++ * Indicates how deep in a filesystem stack this SB is ++ */ ++ int s_stack_depth; + }; + + extern struct timespec current_fs_time(struct super_block *sb); +@@ -1603,6 +1614,7 @@ struct inode_operations { + void (*truncate_range)(struct inode *, loff_t, loff_t); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, + u64 len); ++ struct file *(*open)(struct dentry *, int flags, const struct cred *); + } ____cacheline_aligned; + + struct seq_file; +@@ -1998,6 +2010,7 @@ extern long do_sys_open(int dfd, const c + extern struct file *filp_open(const char *, int, int); + extern struct file *file_open_root(struct dentry *, struct vfsmount *, + const char *, int); ++extern struct file *vfs_open(struct path *, int flags, const struct cred *); + extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, + const struct cred *); + extern int filp_close(struct file *, fl_owner_t id); +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -100,6 +100,9 @@ extern void mnt_pin(struct vfsmount *mnt + extern void mnt_unpin(struct vfsmount *mnt); + extern int __mnt_is_readonly(struct vfsmount *mnt); + ++struct path; ++extern struct vfsmount *clone_private_mount(struct path *path); ++ + extern struct vfsmount *do_kern_mount(const char *fstype, int flags, + const char *name, void *data); + diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/11_fix_yylloc_for_modern_computers.patch b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/11_fix_yylloc_for_modern_computers.patch new file mode 100644 index 00000000..d7088f90 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/11_fix_yylloc_for_modern_computers.patch @@ -0,0 +1,11 @@ +--- a/scripts/dtc/dtc-lexer.lex.c_shipped 2015-08-07 22:08:04.000000000 +0300 ++++ b/scripts/dtc/dtc-lexer.lex.c_shipped 2021-11-01 22:15:12.347053553 +0300 +@@ -637,7 +637,7 @@ + #include "srcpos.h" + #include "dtc-parser.tab.h" + +-YYLTYPE yylloc; ++extern YYLTYPE yylloc; + + /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ + #define YY_USER_ACTION \ diff --git a/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/12_uimage_makefile.patch b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/12_uimage_makefile.patch new file mode 100644 index 00000000..428b5a73 --- /dev/null +++ b/br-ext-chip-fullhan/board/fh8852v100/kernel/patches/12_uimage_makefile.patch @@ -0,0 +1,62 @@ +--- linux-3.0.101/arch/arm/boot/Makefile 2013-10-22 11:58:59.000000000 +0400 ++++ linux-3.0.101/arch/arm/boot/Makefile 2021-12-15 10:51:15.956535987 +0300 +@@ -59,15 +59,19 @@ + + endif + +-quiet_cmd_uimage = UIMAGE $@ +- cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ +- -C none -a $(LOADADDR) -e $(STARTADDR) \ +- -n 'Linux-$(KERNELRELEASE)' -d $< $@ ++#quiet_cmd_uimage = UIMAGE $@ ++# cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ ++# -C none -a $(LOADADDR) -e $(STARTADDR) \ ++# -n 'Linux-$(KERNELRELEASE)' -d $< $@ + +-ifeq ($(CONFIG_ZBOOT_ROM),y) +-$(obj)/uImage: LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT) ++ifneq ($(LOADADDR),) ++ UIMAGE_LOADADDR=$(LOADADDR) + else +-$(obj)/uImage: LOADADDR=$(ZRELADDR) ++ ifeq ($(CONFIG_ZBOOT_ROM),y) ++ UIMAGE_LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT) ++ else ++ UIMAGE_LOADADDR=$(ZRELADDR) ++ endif + endif + + $(obj)/uImage: STARTADDR=$(LOADADDR) +--- linux-3.0.101/scripts/Makefile.lib 2013-10-22 11:58:59.000000000 +0400 ++++ linux-3.0.101/scripts/Makefile.lib 2021-12-15 10:53:24.551357718 +0300 +@@ -262,6 +262,30 @@ + lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + ++# U-Boot mkimage ++# --------------------------------------------------------------------------- ++ ++MKIMAGE := $(srctree)/scripts/mkuboot.sh ++ ++# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces ++# the number of overrides in arch makefiles ++UIMAGE_ARCH ?= $(SRCARCH) ++UIMAGE_COMPRESSION ?= $(if $(2),$(2),none) ++UIMAGE_OPTS-y ?= ++UIMAGE_TYPE ?= kernel ++UIMAGE_LOADADDR ?= arch_must_set_this ++UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR) ++UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)' ++UIMAGE_IN ?= $< ++UIMAGE_OUT ?= $@ ++ ++quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT) ++ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \ ++ -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \ ++ -T $(UIMAGE_TYPE) \ ++ -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \ ++ -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT) ++ + # XZ + # --------------------------------------------------------------------------- + # Use xzkern to compress the kernel image and xzmisc to compress other things. diff --git a/br-ext-chip-fullhan/configs/unknown_unknown_fh8833v100_openipc_defconfig b/br-ext-chip-fullhan/configs/unknown_unknown_fh8833v100_openipc_defconfig new file mode 100644 index 00000000..5319bd4f --- /dev/null +++ b/br-ext-chip-fullhan/configs/unknown_unknown_fh8833v100_openipc_defconfig @@ -0,0 +1,97 @@ +# Architecture +BR2_arm=y +BR2_arm926t=y +BR2_ARM_EABI=y +# BR2_ARM_INSTRUCTIONS_THUMB is not set +BR2_KERNEL_HEADERS_VERSION=y +BR2_DEFAULT_KERNEL_VERSION="3.0.8" +BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_3_0=y + +# Toolchain +BR2_PER_PACKAGE_DIRECTORIES=y +BR2_GCC_VERSION_7_X=y +# BR2_TOOLCHAIN_USES_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_LIBC="uclibc" +BR2_TOOLCHAIN_USES_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_LIBC="musl" +BR2_TOOLCHAIN_BUILDROOT_CXX=y +BR2_TOOLCHAIN_BUILDROOT_LOCALE=y +BR2_TOOLCHAIN_BUILDROOT_USE_SSP=y + +# Kernel +BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="3.0.8" +BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y +BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8833v100/kernel/fh8833v100.generic.config" +BR2_LINUX_KERNEL_UIMAGE=y +BR2_LINUX_KERNEL_XZ=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER_LIST="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8833v100/kernel/patches/ $(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8833v100/kernel/overlay" + +# Filesystem +# BR2_TARGET_TZ_INFO is not set +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_SQUASHFS=y +BR2_TARGET_ROOTFS_SQUASHFS4_XZ=y +BR2_ROOTFS_OVERLAY="$(TOPDIR)/../general/overlay" +BR2_ROOTFS_POST_BUILD_SCRIPT="$(TOPDIR)/../scripts/executing_commands_for_$(BR2_TOOLCHAIN_BUILDROOT_LIBC).sh" + +# OpenIPC configuration +BR2_TOOLCHAIN_BUILDROOT_VENDOR="openipc" +BR2_TARGET_GENERIC_ISSUE="Welcome to OpenIPC v2.2" +BR2_TARGET_GENERIC_HOSTNAME="openipc-fh8833v100" +BR2_GLOBAL_PATCH_DIR="$(TOPDIR)/../general/package/all-patches" + +# OpenIPC packages +BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config" +BR2_PACKAGE_DROPBEAR=y +# BR2_PACKAGE_FDK_AAC_OPENIPC is not set +BR2_PACKAGE_FWPRINTENV_OPENIPC=y +BR2_PACKAGE_HASERL=y +BR2_PACKAGE_FULLHAN_OSDRV_FH8852V100=y +BR2_PACKAGE_IPCTOOL=y +BR2_PACKAGE_JSON_C=y +BR2_PACKAGE_LAME_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC_CURL=y +# BR2_PACKAGE_LIBCURL_OPENIPC_VERBOSE is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_PROXY_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_COOKIES_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_EXTRA_PROTOCOLS_FEATURES is not set +BR2_PACKAGE_LIBCURL_OPENIPC_MBEDTLS=y +BR2_PACKAGE_LIBEVENT_OPENIPC=y +BR2_PACKAGE_LIBEVENT_OPENIPC_REMOVE_PYSCRIPT=y +BR2_PACKAGE_LIBOGG_OPENIPC=y +BR2_PACKAGE_LIBWEBSOCKETS_OPENIPC=y +BR2_PACKAGE_LIBYAML=y +BR2_PACKAGE_MAJESTIC_FONTS=y +# BR2_PACKAGE_MAJESTIC_FH8852V100=y +BR2_PACKAGE_MBEDTLS_OPENIPC=y +# BR2_PACKAGE_MBEDTLS_OPENIPC_PROGRAMS is not set +# BR2_PACKAGE_MBEDTLS_OPENIPC_COMPRESSION is not set +BR2_PACKAGE_MICROBE_WEB=y +# BR2_PACKAGE_MINI_SNMPD is not set +BR2_PACKAGE_MOTORS=y +BR2_PACKAGE_OPUS_OPENIPC=y +BR2_PACKAGE_OPUS_OPENIPC_FIXED_POINT=y +# BR2_PACKAGE_SSHPASS is not set +BR2_PACKAGE_UACME_OPENIPC=y +BR2_PACKAGE_VTUND_OPENIPC=y +BR2_PACKAGE_YAML_CLI=y + +# WiFi +BR2_PACKAGE_WIRELESS_TOOLS=y +BR2_PACKAGE_WPA_SUPPLICANT=y +BR2_PACKAGE_WPA_SUPPLICANT_CLI=y +BR2_PACKAGE_WPA_SUPPLICANT_NL80211=y +BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC_MT7601U=y +# BR2_PACKAGE_RTL8188EU is not set + +# WIREGUARD +BR2_PACKAGE_WIREGUARD_LINUX_COMPAT=y +BR2_PACKAGE_WIREGUARD_TOOLS=y diff --git a/br-ext-chip-fullhan/configs/unknown_unknown_fh8852v100_openipc_defconfig b/br-ext-chip-fullhan/configs/unknown_unknown_fh8852v100_openipc_defconfig new file mode 100644 index 00000000..cd69021f --- /dev/null +++ b/br-ext-chip-fullhan/configs/unknown_unknown_fh8852v100_openipc_defconfig @@ -0,0 +1,97 @@ +# Architecture +BR2_arm=y +BR2_arm926t=y +BR2_ARM_EABI=y +# BR2_ARM_INSTRUCTIONS_THUMB is not set +BR2_KERNEL_HEADERS_VERSION=y +BR2_DEFAULT_KERNEL_VERSION="3.0.8" +BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_3_0=y + +# Toolchain +BR2_PER_PACKAGE_DIRECTORIES=y +BR2_GCC_VERSION_7_X=y +# BR2_TOOLCHAIN_USES_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_LIBC="uclibc" +BR2_TOOLCHAIN_USES_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_LIBC="musl" +BR2_TOOLCHAIN_BUILDROOT_CXX=y +BR2_TOOLCHAIN_BUILDROOT_LOCALE=y +BR2_TOOLCHAIN_BUILDROOT_USE_SSP=y + +# Kernel +BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="3.0.8" +BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y +BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8852v100/kernel/fh8852v100.generic.config" +BR2_LINUX_KERNEL_UIMAGE=y +BR2_LINUX_KERNEL_XZ=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER_LIST="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8852v100/kernel/patches/ $(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8852v100/kernel/overlay" + +# Filesystem +# BR2_TARGET_TZ_INFO is not set +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_SQUASHFS=y +BR2_TARGET_ROOTFS_SQUASHFS4_XZ=y +BR2_ROOTFS_OVERLAY="$(TOPDIR)/../general/overlay" +BR2_ROOTFS_POST_BUILD_SCRIPT="$(TOPDIR)/../scripts/executing_commands_for_$(BR2_TOOLCHAIN_BUILDROOT_LIBC).sh" + +# OpenIPC configuration +BR2_TOOLCHAIN_BUILDROOT_VENDOR="openipc" +BR2_TARGET_GENERIC_ISSUE="Welcome to OpenIPC v2.2" +BR2_TARGET_GENERIC_HOSTNAME="openipc-fh8852v100" +BR2_GLOBAL_PATCH_DIR="$(TOPDIR)/../general/package/all-patches" + +# OpenIPC packages +BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config" +BR2_PACKAGE_DROPBEAR=y +# BR2_PACKAGE_FDK_AAC_OPENIPC is not set +BR2_PACKAGE_FWPRINTENV_OPENIPC=y +BR2_PACKAGE_HASERL=y +BR2_PACKAGE_FULLHAN_OSDRV_FH8852V100=y +BR2_PACKAGE_IPCTOOL=y +BR2_PACKAGE_JSON_C=y +BR2_PACKAGE_LAME_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC_CURL=y +# BR2_PACKAGE_LIBCURL_OPENIPC_VERBOSE is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_PROXY_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_COOKIES_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_EXTRA_PROTOCOLS_FEATURES is not set +BR2_PACKAGE_LIBCURL_OPENIPC_MBEDTLS=y +BR2_PACKAGE_LIBEVENT_OPENIPC=y +BR2_PACKAGE_LIBEVENT_OPENIPC_REMOVE_PYSCRIPT=y +BR2_PACKAGE_LIBOGG_OPENIPC=y +BR2_PACKAGE_LIBWEBSOCKETS_OPENIPC=y +BR2_PACKAGE_LIBYAML=y +BR2_PACKAGE_MAJESTIC_FONTS=y +# BR2_PACKAGE_MAJESTIC_FH8852V100=y +BR2_PACKAGE_MBEDTLS_OPENIPC=y +# BR2_PACKAGE_MBEDTLS_OPENIPC_PROGRAMS is not set +# BR2_PACKAGE_MBEDTLS_OPENIPC_COMPRESSION is not set +BR2_PACKAGE_MICROBE_WEB=y +# BR2_PACKAGE_MINI_SNMPD is not set +BR2_PACKAGE_MOTORS=y +BR2_PACKAGE_OPUS_OPENIPC=y +BR2_PACKAGE_OPUS_OPENIPC_FIXED_POINT=y +# BR2_PACKAGE_SSHPASS is not set +BR2_PACKAGE_UACME_OPENIPC=y +BR2_PACKAGE_VTUND_OPENIPC=y +BR2_PACKAGE_YAML_CLI=y + +# WiFi +BR2_PACKAGE_WIRELESS_TOOLS=y +BR2_PACKAGE_WPA_SUPPLICANT=y +BR2_PACKAGE_WPA_SUPPLICANT_CLI=y +BR2_PACKAGE_WPA_SUPPLICANT_NL80211=y +BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC_MT7601U=y +# BR2_PACKAGE_RTL8188EU is not set + +# WIREGUARD +BR2_PACKAGE_WIREGUARD_LINUX_COMPAT=y +BR2_PACKAGE_WIREGUARD_TOOLS=y diff --git a/br-ext-chip-fullhan/configs/unknown_unknown_fh8856v100_openipc_defconfig b/br-ext-chip-fullhan/configs/unknown_unknown_fh8856v100_openipc_defconfig new file mode 100644 index 00000000..8f30dd26 --- /dev/null +++ b/br-ext-chip-fullhan/configs/unknown_unknown_fh8856v100_openipc_defconfig @@ -0,0 +1,97 @@ +# Architecture +BR2_arm=y +BR2_arm926t=y +BR2_ARM_EABI=y +# BR2_ARM_INSTRUCTIONS_THUMB is not set +BR2_KERNEL_HEADERS_VERSION=y +BR2_DEFAULT_KERNEL_VERSION="3.0.8" +BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_3_0=y + +# Toolchain +BR2_PER_PACKAGE_DIRECTORIES=y +BR2_GCC_VERSION_7_X=y +# BR2_TOOLCHAIN_USES_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_UCLIBC is not set +# BR2_TOOLCHAIN_BUILDROOT_LIBC="uclibc" +BR2_TOOLCHAIN_USES_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_MUSL=y +BR2_TOOLCHAIN_BUILDROOT_LIBC="musl" +BR2_TOOLCHAIN_BUILDROOT_CXX=y +BR2_TOOLCHAIN_BUILDROOT_LOCALE=y +BR2_TOOLCHAIN_BUILDROOT_USE_SSP=y + +# Kernel +BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="3.0.8" +BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y +BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8856v100/kernel/fh8856v100.generic.config" +BR2_LINUX_KERNEL_UIMAGE=y +BR2_LINUX_KERNEL_XZ=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER=y +BR2_LINUX_KERNEL_EXT_FULLHAN_PATCHER_LIST="$(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8856v100/kernel/patches/ $(BR2_EXTERNAL_FULLHAN_PATH)/board/fh8856v100/kernel/overlay" + +# Filesystem +# BR2_TARGET_TZ_INFO is not set +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_SQUASHFS=y +BR2_TARGET_ROOTFS_SQUASHFS4_XZ=y +BR2_ROOTFS_OVERLAY="$(TOPDIR)/../general/overlay" +BR2_ROOTFS_POST_BUILD_SCRIPT="$(TOPDIR)/../scripts/executing_commands_for_$(BR2_TOOLCHAIN_BUILDROOT_LIBC).sh" + +# OpenIPC configuration +BR2_TOOLCHAIN_BUILDROOT_VENDOR="openipc" +BR2_TARGET_GENERIC_ISSUE="Welcome to OpenIPC v2.2" +BR2_TARGET_GENERIC_HOSTNAME="openipc-fh8856v100" +BR2_GLOBAL_PATCH_DIR="$(TOPDIR)/../general/package/all-patches" + +# OpenIPC packages +BR2_PACKAGE_BUSYBOX_CONFIG="$(TOPDIR)/../general/package/busybox/busybox.config" +BR2_PACKAGE_DROPBEAR=y +# BR2_PACKAGE_FDK_AAC_OPENIPC is not set +BR2_PACKAGE_FWPRINTENV_OPENIPC=y +BR2_PACKAGE_HASERL=y +BR2_PACKAGE_FULLHAN_OSDRV_FH8852V100=y +BR2_PACKAGE_IPCTOOL=y +BR2_PACKAGE_JSON_C=y +BR2_PACKAGE_LAME_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC=y +BR2_PACKAGE_LIBCURL_OPENIPC_CURL=y +# BR2_PACKAGE_LIBCURL_OPENIPC_VERBOSE is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_PROXY_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_COOKIES_SUPPORT is not set +# BR2_PACKAGE_LIBCURL_OPENIPC_EXTRA_PROTOCOLS_FEATURES is not set +BR2_PACKAGE_LIBCURL_OPENIPC_MBEDTLS=y +BR2_PACKAGE_LIBEVENT_OPENIPC=y +BR2_PACKAGE_LIBEVENT_OPENIPC_REMOVE_PYSCRIPT=y +BR2_PACKAGE_LIBOGG_OPENIPC=y +BR2_PACKAGE_LIBWEBSOCKETS_OPENIPC=y +BR2_PACKAGE_LIBYAML=y +BR2_PACKAGE_MAJESTIC_FONTS=y +# BR2_PACKAGE_MAJESTIC_FH8852V100=y +BR2_PACKAGE_MBEDTLS_OPENIPC=y +# BR2_PACKAGE_MBEDTLS_OPENIPC_PROGRAMS is not set +# BR2_PACKAGE_MBEDTLS_OPENIPC_COMPRESSION is not set +BR2_PACKAGE_MICROBE_WEB=y +# BR2_PACKAGE_MINI_SNMPD is not set +BR2_PACKAGE_MOTORS=y +BR2_PACKAGE_OPUS_OPENIPC=y +BR2_PACKAGE_OPUS_OPENIPC_FIXED_POINT=y +# BR2_PACKAGE_SSHPASS is not set +BR2_PACKAGE_UACME_OPENIPC=y +BR2_PACKAGE_VTUND_OPENIPC=y +BR2_PACKAGE_YAML_CLI=y + +# WiFi +BR2_PACKAGE_WIRELESS_TOOLS=y +BR2_PACKAGE_WPA_SUPPLICANT=y +BR2_PACKAGE_WPA_SUPPLICANT_CLI=y +BR2_PACKAGE_WPA_SUPPLICANT_NL80211=y +BR2_PACKAGE_WPA_SUPPLICANT_PASSPHRASE=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC=y +BR2_PACKAGE_LINUX_FIRMWARE_OPENIPC_MT7601U=y +# BR2_PACKAGE_RTL8188EU is not set + +# WIREGUARD +BR2_PACKAGE_WIREGUARD_LINUX_COMPAT=y +BR2_PACKAGE_WIREGUARD_TOOLS=y diff --git a/br-ext-chip-fullhan/external.mk b/br-ext-chip-fullhan/external.mk index 19772ffc..03b6ca4c 100644 --- a/br-ext-chip-fullhan/external.mk +++ b/br-ext-chip-fullhan/external.mk @@ -1,4 +1,5 @@ include $(BR2_EXTERNAL_FULLHAN_PATH)/linux/linux-ext-fullhan_patcher.mk +include $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/fullhan-osdrv-fh8852v100.mk include $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v200/fullhan-osdrv-fh8852v200.mk include $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan_patcher/fullhan_patcher.mk include $(BR2_EXTERNAL_FULLHAN_PATH)/package/aura-httpd/aura-httpd.mk diff --git a/br-ext-chip-fullhan/package/fullhan-osdrv-fh8852v100 b/br-ext-chip-fullhan/package/fullhan-osdrv-fh8852v100 new file mode 120000 index 00000000..126e195c --- /dev/null +++ b/br-ext-chip-fullhan/package/fullhan-osdrv-fh8852v100 @@ -0,0 +1 @@ +../../general/package/fullhan-osdrv-fh8852v100 \ No newline at end of file diff --git a/building.sh b/building.sh index 9c5548b3..1bdabc8f 100755 --- a/building.sh +++ b/building.sh @@ -60,6 +60,21 @@ sdk() { ################################################################################# +fh8833v100() { + soc="fh8833v100" + fresh && make PLATFORM=fullhan BOARD=unknown_unknown_${soc}_openipc all && rename +} + +fh8852v100() { + soc="fh8852v100" + fresh && make PLATFORM=fullhan BOARD=unknown_unknown_${soc}_openipc all && rename +} + +fh8856v100() { + soc="fh8856v100" + fresh && make PLATFORM=fullhan BOARD=unknown_unknown_${soc}_openipc all && rename +} + fh8852v200() { soc="fh8852v200" fresh && make PLATFORM=fullhan BOARD=unknown_unknown_${soc}_openipc all && rename @@ -375,6 +390,10 @@ xm550() { # Build firmware # +# fh8833v100 # testing.. +# fh8852v100 # testing.. +# fh8856v100 # testing.. +# fh8852v200 # testing.. # fh8856v200 # testing.. # fh8858v200 # testing.. diff --git a/general/package/fullhan-osdrv-fh8852v100/Config.in b/general/package/fullhan-osdrv-fh8852v100/Config.in new file mode 100644 index 00000000..4e0a1caf --- /dev/null +++ b/general/package/fullhan-osdrv-fh8852v100/Config.in @@ -0,0 +1,6 @@ +config BR2_PACKAGE_FULLHAN_OSDRV_FH8852V100 + bool "fullhan-osdrv-fh8852v100" + help + fullhan-osdrv-fh8852v100 - Fullhan kernel modules and libs + + https://openipc.org diff --git a/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852.bin b/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852.bin new file mode 100755 index 0000000000000000000000000000000000000000..9648dc45d2572abb144877694e3aaf15ac9961ce GIT binary patch literal 417944 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	($ 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Ν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�>bICO%CtnoYNcS93=t=xryV0 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℘O&P;#N(9#T5HIZdrmK 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852_human_detect.bin b/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8852_human_detect.bin new file mode 100755 index 0000000000000000000000000000000000000000..668cdc43ab0ad349363fc55a6cdd7bfdec6c5940 GIT binary patch literal 498804 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856.bin b/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856.bin new file mode 100755 index 0000000000000000000000000000000000000000..9648dc45d2572abb144877694e3aaf15ac9961ce GIT binary patch literal 417944 zcmbTf3w#vS**|_}b`mDDx7pkXA%w|hb1@(UiqukSXV-u+AOtMF*0=fwR9=LNn@s~T zYMgAc0pf*7tv_C0Uk%ZOo8YBtEn3|KL=%;ZwH88aw?X}pNRUu&`Xc-PJ~O+Ui_rS} z>nEI<Gw1T0bDs0u&)JZo*-vg}Tu4tBK4YX8pHcMpZOukny~#*RT8uRPStIR>q`RIo z-Wywu^p-XwE!b?N-$c@`EynwkTa9%2HY1&}-AJY9jkG(GZrfqJSMM~^k{66L{Y4|~ zi=?|=GTs|sHqu*uYorCQ80j~WwCh#l{mIvibouWjm-f@Mo14n&T|fP)$CWWna%w+4 zv$?6aB%2kk$W`yf+_3GrqL<;nZ3@TND{tGkBVDej0zI!lDq*h9Y`*`rl%?6x*3BuR z%1WH5kft$JVcgeZkw*QU-aPaDl3eDE{@taZ+>rNBRj7)kGVhtq+UZbDsA?dXQicCf zg0cT=sus&~8?)@v!61DzzF){F{%xB%B#4zPQ>~zSLh|@R_D-uQB(wxsDzCRS5OgnR znVSCGAgaPmn#bv34rvOzsd<r>DwPR0H6IM7u%JMFo<^He4r}tf>)ty#uUOv0ve>3} zR|@aQmd0~;2gaETS^ciE`?h+eT-MaYoNQ}3eXZZM@YN~O-`KpskEBAj)mv8GTmG=} z_M?+fUtE=RqSGq_HX+$MmD|g|8+!1$U@mI?QM#x#Di7LD4Pfk_=BN1Oy0`!Fs(bnT z>OV?TwES^?*_7cg+z;5V-oC&5%;x6p`+cW3U;X86wh-5tZ4yn%{=)gy-%5pAr}qHb zppwhBd+@c>_t>bf!kykw6`$ex!C(tFM_R~4ncp4Z_4+k^IVek`7#zQQujk$3Rh!x; z0{;BfzQBt6WIS~#Sr}VydD(rPzLDcGjp#>m(wd*{d)Z2`&WgZV)Au{{<qObUpO4J7 zd+(<94C-eUJM@05B{ol?2cHdwsxIB`p}t%6b_2G-Ibet0LEG=QUasvAzGvHS_Fc3P z%zI5E+x|droA8csgkav(o@p&JZS}H4Vg&BcgDt_4Fw?5t{N*;ZdfgGD&6>W?uwDbf zld(DQylcr|(~4JbYELh}87(hcm7h{CPqD~MO%dcDSqhm{j=A?`V^4KfB*$inf7g;M z7ls~e#auPgoG4-YQOpB76soG$-`}?VG4ehVE@O?-zO?D%-4h>$?IDz>-oGDwMc*5~ zKI&%(eBJu{zk*Nva-~_vA@*JPqHFOBeJyAQJ%Ig3JA8iioNC%Znb@Pjs`-H&<g-I% z)smu`#)z6d9R4OO9vix9p{m?*_2Y@w4b2@nXSA02Uw$fuxKpvUd_<owzx-RIG(KY= z5e-STD1x}!T=lx-H?dSJ_Gfb6Xlw0wN;6J22d=Ve`m-m;mfBn1>Agm5=H%|v$38VP zA^q6Xl4k1k(vD#7MCnEczN|jhfG_OO@GqgNk!1&h$AMpjSCYb-<qUNi?dy4%tI1hw zm1?sh<O8;hOTd;6*rtqtt;JrZ!{z}5<|>9-<`Y*jh0%yZRRwzP@dUp~0+#v{%1omU zvu;;fkt;vVujHoHPo|k=hX`|x(GcFs$qwLd8*mr+S~HX;EYnx?hJc;c?Ne8Z$uY*9 z$r&Rw=%_&-vK0+9iKwxHmF`k%O;LJ0oRS!{acj9VA;baiO~1!l5q-SW`WAnAQ4Dd9 z$JX}&l)V8oi)9jjS{va{G`Gf_iW$Kl&@7i^G37DL$fovCRi?EWyiqmrR!tyYbar$7 z>_7YHUxmwJ>0ZJHdOMwBZ%VQk%D{lMk~If?=P_>9tp)__ss{o>I^*bR#eFP8!|42` zO|3_j4%XcIjZ_BQs0|%JdCB{-MH2>6I-2g55?PznY>ErS>)&7hD%$rtiTHE<Y#&PY zh-Dlon0%`!YcwyffV+UN9FG@+oWUzFE7OSMJp8=QagLv`H*>ee=3@hB*Xb12v{zD0 z$tj%tBv!lAJNK)SHMxE2Xx?FVYTDK2zw=#6JFwmu`#Pz1J@ub9f^tPMz>YaC*&M3+ z!mJ4=(Eg2U7Uk_u_WE8K)f1*RX-}6{Z$&9}e7zj1x{&eS?+hNl_B8d^qxjiM+y3xb zovsq>hrsJjZhkX?9f6z!8Rg;AQjTV)?cJE$Zl`fRd?C}O2qk$;G~Nyd9~s3U2k02B z%OE4^^F0p|eZCrVUc73nmplBVO)*J6HAhHehdzGQHI6wH{0;25G<_b9YayK%m!8;Q zYvvANZtDwgbnW53wiIexz1uNP?(lGaJilgBdog;>Url@fkehhyusN-b&ahq0F{KrN z+Ob2d`>xhyt@%17<Jbh`9o+HHdG*Qd5nkON4@erb-vi&PE4=5vZ_NbBe*uzS-%#0z zXb8bFEe6X5t70-8CKy;ZJ9KadK~T~<ve%J&O?ckux2gY8EA{&!c==$zJ7WFPJ|lih z{n9R@JvUhym9?pTMtSk7I{?Kp%!qK<1}F-!7V&9nPTV+l$T5yjc8$}pBATPC_3W#Y zBGkPwl1`1JSC3O2)9`mW%p3`KS_E#T{}T(r{YS}^94Ndo=N;~AE6vz_fLy@Z9lHeF z$r&18zYeh9QeM1z*{Y`iy_ChWwtC|Z&$B3|62Q-=-M&)Dt^=lC2w&g2XGL-As#goV zG@8CvpEZ=zSuQC4^^AqX?8xX>?`~b$N>bWAt-Tc`F2<h0T5VA@j*Vs9#)>1i)4nMz zc*`^$e|f9FYGsF_<IlLnPE1Zt1U=sT9l0w%GUnHh_n2wS{~k9e8*TMohY`mej><F9 zb(*j56<!1#%w_UQi^7SOPaliNJ9f^YTQFKFOEV>jh0qgBVt$$++||6Sd0@+>_s$@l zDm-zU8RP4YQYuKuF-lc<!lT1iBpA3<^W}RwJs`QB;1VIz`s`)G<Oe@B6FhClR^e@{ zmp{~HHsHBJhldxhZ!T`e?rNspm7i9R)!<k`nx749Vcipuj>PUk_&)A`OS&9<ANRLN zG=JCgQCTMV9r!-75q#I^@I7_x6TEHpnhq62;4|in7YDW&5SBELgv8JT44UrkpL$tX zy#1*<EH+CNmM*|z(CfJ#gBQ=K7Auc}vby)qu&KgUpOR?euQWG9r>U`pOrC5eP6vF@ z0Zr5G3=#=RPQ={}-kcAe!o55dC4Tnm$Zv*hLi?KJr0BlRU;P1ac~kotyDUc`QNbDK zR1*|kipTV_RTYW@%L6mKcRu(VTeF-$E|^rJFr_fDj=9a5Y+|Co@>AkuAt#=@&Z2Ru zzt>jVw82^?6nK9wmMZMf<@foY%(rP&m)a0=gxa2eOa%XRnBQU{e|%0Hmk%n@V8ytd zOe|4UWpji^&9E^OQEZaAa{=Eok>}y`K1%OO`=5rC*O<NE9G&-dnD-T^GblTXm4vN( zEoB1q@+tcgLMCyQl*gK$JoU0g6`TnQhd24K=wPp*jHCojJM~mEwIl>hkK$Qe6`emT zBq(upS@l-$oWSSOCKF-w1W3w;l>7iRVd4@6DRr_t)h|1+x}9GBa7}_Ds5$<0W6fuo zHKy0Wikn-rlIoZWx<d6<Swg0QaUJrc2pp5Fga_ZnNx}toWJRlcd1H3i{<Bx9&Nt>V zp%=Q-$kKy*skz^0S1+^IoBMBqMB11=H=?K2^i^XXd%bOFb$%Q151LP%N<2^UO>=)P z+A^pHpV9FHgK8K&sJUN?v=!Bf=j!{C_<xk1<%4!iR@Nv}(Z0C)X?uu?m9HI}jyG_h zLyh(j-&;=j{5UX}cp*`2;)I{PdZ4P!Qf5kARtwr9wSvNryBsf?*Lp+iR_~=K;NYCF z{@ZMqn-kXWvC*774xU83wC2kfF^-oa_;?C1l1#cO@;<2F8JyL<H@$pQ`*FZuyxOd= z=hmM3AMC@4Sh>>G)$B?}^BKh|Qy*beuA~b41Mk-~o>Cho!Im<=l^yBzNzi0gVSa?P z1B^$Bc>%MIgTa;?0s%bjYbC5=d|`^<DD|o?4=Y2TH@{jSVQ(o+>`5?ix<?{hy3}kC zPsR#DhBGW9^%4Gb|8b9%#{Vhkt1<p982^Sydt`f{Jz9tKL+J9{Fq=h`$K8MYqJ`SH zjpt(a6`GCe0X~DDHrS^(*5^LG{L_3CckV==nF*>ud=d5?=z~!i#`CVBF%Z3*fw?|u z%ypLfT;r)t|6;Cp!Fok=oyL(R#-A<7yla<8bB-C$QiXV12%5kKlv)|MAt0_++t$Ha z_2GBsnk1&1Uwun7=6V%cAo{T?f#&-1wDHpO{mbJYnQ5;62K$aN-)$JXGtwsM!!+Ly zBHee{`TphcNA))TLmV>Sn2{>XH?)x08b{~*m&b3@%ReJV=lgc_xzo;sYh&~M8TPF~ zL!+F9B(JoL;I#ZzE$xyMQ;-oXTxwSY+R-a5%_gF!ki?n=o@4XS)>~%GW)@R^4;s4= z<*;vr5~RJ}?GL<&6?nhqqf^r@T13D3nTH(_SI?=wr#Z@}B(yOD9OoLP+FKIXQ++FG z>>YmvwQY31ZJ)pSqD>K&LklGBsMIsa-|TB#;Gtr~QW({dNiIuEPJ(Q<1+rO@;#cNZ zPwFcP2)X{IPyX?$_*OGZ*OZdLUR^^f!CVj03$=feG)OPv$f6jNm(>15iPrC+DK4^p zjhM?(!>o=ENAO(j|003PIxM5~vZNodjvvDMNF(~==F;(e^1(+wv0^TPPd~I3%A^;$ zZRIlSC=TRVH0B;1kh8$2Q>^c>zd}zIz-Q_GL+c)<`oFf+YIg<HJU&f*_O8v>w<_bA zgLRCRd~8wPz7%#Ct2SyLq>fJS^aMrd^uA?Pz|-Hd1$p}#bJd+^p0qOI#x>R6t?|G* z%tol{cX%S26+djBNBOYYpQ?}NF(E#-&)=^}!T5EY(|Ly4e@cw<3?Zfy8$3hp{{(t8 z&0SW<{OX#%599WSLsc{;H4mClMv%EMg2gRA1y&Ys9<Ixk0s%L*D=9qY$ewnEU6Z>l z3_M#55O*dTn2C9u2^;z+78+}D;P3X@rkBMKPqxO9{BpRQVd$0Wi5Y<IOiX7dJ+2rw zjDH2k!Vz#hfxSU+Ks$-SQSiOsi0YM}_3yMRn5VTddFMCZ6PCT^;d3HIVCgUq!t%7e z`FqSsbj`JXrw+@$i2hR3_kCfRF#?tvvoSBzhrp8fy<my*nJveku+h9c#YN@7L0F>v z!jOy&t}z)p_pg9A>Au=8K>uOE42N@0w@4(X+0%*xSK6E98Qu-j@HzWLGT?j^<vP8~ zfJg03M9XUMo<B}Vt}zGse@^#@`VT@8TY+$*+e)yHN-$t2A4KgJuVU{E$`nz#X>yHM z$M&I6pTG_tgc{aKr8{9b+?f%$KhgKPf&Y@X1fHe6$SG;vD-qn6lMRN#99{c~{kb~K z8|*`2eocp&^h1MREJW)hbH8OJE$8`TH{qT1o5!rOJaoSnjDUA#f-%pzL*Vt>E{&Um zv{^Z^!NOwlEkBGlD<@W2XpRL-l+SgE1}yhl9Ze(myg`$c6CS-zeN3lYFl?_GV_b=L zXpG$!V~oB?yCcUqTO7V7jiNC|56VYr($m&|HO4*tJI$9H<DUKv&~qEJ*GbVaeqj%R ze`u!fjxkD4_VnMT*GY)cli_0|8JuvBY%81E{q~^gl&-OEIR+UW+@m-UrMXM-Z79v% zW-rre-I7Q-qPcHb{?+)(`u9nL<I_EMG5%WC|FT5mv%?-izPg&ew}5ZMeR5I!EbDL3 z%dR&?=b~i<ZoX!N%!YMy>f?Fk*e<-&T(yqC%|~s+#|4XmKCVWTkFJ{|r9)l}YccdU zUJ7)ZFFneka>Ux>UnC5Ub2zT9J>Hc-;~W>0$zBHRaRKN(d_mwKo`>UWlm@OnzCo|| z*O-6sCoy~_8W^P^BsG&iaz^=N<y~bbba0Z_(xqmG)t0wHMx#7f(GKxab3_mO80#O* z>QN3<3t6?3$(nY@U4;|gf^Np^y4m%u#jVp{{qw65w4%x09lCBdDJ9Oqx^HNm*ZKo% zA)DVi5gJNy&izdEsV;$IN65COa%C;W6`IeJGm8~Ytl_5PFVAaljoQ_=dM_tM5AOSo z$Db4j=W;mCY&>2g(p)|T+8VV9%UToWkgVS%PoJ=U6$TAA5l^RggQpvNdjs@w!jX$2 z<_31R|H9l*9^uKKM&QX(%Wyo|1}&9%{SuUq;>k2aMj1yk%5=TFH727}N6Jst%io~O zC{eu1lnAf<3I7_eP9A^M9)!<Bm%6qO$E%aaeb6Htvlqoh_r#MrUd@v(jaO0I?8)OZ z^m-{VpQbg2SBHRCo_EQbl99o#8nit{H3TI?y~>rLUDeXAc9ij1?8)+Zq8gL)bxpPs z{(WzOIcS<RI>q6zPElrfS;w4e4Y~u_qSQPaY|x2mf5(?aIe$!H-O!8i{TRowQ&P}$ z(XN=fz2>T?@ZN*>h4wPG3-3>#?t=!r&D(>2yS$FkzmXdy@-AOxl@+(OT!9?D<_eo8 zyWyK9xp}nZ9d;e3u*LpR6}>lAT+LY_NuPnm>-sg2fraZ^UE{Un_t5)TX(4N|?Z3zl zr+Xjr#Y1{o?mc0pe^;Tm0`Drb#@hqyN!tNLhTJ{F>!TVSHbqu=CodE`d8T&In6W!x z9i2Mb<j5Zld)a8g;a+hvXE!`F7MG?$_EnO(N$lsp>-9~8p6|(7q*xS9o5^LdN#l!B zJQx+pxZfmD&m(o94pX0`fwvd_6Fn#+Ik`|tPAPOHr$Q&%4xMOlZ+(3H8tWiF>AFme z9)En?X(fC*WE&Ns$JYU$7W>&)O}ML7z>NJFIzw?pf4W-N0X{x{!V+W#c0!Z5YN*}l z<KrJ$jP?v2qNXnm?K$;vHRil+Z&cp4{}`Az6PCkJ)ztBZf4LuhkWVFUm<=O}yB{B~ z(c9b@7Z-uC7MjIAap+u$u)g$q|3;b)_CLW)={7NFdLPf!>p+n3+`ShxK*#ez-^r!$ z{FgeOFSW7=p3n6}@x0UPL93HedB?<5lf&z?pd{(VI-cj+#}S@?Zr;R(;`v{&&Lm^P zpJ+<7DyCiJpKacI>a1NeEwz*}!u=;sU$i#^%g^H9ZC*#}Z{(-#$}n8Np@C@5P+b4v zFkH_!a2-5)UW0+_S7&O;$0E4?nmLN==^|k{Z>E16(OZGHQ6yY{``A*z!#c)6!<^x5 zpz<RzJu>Pm%$io1Dmd~}<7L$~i^11pvg8D{lw5(6xm?CFSX^Odk)yLhNn$)%M!jB< za6PkLz6qluT(_ZTniCuP{{N5Lq2o)W%i(tD_-u)AF;$A<_WTjJ{eOWQ!*M%wJQ3|h zaoax(w?oIzCK&BSaa%!qvu&CwYG+}|LZR8kYR|{@gu4`{LUBxmnFfxZLtmX0p{i7y zF>dnj5{|<DFvM;b#re?jM!m0_xG2t70_R!xPjsF7QaZ)+;O?8+2X%^TPd^E2He9D@ zuxi8PyDs1&@i#w8M)}(ffpL8)utm&-mz}}dp97oOM&B~u)$juhNQ-OB{3SVzk&lqR zercYfZS>vUI&+*RNBRA9v?h6{+tlx=kL2q<_0r?}D;RrQ+#m)caV>@pwGneT5d1jC zqoUmCyL^hcSAItDs%P8P-QDGDu`hS|%(+_YD|j;JsI7Csjh;w|?&zO+bU%R3xmH>< zQ{m{*4u{>~T;xB0Wf<>DO8XnWEz0>g#e=f*5){)d*t1)}ucqR?MJ!|A;JxMa3`?`A z&pQ?WmUyFFE_BK<dV{>rtPsANu9CpJB;sAmz`KIReopd(cLj9b<*ozo!h4gCcvo57 z8C$!~yMj9J3dVTX7xwiL-c<srqtQFnPXF%0t}gKIvZ&b4YrwmnFw>4Eo6!vKYgA*z zj;2vhvCGXn)~sBk241Ro9lP{~%>`ah-oGg;(N^L3Jt-3rZQ!~a@=}~7M{C}Rv35D< z#mzv=^Vg`Yvr+1W&4WD420Wy=IHJew(AD5smdn`ghVrcZ<k8?;&ky5UWyc$AT1*Zy z57Pz9j!W4TyRbl9f->fat<DWxao4eQnk!*!Q0HCChVibl<5N-I*xyn{M`V9fOh=iH ze+$G!e3v48CK2r|m2?UTiym>2A7IzcZ%rVs7qi3G>-cNb|FQUyRbvT}`oG3*9W{)n z8Mtng{gK#)vIcD;Tqj)pH+_GL8K69|_Ps;epCS5C#|itIUISP?L8l7~Kwai--j$%4 z*2nnW$XJb*b}v>}Z8z5HXC6WKSolzfd{Ljn5{oDtNM+rpZbRO3TZlJ&Y_FV}hj&;P z8R;10V_TR&G%RQ;(NoQI4Q!6U_U3^{`a}g3=7)&i(QTdfA-2xcL0jjahS)mau@13y z=IXZ2HrP5dqqa_Vcv0^D6bZJ@B?)DwUN2#LulFO7Xv{|m!1IQOjzzIAz0Zh#GVC`) zZN^4CAbI$nKuvgGBX;KAzCTCkFwM8&BThbHgKah{e-D?Jl24HCjQCA+l&6r7O}BC8 zMr@pbd~pkTI*QxkhS^!8wxZ+{JB>DAV>Wc)AEFI?y><C2`NX5<D2~RD@XIBi@J0HM z@}Q}x+hJEt#7_uA+2MqEvbzqqYic@o7;3MnMxCL${#(%ch!?>BAL9i>b)6Eu{GhJ$ zXr%mXy}Y68IL*rUusue3oZR0g(Of<r^H<(Uv!>f*N8;|}npgA@4Dz?@PVcgnjo@!> zw&7#y0}j)eT2L~|--eE9m0o^uOt2s5<$Zd2V@#LzOrneglRbPR-;>Wp$GzwH&IB6w zEfHPJ;B${-9Sy!d=%;CE|HO(hwtouU(b$WjQyo^-G!-3F6y=kryYRi&+kt;O;fMJP z$FUZC-$~_HNB6nT=T?z-(i~vj2fan00`uGQ5ka^Byxo(1Ej-!v^82m7dX@a$stfP% zMN{<Da=rEFUeS6O+NX9dx4+o#75CMnb@G3>Q|o27T*p4Qe8xI`j+7>OA1o`K-XDsE zicT9uU4JwDAVX+F=MdWP`|m*;4(PODwiVpfJ4wWvcwf^g#A{Z@&rD_Vzljd*Q49Dk za7$c0R4;m^KUW;w=kde%%Paj7>;;Y45+B`XbFe;Uv_Uc(dH&tYKL@2Hk3Z~JhnGMi zaQBSIcN*z;>A{VJ*=>V+{FVM~b~VC>bgf6%$Rs^R{FVMk?PYr3QTh;%zDEtCB~jbo zEB#CKvW<L{9x;^d^}cK_GtF=N_XsawsT#a$#U49O3Je7OX4SMGk(b4uvc|<L%C;R0 z)|yn)Kydkxe8LL)au>c3UQ%4~<a=wSX^0UjQg*ZZ%u|?pg^AC(Pn{qL*GtocIM*JA zFWidzJWi9~o-mW!TA{jBc(d>KPC9+7_&7(lBJc^sVF~yX@n^xGe02A&<YiZ&<=4wl zlXJeYctwi&6`Yq~oYj09K68}CUu9MME>mBlS+ya$K#!`S$nwjzNgn>)yG8@9;)*z> zh!wfsVLM>KD#=yZM(;B^-WM~~#dD?QB{?c9x~nTEhmo$%b$2;)*t(-}IRQq`lOQ{4 zS}CwP4u1LeU3037I45&Y@H5G!oh->y*}~<J`NN*9c#0wAy7G9t<O-IT;G_n{oe8O< zcwyWDuC#)=>e<g1ldIL{<oU97W8wK{869l#I=kd$9G*PuVC`X{8pMAI-f}g|By{EG zKzH&u;{^AWGdY5k;8b1Ld*^0pO>w!iBYA)_SFH`A?IOfX{@&tX>cpAlW4tU|u;*9s zt|I1f34(j#OsoQ}h;FxwV@dH$NE*e&B!O9y;+U$4$tTma$4;jOA3LAM9=njHK1S<P z*P~t$=P0gVN)fjw{zSOB+~edq8nL@zEm<5nRk>Dvrefrn)d>MMPZ4G2D&m^U9|1O| zI8A)0>X`~pmYWd_8pk>OJeRQnqc$MhST0t;rWnVP<CuIDRz~6EShe<aa-4P=>3O8* zkzPQ00qI@(I$x2H!~T77j`$86M{}ywBkFH$B<?SqRPPU`OSRNKQCg4lI(El0Z+VGJ zWp~`w<)ZoJj&x;X&3g!k=^3->3TnT^Y{n_qvi3I?1KZsNby)G>Nx~rC3S-6NxQ*Vf zTv~5!aJ^IFc_E{T^ZM>xTwV6?sK1A8*}FOBsAsk0A5P~n;(AtT_G%oSm#kZ|EmZT2 zkLE-48S_!cbLk)H^Fe24N}z2qxt^7+<6ZA)`4rRbs`aYCX_`M~T9K=HPj3F;Dw=yb zGo-J9H&nwV*9kPYe70XZ4k)^E{A>&InPVNhE<u*nEDvLe^{lw!Tgw#9y`0Z3)<&OF z*U}7@<T2oa@%_9n@;z@9TWsg~Ltd*mMfT)f2M9e%iL9>uiL{tkb7xZol$>AjjPE^+ zBMR3Y(}%)EYrrMe3tUowAF#4o2ikkj+m1EV+pBs3Peflmm~}h&0L{t|#ZAmp#U;U( zh|z5H`dw}|*QGY7N}RaS*QLzkVmVGh>~h+;W5+z8bI!i9wKVHCtm$M|97lTjRGK}7 z2aU?d+AdypbJ>zAZrL-~r%`y5e>fCgz*55{`7w|6JnsZOs`~m^FHRz{LuUrmwPPVM zm#xbJoCGr``+2dCbJX!)OF^yJy96*SUdIkmYRsy8+0gm6DM5XWsgJ0B``+p=-Zu1F zip(H=mb6{6^^=W?Y_O!?N{Tl5^yd3dwYH0u`Ku%s%aU@`EJXSvciAbk{TfG6Zj#Xa zcIfSrEH<$#D=Yu+Z@&rpRpMld*7FO~1lD-8=j}8ev?4FjF{gTq{w-M0cvME7bhya5 z+r(FtJ>)JBYRgQRr`<)aSdRZ^$N|SH9FkX8j66uHL-XoqA`iOH(7Zq)@|Fy3tsx&d z3ByY9Ych}r-K>x)IKm+N74Zn^esl8F$HnYfah~k!m<<qvre#60Q4UrXaW=N;?kmkx zlou=Jx|sGHKM~Z<gWbx?b^gF5*ou<aI8XAXyBl3$`->IJ_yWe~yu%8Qu$*ECuiT$x z(4tW&SGHr*-E;GprsjD-MTi4P_5@&cZ3lC{6X9W2+a8&vG%z;S&n;d-eh=!m7(0Y& zC8K}N2UO#fBfRovgwBn!)yrku+{;z)uH^p*jd)J=FXMZ{jYnzxh24ugxFfVXX(j}m z1fW@%VyR%TSUg8CG;@PvSGtLw(3n(==}#mJVDufXCG4oBLZcaKN8U!zNjA=({5GCF z;1fsRehj;?%jwJyRTX;^#b%e<!8*S2N{4gtT<qn&>RNMNu(b$lu((4ye8OJl>ciJ= zZ#=&D8Q-DFPQ-VLt&tAzLy0bw_{Q6#KSf(eMhTL-q{HwtM%w7mpQyxKSV-yY2kBqZ z;l@}SPsiH$++L_G0R$^!wf(W$2W^E)f?ji8tme{K&EKP@q<@9gB+~QjSlu0{OBg2| zPK?zph}8|C?(H3Y-c;mBhY3>Y$enRtg{`P@WA$F4CtTuGCv;*qrNh5R{+P;8l@)Kr zpw0{MPV@a>B)t+T2OnAvQXc6zq$Z>(NCl);q;W{&kj5kZR`@DB3h5c72}t{qibw~7 zL@6o8tGF^6-^G+tji?5B42hbkjWa4J(zGi(UYJvTi}y5kS$ajz-}bLMv$^T{aiC&2 z<%%^QB?^kV#r+7k>?k<Frn?8E@^zqzOmeCw&~9GMnI(h%K163e_UC4Cb6vs4iTd*< zw$N2mtLV>v$BqcDP1c_mb19Z77LUthnFTKK2VmD0%*m_fS9uA0qy&3BMG+H|og&Yr z_~DJbfq4`$!{Zbzy_Q$}uUGEu0q@eIJ4#OpPKrGLU-nl^Ez)I-OIasxy4#agH0H1^ zuAH$OS(4~d%vtJ&&=!Vo^z=NantNG-Sg&wt9^U;3zwAoT@J)B~N}Z7C_41RT>oc6m zTIQt_0K?B>4UaRM>(Uw(wAKabXJ^lr$|zjRu@ezjHQxOQBv{L>7@3+=B(o!x_a!@b zGeq%0V#BDiO%@szX3u|Y)QRxM%IIhwc5#i<!J~__<JgZN3lxoc*wtQt^{9SWd{5>I zh}BISP;kz1ThB!5J%@MvFEENEgHV-xBn2m#82cqV*7H1el$s@EG0-$M%aH}YgwU1% zOms2+2dLqGBvkcB%)bPjp)#EnbE><t{cM@9>>+b@P&=*HcVwx~BF2&%$*<w~TAI?N zf-dk`>tsug>VKS@z~<&KZ9y)pE#o*gH;Xm7*hD5mI=mLr#!Q3W@mAmw@jI3ViD#L6 zxh0Ejc!~qvRf-c?Hsg8a0)sxlC5U?zHnu}pyyDlua`z(-E8%AdHmMv|#6(~ilaKU> z#u#W!EA&!^E=IUNE4P7#X}95dg6*dqjo+gb%j3m`GR6&Ag!%w1X&nN$jIfPLY!Y)6 z>SeB?Hk}6ai<dEF6u->J=Uvd@r#kftOYace%RS0<vilL19pt{ke#4w(&ChM%9zvfo z`n2FA;YY$d;r;j)+CuXxDogJ6JTg~dO$6_<%6-ZN`KN$-f9?eEkN?J#igIRK4Fd#O z^Qvzp=+SDZ>K=R}Izh4TRHiZ^I}x&w3=Wkzd>nkXiC>3$EbBcvRMnL;m#6jk6*vVV zUmbLomO0`S&m#muaZVh2AJDbjorLzuXYYPwnKwH!mMhUp2`1V7ND^|Ed8gog4Ez)u z%Zn=-v%>bZzE%_2lZ><I`C*db=r8-OfuLy_>4mc)$;{6BkbPteL5CY7BD%i9ljD)+ zRHcCl1{JsILRwH8s<Wjp`RxP!7^481(%Oy_>AS@YHpP;mPLVUTDajeZDO1f~g==>+ z>_<8cIi|d=onS%94$p2-IFwUSPMZSCHYLHw4=GJ&b&Rtb?!7G42CH6v*l)F8gqG4o zQXid&jE==zb-==3ggrw)FP|SyOqhJ}+QXgRp{F)B13nt1r~TTFqTQk|8NK^=r=kB0 z^sk_Q((3cSt&zZAv))BKxS;p>u=4Ku#_V@NZ*A-<oK|LsbCa#yTJQXvfMdUpYP@Ei zd@(nph$H(7LHXO4qjR(sV=!8M5-0cua|eQyyYcyz_WfacdhYq9k*D{br?YR8ey;D> z^YiS)SE$74=MM(mqiFpu$V~e$F31_9q0_%&C2@_&`6x)&b^I9U#a!A)jO?UCwQS89 zUVn;o2&`qiC1hoXhkm8`Zn4kD>0x7DCx+=(f&x+HtB%<<dN%s3vELIGE2U$`Y)_1h zt0j05HnhrPFEmF-N_zc3aGu^KjlyU#RP_nURUMldGTNl`^6tIr+Bwyqfo{QScK1;E zy5+w171vloI3a7U5<oROeeKd!0`xhPSg{$S_c*U-YPP^NRgzW>i<E;j>n5BTgN_ZY z5ZWM4xEOC_10ZS#i6&={3=JFlA*(IroX`sENzNQ7$wM0x>nT6%$%%KoUU4})K$B0a z&?<9*iF_7LfWY#m+X2RcO5$0!1mM~8h-dpyEJTcR_8xW}G_{gk^rY}YX(i%zlF2?$ z>ZK8Qa)o3XfqSCB!9D=G{9XIN9`vf>d&e7pfJS@XtNB{04^={!7u*F=%K&7?IN&f7 zQsbDI$}>x<2~zDS;pBK$dwM)H@bQ{<VSG?ibK`~GZ`FOFULiO-eM~WN&%-jHReEx5 z4o^;;!#!z@ys^TNq9H#RwvdQ!tYX&Y<?)PWq7w8bCD$)Q2hO<xv`p85Q~ZhC*bVx* z^XTcRt5A;n6m-ZL$B7kNeGGBM@=>|x<XFI!D8M=Zzbn%7NG~A$JA9QF@cbX3GrQjk zRs9zANl!CZ&D5y?Sfg=jkfohAo>*7~y(->CZ(%6iF1)qpXT?v|Z|i6}H6}!KZ>nyi zYdXa(3)PhFioQ99eM`WbamK-js~PlF8ZleTDqjZ-5=5l}U$1wmxr~cHtSWny*}$yX zIYBueanh>G%DuNaVe_LF#kIBET!lFBOv~o^o9At|Zf4!E0q7FZ475|a`5EsUOGz3i zaWU{zRWNJ<X|oHjtT9c;AIqJU$;JgCg%q(jZYL=paatzCX_?p&mg~tZYr#zun=coo z6{@1M;h>+~@G}p}4*e|jnI2HSJ0o$`WML`rO-A`%@Uh`Oh?@cHruM6i_^Hgvh-Ely z(_q)O#p0)C*cE<$b7=rE7ETX4VQc0~TjvG-Dz(>jAu1nq`a6-{Bje}{nDWoe156uZ zvEHQ7%!~OIqA_&&bhm`hhh8Mag?%dBLt~U*f`5zhwt73u_oCPML-^Vh0_;JhN13g3 zD9<e~yz*kwbo`aHxiZzvZhJE~+4~Ohy*4$M&ph5XzinPye;e!G1V315+cT?omC?$u zBd{|>*5>)^Vk@8&+2}0$;uX7=kkz$t0#*ipSQ*7*D{C>gbzbuP6Io3*f=?5DH2hX+ zXKqT^4~da-uHHU8hA!>Q49J0v+1EzSGS__hC}aeRuO^)!dj6>g<CQ437x}bThQ`sA zSeto@qkAm@RD9KI$L8Uk%5Fsr-Ox34T8FRcQtQw)O-HThnnokz5PQXmfu)yO;lc5V zXI6=W;~O3qC!V<lGGb$PQS8hSo%4zdAR3*^4}65@;qjKr4oTm~;u)u2Pl)-TeiXx% zzkt6C`eLG1n4y-LmiE~R3a_?LvNQvaZwQ=$MF@Tu_)t~w3h2=AbR=b}xpErTUwH&N z)}q{lDWR%Fl;4K<fKK@9F*|MZ0$#e=Kqziw9aoQI$*#;`vex5Xfzz9;wDqEW{kQD! zEna9#qi(a5@daM!s`z&wVpMy*`z$IqzX4V$#yV0E)3%RFcX)h!wGo}R!L0E&1a37T zOXdq(C7IPA?}U9a;k!~f?9PJ=rxWe#b=l(T?eQ7>u=tk?r_b76z#P95AN7emg?W8H zKzsFGoNl?HRc+|?&S{+vxSHDxspjf%LEoO0bpKB$&cIECJU7%UOLrYaHLPefK<L43 z!BZ09R?yUCM}P2Xc1G}#aGvmz&aLfPsh`Uk5<63<)1wQg7wS;PM?4}A^xcEfYJ&k! zVc77o&8fa1TQ#BtwD&!Vo$Jc-o9H|(omV0q`W8v!ry&N$8<-Oyx;YK^7+lEIn!aou z2i}>k-(NJSE4uk+zBOore~n_Be3F6ll1|5RF`82S^#5S_F{U!EHOTb)Gp^QUYU8<3 ze}<d~39*b$?ckn<Uwlq)H-{<Cu6T!$SKrHY`R<PJO50c8a&*f;OwPipHu*rWwzSU) ztbnA$4lCUr+vM;=IPY4R5>KbPMxXbUD5^|UiFfYi+~!u!gZHw=bw{t}oUHjM<t|=v zpn}gM`xSG&Sw4}w5<Uj4w#&7c?4__#Cvs(tW6TR+&wurp3oEO@s%7|OzA_iC<zX%B zwFYYMG`}b=Ue3m7X#Iy~FQ4H3fw@pL+8=Da)3%4bW0TPr_!rM5*70U@DL=|Ai|`6S zo4Zvk-=JnCIIa(5D~Qj4S!igF30^iPDD&AJ+yQ8C9W3Z`FNX&JCp5cUcY7Z|yXr&a zdouXqg}Hgsi=vu6i~XhN`aoIrL*?DTW3p#-WqUaFp?>M5we*$R`?b_sOZ`Jn+`u50 zxmO&3jzy5%3#_^xJmn#zOIC!c{_`IX50t>)^$gmgbY&!6N7(leVgwv@(Dwv}d%VoQ zk~A;T-DO@{wNTZ`+&$jYn>U^z9iPbpI0gBN$OC4SP@CD2XxTC?$$T;H#_T<DaW2?G zAgJ)wLUurZN^w$5wi|LNZqC4W=oW)*XzYmK^xN4<JBvfw%(0Vdv(f5cpS%mb$LjF1 z3Gk3#OS5ZWVD1UmncS1=`B8bJxCOA0x+lD=KX>Ig8NJ__dp%#|x{lqLy_P3kL`5BS z@~HSOmlNK?gd{b;SdPoPj*rV5#mC`(2!haR$&BY|Bs`5o^VLe3jKRti#(fTzHlaMs zT@0VwRRa0iQy|25<vH2eT}9ZB>cjx=DG*I`GX!paIB+BE3iY`Pi_4AYqkb`hlVDRP zUuPPn&qh7>^X2NqJ$%=$JFD4|IA;f7sApmtOaqa%08hi7E8QVU>%)s7GtxR4vRtu# z2A%i-(T5q{P3`%sW}8FYGI-+e2fb(A$vC8M#>v=U;%zIUDnndvIZGAgABlxBSsPel zJUdWXkFTmz;7cH}Nw825&PV+Z2j-IxN6Ldo4OZomyu3-LaHZ!~CJ-Io7&*6t7+dVV z=v`{j6OyDii^=iAtJY1AZK)7O3y|WkmtV4|{4BfTAe%<C^(ZH8itxnJb2g)WYc$4u zCM*y{<te@%@f6Cn=Fb6N5&WgWT0Zaoh?Zo7AB>e_p9vK!pjq)c4kyFIm@Ke=za0_9 zy5E<^wWWd`NzD~~;qdt|=PPSj+`=-0j%Y9Bsi$7B^C$C34E7!R!n^jE*m$%to^b>V z#jjH-L)zhBeI@!>6&pi|NON>3Ztx6kiNch7u%cVN=Y8zRS9qcoD0J}9i4TC+	($ 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Ν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�>bICO%CtnoYNcS93=t=xryV0 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℘O&P;#N(9#T5HIZdrmK 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856_human_detect.bin b/general/package/fullhan-osdrv-fh8852v100/files/firmware/rtthread_arc_FH8856_human_detect.bin new file mode 100755 index 0000000000000000000000000000000000000000..668cdc43ab0ad349363fc55a6cdd7bfdec6c5940 GIT binary patch literal 498804 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/bgm.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/bgm.ko new file mode 100644 index 0000000000000000000000000000000000000000..934702640b0d4d565498a8547811851bfa81229d GIT binary patch literal 55152 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 R+MZ1}rhfUC3=V0!{{Vhg>Pi3r literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/enc.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/enc.ko new file mode 100644 index 0000000000000000000000000000000000000000..e9e0ee0959b55d04ae8a59c8f0e6213958d28efd GIT binary patch literal 146188 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/hevc.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/hevc.ko new file mode 100644 index 0000000000000000000000000000000000000000..1bb2324b4ccb5b559071b313f12a4475470da710 GIT binary patch literal 450052 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⩔i+MxUcgs-3NmdxF?PXQ;L^<{jTRR*DlFuz+`t8}xdi?EOKeIWDqr75Iq z$qo6sSKmSSZ1#CulL^|f$wP+Xe)f<*=rA{sSI;_!n(gkvCcSyyz)$U5hApe<6ZeSQ zKTo;wHh!5fey4*s>A1I(<}53XElWB*eg?dd_$4*W7w!ljkIsS3xnpqF&3rv){xY9` z7U@5)f(EM1+%1mJUD2lIZSY1Bb9Ns6(Ee{4;d+Nh`!d~w)Enmdekb2;(Kq~#yRKpQ zoA{m{eg8J!6X|E-+-$Ru#rRFvPw%#{_BRAJD4M(0gH7y>@0r|GxdB?f^Sq|YD*mUz zE#uHM1^m7pSo7cHor%71CO#1o@b`o>5a7Ji8}hLocyc12kREHkx4w+bBHc@pJ5tT_ zv5QIM3f`8>I=t>2vMyux9C?2P&J*}Gp9+snr`gBQw+8ZWCog?|a6a|Ur``c?z?<Ai zz0@r_ehNC4&Pn-{zlFS{P0aqGo1E3`+8xu}=EqP5nYR8hbsZ=DdEj6^JXH8^MP9sU z8FozQ^0r*m;mH@Q%Km>STe6L45?oXgvj#oU-hI&FeZY^ShY+kjFwdS8UCpGwvi(te z|I~9!^K;KuHm5gxc8PU|HJN#LdVb$m*@G9n^~^KXwI2R`5%Y;NW7d4lryGO(>aX26 zU=1{)cWZL(-Hon20G$^}r~YcL-bdTi7SlGh>F<b_JZ5B7t<@9P97C^++0z}+tXX43 zYogHxc$a8&39#r^>yFkO*_LR%5$)<;f}!2J_-=^k@}qnkI#zjS@%eC8eF0AwP*+<~ zw7jzNG;!jMqW2?w8(KDR&P}9cv(AX7O&Z}#`uv61JAIHc41fCv#?H{ANt-AZJn>bt z)`+K``A7W9l~_ZdreEb3uMZw*@i$f{y6Ep|423V@NjSQfc!Q(+_%?XqPI9~G&(J~@ zv?V&y`fw0h!k&ls<Hy^2J8hjuJMZSVlHbYLPvJXbu;LV^{%U<S{jH~rQ}k26m!kg$ zUP^lX46Ofx4L<LuZ%@)Dm8rGWlnHx0y%8MlBkl4Dza50@7Y`S#wL$aiUdr4~nc&g$ zqyL}bKX}ud3a1Y^tOv}aDa^N7P1qH&9&Aal765DBO<V(1j?OpYYmICJ%$(91MSs$P zZx!aunqLt2AaRmi#4F7FmpozSnc)E)%r}kOddBQd(gy3<Z1~fg2a)UHk;L_+(XkMJ zo9aVe7H?qh!~V)`uJ_!e=DG0t*sKoZN9rICZF}-vq?ZhVtkBHb+j<Q&6Rgef4z0~f z*G-$!xgq~@(rev{pE-bI_9EDM?fvYD6-D+R$Q(PtU$VI6`;u`bvv5ynmSp6>W_IFv z1UQbrm+3Hh<NLhn@RhzYZ_m-ERNuSGI%nYht7h$Wk=qNqbjN|PD)gH+v_CFK_f-y} z!&^>X<vBFWImEC_k{c_%>=P)c-ST$&+B0<VUug)dtMc9j|9Ni(dAU&2=MF6ROn&g? zpbpMW@*B&kV%zpqamD(jN8BxGYkFmh*HBJoU3*g2ZCsmcC@+5(x&*>gUWfPgyV#d- zX7c=D{ZA!yf6rn(bmn1umo?4!=>492_omqo>#n5*{%-tCzTDuV(?MoW6c?1WN0E)Z z>J~qv{`J(qo%#oU<N81MU{F6k0V~Xn_IYl-pY5;rE!VAN`ltDIwBZigBm4fS?{9eB zrtk7WlBG_`^x|pga=;fdOm>=llC&PE+-_fg%54;VP3A6mlC`JipY!Evc*8BsA?bc3 zXV~mH9q^>JPyR7e&X)t;J>N+*Eu8Jz3vb$w{Ff-R@2Zm?VtI#at1j}|KO!ta*lkgm z+M)1xnX<QBeABRBWx=B)>+nv4_Dx;=JAFs=b|>#r<aeTbxTR9<L6hEwq-g8$cMql$ z(8&?#M0+{WUTxn_{~FrZ;D+fl;6Kf`J)9`_@ZG}qLeXULw}P>MmOk6;VIPAYMaNad zX&q;d+xSGOs-iyj_Z+3vw`S7QXv5TCZ<}(nWt+IFyjxml<;$tue)iwbfR~lB<7!NE z2W3jmE~8hlQ~l8KuwB08W1{26N=>fAd&f5F%~hA5MR#ZCY8V&%Am>EK*ca#KG)-Nx z-m{@k2mb=nRZO;!ImU2vV`Xw5I5chLJH>js<;vM!9Ea*h%G+60>+NjSoV)-&W773F z)8JPHuZFOAztvyj$m6ojqt8x#Rd7F__Ki@!eAOgKGnu?+(9bFF6t7SQdB~gCg?a97 z(b$yiV41Pm{jRcGTC@;;loPMfn$LS|%+KmR(lIA)Kqjfnxup^RG7r8`&d|<;x1c;3 zS-r<Xmtf|J#T>O(Y|o}NN7K}4jq`{;E8-F9fJfYbOeh{vOzOXQ1aI^NJOX`(c*N(K zqdDGAr!C?U(n<7K?8%u2sgrK0Xzx7rDevryHM~hs=Wg~EjfDGs%?t5=E6aQV_u?}S zWupu7?gUO1_tQUQz+yww(!;JTKDPAG{?cvmua~LE&Zf#OHw53OZzasY+K(yU+oJKz z^wqciF5jXx(HuS#pl|$q_MsOM-oS5-2Y$h|@b?Y$Nzy@SY(<yBnB?#smLqN2t-SqC z>Vi%md(UN_XjQb3>U##=i`u)g!kBZEHiPmfmy<bYDJOcJTz=2{M6WX{)qN4Y_EnX? zQK789YH$j@_K99Oqwc$?skIHg0Q6cL(Q6gsCY_Y_J*p$w%&<Wth2{Z#QOMuKfVT?z z3Hq3u=1-<x)5j^uou;46v6A|k$<_PntLRC#194ibiP74T1#ams;(HlS<koZe-jskw zZ>&^*z-_#^!EK!Lo;*L-uBtA0Hw3gyJ6i@U_C$4(A2NCLdhRrTXHcJ4nP=#|zow}s z<=S1fob|5AH#(Gop5z=on{=t*ztq>nIu6g*eE=Js4tu}Ti~b3J%=F-(etZZ24g3rK zOYfq)X7M*9k51uy3!fWRpT&ns#|CsePk`H7OZ#W;@_!1=Rew_cIpFIVe!sn;yr^-5 zznI@retrCuUhh4<s<hBmf;OVZI(_Dc$f7LL&+}W&ZzsQFYWF|mvpN6v^16QJPnt4| zZYgWIm9XyJ;QSVRFYF8I7Cnj<MS~V~Ju$OjC86bK)2!`LU6ZIw{m=dw+4f)XH~orb z?f(gP%>NfUAHrUxUj39t^K)YVm(Rx!BYkbSVuN424*OQ>S#;$Ff0Xah8N2*bgdav` zdWHXk{C}1Idx%Suu9kEPOGp3PqW@0xKTrNHzR$ZBpKvPYI=6C?d`I{mM5lk0|IhPN zyIvyv7~h8pUjTdt_&9KuG6sQ9D31TBrVaiJd@KLL`Peo9dlCFJa0~Fu5qur>O$WBF z4AY;vc9*~6vR!^BValJHwZT7i-Y&m8f_q8#74q}|XZco|fMz&Xoky5(x8O4y%GH0u zc!2kmGaC3~se(TA#)0;hcbs=y<qWhi^66bcT*~>9ACIraPmJQ%j>Z4Q>&7qY2z|XM zugYD-+4ka3GFId}%=waJi{;Sk^?V=JnG~?jy;l&nlD2aOSxPwv!m{zLtTJk$E!7>T z|5qC*^FqeoW?cAwdEPGnB;O0B<jb${f0QuML<$@nhWG88zAK=QH1JW<Dr|Zb=aEkI zvH(BA3-Ha*MfiE=VV6bt8N%0)cL#aWlxsor$5aphEpRJZ(%6gEjuSpexW=|67Jh>8 zqlC8+E*dlGUm!e>zwW1}aIQ&Qw~1pcUn1_h$-Mha{f6FNB`g^G`dxm8^cri8yT*GS z-x~8C+TKf?#(V(Yl$wP-0O6V&0ZkAt{aOm&b$SPTA-<dS4)({uufp}NiSF-yID#!; z-J|^=@Q$~EhiTxMHXWwFqSsA?34fYj3-GV`%jTBas=1~4cZz%&zL!#_=9uYg4`HHd z^+|nH`!%mL=N4e=pn0bGq<N?EG|z-{%{#%GZ<<e<dx94*zcioB{2K%ozF#u&)UCNB zUSX%fC$QF4>q^=O4&(T`1V8G+S24x94{k^1hWE~tUN}Yvbx!(QqV!gje$|BZe>5Te ze~;3yj?&MYkY4-kczf1H={uwJ=?Uozq?i3(V-XzjR%a96X?#Mo@ZC&U5?DSWrUSPC zw*ouBoxoFpQ@~xo-N04A)xa6x9^e|_THr(j?|Tt8k1(XJ=Xl>5-M(AN;_K@Iz84X` znD2JNrU5Sn?gQ3&ej{O<_~tEd-e%w6kMP}0SQ2;#@J`?sVBXfQxWIdWrvj&d_X6(& zhSyZ8f%gL+0ImVn9i~LXjg?Wt4ifgaHtkBw2L|u|5MNBgHwbShOl>+!y5|WyMpzAN z)Mn(DgT0I`G*P{T`U1W*8uF!Vc)#?{^OgrZGmMM)VH9^k!+0F+D_PKrc$swtcTOB| z=+yg%IddQ5gR!%D@ww&Dqv450{y$Lz52CG&w7H2gEcihK?G?U+L*Xn<ABOq0IN*|B z8~vJ2+zx)|*H0gPi*)CdL4MJK`loyi<k`e8O`c(Xq7V5C(Rh4WG(>uhRReLVJ59Xm z2*wIHs0Uc|QU&Y~-w7;wX#ws6?grM_v;vD}GKBRIHXWMLcxhbEC$5(|HBO?ZEb$tz zcET4CuCZE7_)@|H8X~-rF!f~<VZ)?pCQN-AA>9tbOq)bYqLYA*2p6s2PujhNi&jR6 z+ee=L#EFhR0?i=nRHl-~(DY~;dLsS;!quiC>C~np<U2~-^TdgU)?E|Q&b@Ci?yjcJ zIPRWN8>#>QHtr74hB)p}ApP37bHJIQ&j#?R@ig=%UX}#@P3UdgZ-BF)UGz1WbF@wL zrn&J(&>N!euZ^>oo{-+Y&0a<L5zPyCnu`W^nu}_y!JX!_=CYZq>eDZqtGE0HxC`0^ z?!>RnT&<>l@ia46O`9}Vn+g9_=PH8PuZ_DGcq2@Fa0uKP8AxZOSKwP+u#tf-1s);o zNK?4K(6{ylk`X0m>;Tq&K=CPL0m(R$5gYU!$SKH2z>*COoCcmAgC!$&#$X3na-m7z z1uXeUuw*95ffM&7MsAXvBw0{$k(G8Uhk=jLzEBQA&Or`30W3Lg!OT$Z8I$E^U;{(? zSBRG^`9pj$+x6T*fLBjq{LETfw5T7x7w~B6ILf$*A3jg`F~W}nUjkn3`ehZAC}CdW zv&4&^w^5d4gn*|58yTUG_~pPq!I!k^eMxHsX(v&K;m4z-Ihc;hAiU^AYdSP_&YDiR z+JO_8psXLh0cCB7%5vX;vZlcAvRTXOe>rKr6Aeoe?aG}T_D<q^7XLq3&mOrB%_xV` z!~9%+((NZP%(&{~Q>;HE-4mqSfF|Vzep^%QzWKdOd1uc~u|EFs8vZA&$4PSszXMlW zRx1kKkyh$pBc91vRyu82jcA*isk@1CQ{+!3Evp*kS5=i|-Ou@Y3wgGaXCq}G1Y1+5 zTGsjJW0ygDE}%U)0=A}cKs%jFxEEr?G6MsknKLa*<M)?u0G?XFlj!Kbt1QNN5_F?= zub1(i$M{NiklYZ^7GXwiknAaX2;@$}MOX79n*7QeP}ctlXmnZS58i;X?upv<6Y<&K zu#b;ZR-B*V%l#aFhA;Q_SFf1qpJ|+leLZs0l{5VY=6hP-O?(5l0Ji}*0Ji{72X=t} zC;PDJz@5N-#4RFh0DdPO(-7Y|!n%py2)qfn2e=1#7<dGD9`HQi9l$$*7XdE<c7gW* zF9lvIxMQZjm#}?=tsra#VcG-lC+q-WkHMGXef->nKJEtg$nyeu)yGqOn?9Z*>}6on z$CrW60LS}iT^06mUh`}FxQMVc@urV$z-_>$j}EW{Z2H&*+y!j<m;ufJ56vF$qw1MQ zSiFxPn$X9g34P21kCJCUdDX{*e5;Qy0BbBgVD-@h)>ys-tUflh&_3Xkz#7Lk;EChd zMc6CEn?Alu8LtAHKBkCI^^EsXWi|ktKDGe2059(x@1sMQLs-0zeG~dPe?lMM2JDh& zFL~9+QNGPM?k7yJ8OKrJB5-^hj{>WYuM#)0j}5Ie{S(BSK6<3_fK4Ay0iOak<M=Z0 z%fP0OXMoQDFTQBJk15JbU43pJ>tlVCj^$r}dhUGu7vK@{jF1;usg$ChJArFycLU#h z_})WY3*USBP7}TlcslTY;5Og`z@5OOzz*<1VD+~M+y#6Dcq#Bv;KjfL$Pq*Q-$>XA z;!Y6033wRT1NMMNfOi0&0zL)26W9fQ8Te)3J-~Z`&j6nR-UqxN`0!81=cfAm-3k5u z7VywDGyVRl<NeJ8oBk?ph&c6k58vwVe&C?Lz(Ie3)!)6q>hC^a^>;t8`g;Ia{T&6K z*x#eX9VOiK_ZaXoVAJ0dz$buBe?4Fi*!1@l@F`%^-(3^>yLm!?9|T_W7W#Yscz*?( z{%+!XBXR2QM!wbGO~C5!FtGYN0<8Y-09Jo@0;|6+u==|PSpD4#Jh8u{#ElYe`db7p z0-OFG1wIOF`g;uc7_jN@3E&gJroXpL=<nPK{k;bG?%tXH-EHIjT@7sdyN2&I#Hqh) z`Bs0|0js}xVD)zhSpD4ytp08SR)2?q)!z|d^>+vG#QyFjZZF}czx#pr1DpPi0*?Zl z{uY6Yz^1=PfsX>4{wC>f0$Jv-*=tDls6+OU94sAx<PM_)FtYITk=$|2LjFuMzkuH# zl(CF^rI9?#8ed1=Uee4%HZl8n>CRMUpgSYn$TCZ#G6VUT@D;#&;VWv_`O)4?@;PUR zft)-_ymS`_DPKCTK;9<q2ze!|ONVieyiT~<`GKI!u$`u_YLm(``aC1M2Xd9lqF$A? zoVwJm>Ih%c-oSQU5S6)G_@k~jqOaTj9meF9sGXmE1KYVgHYUMd=nbHqPey&8{RYyb z#z^}#(RDpEVRWr#&uDb5W}Zl2Cb~He-JD1xw*Y_kU$u5b<4Zq#39AP-Izcl}f;}YR zMki?INnccEK#S1yO5h*=JCyk~`fB8K@q_v_?<rH?LFzO6RI^7mbMGke;tgi*jqwM< z)%PFK&Va7zm)R!^kD7aCpKRuy*(aO1x55hhda?Qn-pt&6BieP~-=VL4DwBQ%{e6SR zx%J<noj?8m-uQMt#u&*y&-g&nyGk>QvJvYm$uFVq-mvw)#Ku;yCM#RI<(${tT$o}F zY@K2ix9Lt6b{NeaY`sH2RtvFV#BT<++tZ?R_V;q$d%WJZ^c!jjf3F9hBu>9$q|;An ze%&zL1Ct-FnvB{k|Kir8#ujj<mESs(wxeRe)=+OWxL4S9_^zyT3*7s8Fj0@K4&SI3 z9<=#R)MGoS@CLpc@Dm7(TH<t`GZo4zQ&vUa#xI={^?NaC*3uvS+RhvQy#oA;eo8+v z{x=E3UURH%df!BL#+QJbpzThva@^bHKMoDlV{2D$aTl(^_8xQc-eZk}Sm(H<$FWzn z64<R{15*XQ64+FsqM0kaKFgVGiZFD&SLlq!;KL%{Gr&{8&y-BDlC%q+iF1fE-(MgN zH+2HvAUX$Jn%;%X5&HS7qTOxS>&PD0joR16y$iLko^rPq^WN48ZB)5xpT^|7<olB+ zpL{aKK#RupUR#Ry+GHQI#j5dS$7A=orGY-TaUpm1^v0i+!*_sn_C@I%@6TgnlXvZ( z>HPnSUC4~P{49Pui^GNTbdPhZEa!!_mS@YJ!Fw7TsDu6~+9#SC!Hx(!t>;pWTfU## zP1)9p67=+3we{W-deEntBTr1`?G?Tc%T5J)s+*L4^!u7`lezOV+p?atImb&g-(-Vl z^>L?-`T|`r?MB_!F8r8txuoo2fYsK!GrRoMf`YgFjuBMS*r?{+(vPt#lI_zzaEy&{ zVADX|CEe{-9_$9m-={LZAea{l7;E>NjLl(FN1Ze1wcNPX*Zs8R+;jOlj6wHZgxhp< zS557kRJ^_%;8s4}BY)<o?H;Z5@ck;B!!K&G*UN@+o8`F$@f2|NXqCeFhPE^>b$74s zrpvewk=a`Qlry-H{pgMJvB7Sd?3T9Bur#*ETN2^_n+UrvGhF_em0t)Q-FP44pN^$d zd2^!jwj`3?*uBp4(2vum`I-Dv*K-##sXLM6Q`w^LF7ikZkNOk8K-esBCr~^ORVnJn z_v)S@Z!=)Ckd@8C^5E_k+R?x#YCOH}ri6D>&rN@=%4OWbz9hV}m-2q6!`+AT25A>I zQI@-VzLkHfnl@x>n1}rCYse?gTKU9%4aMYHtC&>YcwMuiy0B|Mr)|t5{3e996x=yz zheubG@A1nAJ>7+Du(tV!GSI5d46Mx_y86<5XIuGGnZm+E#=Y_StH2FDB9i<#rwQ7u zekbVn*JEXWnQ!P(bbH#wa~E{1?n8Y43vs3`+{bDEd*EP>8ak2<8+29Mhc9pXp2Rln z)6BD@9O}($X2$WG-W2{67XK+e{xj*`sQ-x^XZ_3<?A9yTcQ!-Y?dBckHr`=gO#OHB zTRL_8r!f6SqMzd9Kbta5c`6&b<hrDHL%BA4LwUxJ?k)W(wuiwy$+`n}cJsD6>V7}t zT+@F8bLN)Hhcthp@4jgMe35wF6Bq5X{snZ_314$K_tzZngdaE#wx{6PuEWOqHurD> z9+jxao}KRv+~btbBIr3Ob-UViQ!3;!^O<X(isssU%{9WeGbi;<nC6X<0aTB<2WI-G zdHu`!#@&@V;Y2hF?VJ|QDYLSh?|px}$rH^!PrDB}ZfR?S<(WG6P1)oXt!RBI7CD1l zrh6fr3XI=JvmDALFLtr#lr@F*ZwfMx%KQOw!rM~Xp)!8Rc&P7Ns%>v4{ZzlsVx!C4 z<ZgJL`O;UJZxx<0b5!`yovP{Ng@-(<b|snDYMb&1XAb{$zj3RT@D34f`XGJ~A195G z#ww6e7#GHZF+xV+8y5UrAfwzKjh$qamH3MRR=c_Pb<ViGhDS!@_NPIAIX`EOOEb^$ z`@{NpV}-kCbq1%wT28yw-ft;AbdsPR?qNQcXy7}l_d~>~526=CYwCkwE33ONAq@?u zEch_EfZv?G)bQa!c-_sF>+w01(9d!k@9Q2+aQ`N8U-u#S-JzuHi4yoI67Mo}CfolM zya@RXejWNLkbN*mOYM{3PnQv1$A8w@kSF$uU*D|wy2-TXgOsUs932JeWP7IaYom0; z2e9E;&|~uV2s3>N_-}SScS_-h4sQrEw#5u%oeudY=a?b?yv8jR2ygB{u7Za1)T=tw z=9?$fk)#f6#OvN2OY?2g`~=w0@Z0&eouRaNr;*`X<Zq0z&+xXQ{7&zU-fe|e>Z<S! zE&0zSY!H8G)!l>J>^Bb<Qj50vZOeI|^~g4K^4t7W30d!&&81Ya!DBrrZMs6f^6<y) z6iSVp%ZmOf|D5*@b!X7ZFT;NV<L0_0j^Dm#=kD|pS;oDO`8zE8sN<!lGRI2?(#K1G zUOZlMPI6zj6Q2au5`Px7*n^+vD>6&`Zo;p0miU*amtb?e1lekXm%`@V;{6Ei)q3!| zQp31iT3q5^Mjo}N3Yn!AnTfkE&!Kx7lZTA_A{-e%f>z&+<pk{%J<b6y4LSTu;y0lN zc_}fs@GbmvA6k3Sw(p#}WZPHu7K_fN)A`6}4g6y&I6&qN<gH1LTe^*S16Kpz9)sBf zm);wL<9?29$_ngFqq1s9t8#87z4|1-d`hGGf<8v^sxJ<!J_E<=VjT(ARdcUXvTu$# z&UgfE-#(AKB=f!<_-dX5PnioYu7rpDHvi`#^CpoACuiMe-D^?1%)LlE%Q+|INCs8C z3-FO^zH9H;<*#9kQp9h2-)!arJ{Qsj-;sY7?(|G59`-fvtUHxj=dgbP{j0YQ`*q%7 z{4gBGri(YE;F*%A8m#4w;`{fJ#<KK2rkm`ftZvfuS%p@uC92Ev+{(81Io=e?tRlVr z=FlFm$IJUm@iRXU-*(HLJbR10AMXd_Uy)53G+KEsm`kc>dF4LJaHyk`UpMt-oI-0K zzY6oO`oe)Sa1gG#6OQVh?GYdNI7w30Ur^Q}&a;yrwSqrh;R*L3k$fY%vvbT7#-Rq> zX+8^&YTFdPk<9~mg=Bfc;(n8De7j(;k`%9#d=F2nQyEI9GA#5jx_45Q;XXw)Zt{;8 z#L-@EQ!=j11?I0B7oQiwU3J>j6Zx93a$%XeKbFeC6CB!`4&S5V9h`rvrX02X{D?mF zt*``XRNt2#yuY0I!;R$x{%sl`xxXxYKjr+SguP;rE+zlgk-cJ~et8A|<L#O+Dq~^P z=9&n$r-yyed{g|}qj-JGrs(<@EE^)jrxdSt-4KfxTm{b5MiX!PVBmMg(ywM;7mwGR z<bL{C{`eeKe!(ph;?0=y27zo6UpuDIwgruM>aG>@zV2j5JHhz;UAT7*cx;yP`=c?+ zhj<olH2#^s@J;G3UBZ1)?vo0K8bd=H8b5s-TsFRGeOd50E^j8DJI9Q54QZK6L3-?x zpeyEt+V;oi`l)P-`Z>`zrQum7+^kQ(gC8{UAFU_Czvx->L3Au1Ov0VPt=eYR8RKVD zWA{7J*r-jW{FkG-WmC4wQ`y{it<+GiWI6V5kE%T7m;I^YW!I~DFfm+qXbRW5taVfT zSZTsCi|k?hDpwM|M!aqo{1ktACO-Ee=>YmGoy5ylZv}kN#98Tw{iUQgu+m||638qw zE_0J>9mb!wnRu1kLm6W*--=g0g;kSRZPK^;^%D9M!NQB$AAA#joN!Zy{wD}CIFLP~ z(#F>`$+OTwyYOuCDU7{aoju2`yfe1`X<nH$`p)I3%gK+0HO11tgLv9GMvv;B=)vSy zzn-KH!SQi6G-1+dAE4Q>4j%h5zgPIh`Iz?3?CYEDEagBC>=*<8PnuW9@}Uo2D;>W3 zsyaKsqt+??SH0q2W<A@JWjxmnmF?AcmjgK@x*H<g)^Jl@_n_52;m_m|toa{@HUAB) zy7eu-u5#1{+6X^qENEjeCj9T3P`AmSvi2aWMDG?wd4!Lwxo;i$NtG<7c_utKxzMk# z=7eyfwcf!uug2#cjDcwSSX04o<<5uZ^zn{D;H%h66#SEfp8~#|Jc~2ZD=iCThQ;vi z#B&?UQ>>9wxBPHZnR+PaX7nPPf3W9<O`Ii;_bKrpcg5c7R@Pj-5u5Rc{q6XGR5`c2 z)lCvs6}}}N`5vY%tnJU-a^1$V>fnvNA6P|G_Ry(4U)|_Szftpn4d|4@v&Qor#w|nJ ztFdpKiVe{m>>97xKwCqc+R^`-xrMUQ>Z~M5Khtvx$hC}DHE&o>MfL#Jo>O+98jFCg zBHm*BPgk>c2(KqPLYeR-{wMHBeRh7Rw@EsMr;MNCg~-_&<KC;ow;poB3H7~?xu7&= zj)uN0$KlW?T?p5-uP@8zWbHLu{D!G|<0VlpWSGa?Te4>jme^aC?u?Zu|3=ya=q{&p zZg&Oauq@c$9H6boo5p=sj{+Zy!SY8`Bux1i!80|dO*`k&2CcIOHol86+hhJLtGt{4 z(wE)Jf5Tff7eXJNVPA~zCHx1qOHK>@35Id<^V@|FvmS4|e~@>xd$k@ka_{m8{z$2N z^Z5hlOb1E@_ECeg21=XorKrAZtv7A*qP_^n!mYy924s$490GcP-(@f2EpFm84hhD{ zaR!6*ol&^PL;2?c$HzkVWwPuQ+St3Ruf>k_?BAG6jIZb!eO6tXvK0Pj;#05F|1T4+ zcT*?gWt8w9`d>7C$G2P;=?cB{n|)YfR=EE%eLYNi`3g~*1o~?m`WMc6irf9>E4)(E ztbD2Anxu3O=iumz<P%++HCgnpH4`2+wk}UcPEkFtkv$_hB?At{bK>%e_7~zU0nf>U z)BbRNXzfUl?_$x%JMS;|-Yp*To{)#|eSq(#oSW2ob^tqay=UDFEWF-ETqED<oZCFF zC*(caw=d#b_;1T?NLB%h&ZqOOJfg*PZbNem@Mx4L%YWt57!k+%z?kuWZxj!2RXOcO z#!<RZcl4eLd+v6PW89aiVEHpOej{6;3Dx@*%019I;(u&9@-FKT_f4DAj179D_6&6? zeJcHF{C+;{e?)0`pKuTH0UrQQN!o#qy)I)-t!OV9@|x}b)0C?;{gkbDR!qH1fy22U z;<^v`u2}qX;Lsm?7_WA!Z+}jCdx(qsS?+ybI4+M8*Ll&%IsSF$0muDhTAA=I^AD4@ z_iElKAU?&qrnl}3SHhdF#@8wR8GvTxPxK?C(|GOWzjRZznH^R5<xC{I2JMg+M(uOd zzMCo<i$2Qz1NtJos=v!G8mSTvj^91vA8TP=<Hz6xIF*mk=Z8l87mkeJ>zDQ3OO^+$ ze96w&mOc6?KMS?Mn{C42oehb6X^>xSDqk9C$(O2I2TGf-#*g_mh0@@hLP>iAgWm%k z55q6zcRp<2DDbfuTm;Uto{jT^`?-%Xm@IbOUlsDsbMcN&vHeJD#P2~CJV@K~wQfoD zB6=7&KVK?L9Y9`LSsCmZDBUL9IuB!e$J~!}FQy&y2oHI2SiZuO(4=Jcke1xa67dso zBDxD`&U=`-wX!6-Q~HLCyW8TOOhbR~CB4Q`<0YObyr-PO!Z1FM^#(0_3g!*I9pG>H zuWA<^J-~mBlfIL08f^SS$~d4g;T>ho$(p(MZ>6s7FSTyl4u2`|y<Y9RnsoYq2meLq zYLDT$g5$Jy7irWM)|BR{)Yk*Pi!JaC@RnpP5WNhr79el53y(TiTtS@5l)qfnvoeC^ zOI&acSpK$^M)2Fn(+y4s!L{T|=+iH79wfiK;-5DYHcFjFhc?h!D5<XMc>~+*w+$3V zh&Mi8%~_-NYr*@3@I>Lq&Pom&_8;L*Zwp?%5?|Z$&u!YE`7+OvFFW_?Putcr8VBXm zTySTRS3bI<`^xeG*n=-0m9vQd*~~)$Km00wOXLIJl&QVHd{xWuq6w2veEDNM5c!qn zjmsoH3S03RRE2NFD)|n=SL2v}arsKtJJk;NrTaM_?WaEZ%)g#<akY_m8-p{N`8pTB z(zZ^$nKS$=!vFd<VYPhAx3~B}4}FT`e<*W27^@^c&z-=}I($QO6*!q0EDdFj_zpBV zgnV+g^HAmN+wjSH@u7<Rtj)hJOk+(#pV;M=&UPQFIDEfKoMkKTkpJhkM*<qtSU=Ny zymXd4(nmQ>@G9Oxc&7JAX(RnaDk-16gtgrn2;x4>_@A9YSWw46>E&XwJX!wV)0?!f zK%bf?AHI&2-#X&|-|*Ql8hMv!1f6-@SHFDpXYpAQ_tXDd0qy<g^vPcn%?%fy{PM+b z{PIuq$?s+~kF0VVX{O^-JK%TV@E_r~zsNs-9-0s5WZ>W9+sKuNg?nUyX7Qjr=M|)B zB~7b%-*wDIt#wQZ-b^GNdb_pEuO#)vX@4!{8vp$dGmgK=fB!G?+po5XPyPkvt6g_d zmhq+kR@xBvr7vFd9D6LujPj+wgEstU^X(n(sY3p)_2lQh5AYA*%e)W3_cKGHiGK0k zTe#P2wMzyuyi<5v`JtgN;wSqVhrLO_myvgjZ}a)=$rxXqUsqN&@`eC3mZQAYHg9@7 zJLKOOE9)k{PZDm*mY-O?GjNJ9WZ?&Q<Cg*2Dh=P|c-p@_#F=9kXG`K?NAPR0jQopO zLri|H1%15dkhI2aLnNnapKJ7OIqu}>zGK{vz0OmNAA9*I>*1$5uEZ~W4}R>gvTpaU zaBhEHKlYsa)?G$irg*!5=>$LamlI~QcK)h<?6a()u6Xiw;1xRzGoQt0-C6j52aluR zrj>LSygF%pIM5gE$M?GCAHEOT+XzqaonTF~m}~oc?$><u=aMI!yL!jLs=NAUXP-$R zqiDYHKFJp9*t*CX+I~6sF>gmyfhT+_w(9*93}dia2<OTw$})1f@FaP>^|7Jy&3`sj ze$Quy%4VHhi(U9S?#P?*dGGuU<#+!r@vKo=NAuhx8X_M3#;Gaz2#>!TqPe;>MjM)& zDtCY8Yo({G=f>7D`M_8BQ-trwGo`63O#2*ZkCtww?eV?KYGeiNUHTnlo6Maa{b!A& zt(+a0{Qabf$LERLNSe1(mSifEPV&^<(42u+@hv<bnoy_eE5`bBkZ+~?bJE3Sy&;7& z_hy3Q_`3z1$(~j_MGK6RAD3|g{TaL!IjHI@+=cs9-Zv0`oCdvoiTdL@9=(5|y|A5w z4*Q1vP=+7Yd<^zq@~<fUruO#=Gx`M4K^RvI;^Z$z`)B1>oJkkocL#4<BO7KpyVkiA zeUt7pcqi7>tGxPdbBf%Z9vs8FbfMaV$M@eqPu~0^c$jGSsN}@{hnP3FNZ;Nrot$&^ z4(eW3(YkYt_fX6@>TQ%!e7P7{ZO}U@23C1GcPbKggmTBi;g6DEu}OKx$fSIOr#{)K z)JYySX?2!+ki12Hq7O4KEXVi?4|#V;Z{u~yuWLA$fBrg5nz3~_6|KKdQGZ-M6P;uz z%e1E_DmURAu7rC~bjZ*ZeQmylyw&JAk&S)%Ty0AuJJ3$GL-OoTiPu~(WoZp}INR1d zbdQd|Nu+mC`pB<6se=z9mv^1?PLz@Bo#)(=-kVt-rE&G11#dR3h^2A=#x1QRjozq9 zQjU10<UYM~p>jq^+h6?Ai;{!ZkY+V$7b(md@2l1{$sMM>>-Y|Fx~wAIu==!~{~Bkl zCq^$KA9(EXg0mX&lz{F@bA<fybXs@p^!U2-UgmER-%KGbA7YM-(~|SijsEWvAKwcF z?|Aix`@&%Uur~5$vH$TjJd5{ewkDI_#o$%rP{0q~eV+<#NTy`&e@Z@44_^(B^>|ao z`C!1`W|!R36UcoUGx?qG_3#-DZZ=bITwfB57i;ZDGCz9p6!8xGF1;P4^<C?c-j6y# zoi9+1r+D6W(LTb}J5n(pDkn+v5@}vmnhS|HZ$}l84Kz+sc^acvNc$@3&XE3iamcse zf$_D#ywQ?k{i}`m=0mjG?4{lTulZ<<_I9wB`g!}P9nn5&$FH%E+CdwinRKLdDRsy7 zMhW!r`7XDVXMfrOP0xm=gEgD}>><xiOY&`~AN_#zqtHudD=;#W=<hdqN9R&#bPjSx z7cz+6(Ye^W-ETO;p01ny8M4P@&X~1_@1TAAY0Ey^a)5R%rVnwP3CH4t8gGYmZpOuX zHvI_q6iw<+7x}u$-%0#StQ!+$fbhH}<XIO}-^csUz8LI7J_HR!d*>F$u#GYNG5OV& z{rnE7OxhFh^2kp4{(t=KvXdPSY&AYJa|!$R@VqqffuXW=$2D_@${(9PRDR{60(ua1 z<sZhD54p$a8?jBT>p^dxL6;orek3nR_cQdmx*zdp=5G?Yw%ypwD6hsR)K`w6uN-<^ zedYgROuMM7eKT?-x-0nlv&gH@vgRGeKJq!vjZSy$gf>n|raSC+z!y`)hy5z=uwM;) zrelj=uka|1;%kYYM0_3L?6J%8J*;<W8n73`PV32+$&;Lr$0CnS9{4vl8`4SLRC$GT z|492x*+D%M%2)kCyJGdn+xHKQjrK`j`b4NVOH4y=%X{^*RrsCxArI8sfyvAQ<VoI3 zvz8Umg*+-<sPOuJ#zH!M(bsOiyBM!dVEIx0zHL1z8Egf-QhaR7!dYI@-pHGtZi&6e z>5iAc+tC=_=wDTF0^XuD0p5t0jg9aoTqPsCeVsLM3}><Qn0T`my%uMla2BN-!x?E! z*<(11m6amiv<;k}UXA?2+gkoi#&4!G7~GYZiB4wYTXy-fBkW3n6BoZ9&Y;)zc)foJ ze4<+{Z##6@J9Ihz`M^sJHpr7B8{`^vLBePEmG%B&+xp%g?plKVg2g?9M*{g-G*}0X zvsQm^5<J|jZFPr+ygR<Wshq*a)5hPR%D`vvlQy!Jp>^dI?TT(izoOeae+k{DX8+sh z79Gu#ul|a3Yf<(uqg&PgtI)0RAX*j8o`>$&(CmKac)%Y-yD8qb5Wm=VX~Z8G2c1m> zYcKe^3%<}8!<X_%7yJXlg}3`JU&1-9^}PhLg3Wq)2X80!Kz}L5KA9Q${%q*PE*<*5 z?pe&<!5VQ=YsAVDZ@l@*;jEwVvOYGs?V4w5@0<(6Ikpa1ZFqAu2jhLIi}l6Kudj(0 zjhOj$Yw3A#p3MB-`22duzt8-VZ2AB9{Oar!&5GyqCL?3hUE~}gJ>m~9L|*{^XuyuQ zq1n7o)K~f`_>Hew8S=-^l1>4~&x&3GeqT(kcp3Pf82k!wT&HvfIIcr_6*&GzTaL5T z@IBUWjnr9`<jf?vYa=eMuaPV&o!KaH;+xX#-yO*iHGEHdi(A=#;ZXVRtMOL^O_{l_ zxxJh>T~<+E{9NpAV99ysp3!gj7ot-ZeVKEyKcqf$)_~t#&KfumZ+R$KW8-HHRira# z0i*PDkn^tUc?He_3WYBCUN3x4=h9YmK5yC=@3Um&xEz%N*7=P|d-s**y=dlIdRs6T zWk0I@ZXv?UgWy8xwHGsUbqa5Eu=YODfQ+Fz%G^wJF)wUn2F=qoz1#c?u3X~Jo{l`+ z#Q!$tBX7%1<GY=3y%}icq2U{sF&_=zIKtYcar+_od4TrX`29WkGx%wmdB%Ljr-Qfc z9dGjN#@IUcJnL9(Y#n3Gsj|X#EH(R)aQ%<c1nU^_lZYQ*$8IdG7=EDq+|SO|z1s1J zAFTbc^cLxD(#O|+i*kc?EJ`=Fj>XDW-2o4cm6amiv`y>SFT%xt1IGs$f6Y7LrN`r3 z>WFL?M*P7!;07IGp?9#f`C{x9co)uc248cQ_g|<ZPTP-QC-d`Y`?Kh+MB8zliROyV z(=<=89ZGKg-{Jl&0X?yv1#}^sqK)WAL~{x=G<Glf-ha<M_l%w88ynReZO<Y{_pxq> zCdnrm)IonBI+JZ`t@Y4r>;t&V73>+M&p2}B{iM<Sy}2S?3H6q$W?>(n@hVSco-G~7 zJnP{rKHy76KcaTZ9&M~W#+Hfp1a<}e$me}w8v<LVJbPivcF<QfVNWGHCfP5&1KsIR zXK2H;F;(zKS_=LS;ANz(<@_+|NcVSBg}jdnZ>;&rhRlX4`<?5N?XU|%*Tp@!ifopC z|HAd<;|~s1o#6KZzms#3*8`pt`P8J&x1#T`I6qY0wVmsIeShG*_2qSZPe(u5%{u5^ zG8BYwA}mGxPX1S051(S6;tlh?lyWV8X?~9C;J2DzKfg8n*794&Z#lme{8sYI@w=O! zY^u_X(JH>%_-4#1>X+L?{h5bb_wZli#$80h!4vH~SU2Ps`5onVgnZaLwIz$^+EW$3 z&igVKqIbQNG}i`cPDu`sZItAv;D2OOHF{|Q`HS;LC)7C~0X}$M!7pB@H?qfZ{y68! zx=RnfeZGTz&zWf7WA;4ZIyLNX;+!_^j`%J8BmPK^|HI+hu~TQv4-S>jULNlIla9Na zb6V`KLY}U5P5tejvkM&U2-Y=t7H8_qnrpfqwClR=Z!~kjaY8#F1M9qV3bqBv=M~O$ z(aGIZxrhH+YrhEn;O871-rD>vc<)luDm+PeA8W;OVBMjUtxkOHlf4T%#pE&3AAQl; z!eyMrb;CCnkx%=TtVP~-_{H3T;9ZNr=BKMrit7S~Njs0US}T+6DF-jt-HZ??n+P|0 z(L~3FU|qYLFvY8lA9l|EmEARX7~9@&>ikLg>8HF^v_Z6z%@m$sPyTfBd6#X<jg@SA z;EC15+qHtVrYx)EC@)CIJ=SE4!f&c%oxvyID^FV)_S~{l!d4-!Z`N8E=T|F%S5U5W zPzm~H+P{u)mG>virMRBZ$%$6B`>LBas4M$2BUQ;eHrPR*X1Y(1|8wZup634-)sAd# z!xQRTJ}M8LUyvqGxZ;6>v`SO$xRLE#h(nzL>x@~tL5-nl+gifo`hs=P<wooQ#^Qm8 zVsMp(ZtBNp|7jJp7x9;7Xr$eX;C^(98F)^be6r&Z&P-W0^CvC`tiEbjU?;11BL_$Z zcn`Fsw6d2rdFfwZA8lZB-{f)XmW*J+B_~Nw`$@^iwDk;cpTzZGJLvCDYXtqxh`%?@ zTE?9vYc{rq*ju=S&y=n!9qLx5I2JNK?;Cd(N^$wm%#)jG=NigcOgTN2t2?9vkxffn z=NHT$(r8Y}zR`}-Oq@q+B=b;SfDh<_`H@`Yj8t)MQ<Zf_S_dyF*n~A}e1(s=T&a1; zyGnunQgKFysc$oPl<!9PlEEGNs^k}=JmPKAYbuTOSO#~N<5l7`Yvp+VhceE=sWnvI zQylT@tzp);m6g5pbAUB5dBp&0YyrI!=gArO+d99}Jj&`^*>RJyKZ(oT2CsjNJii8f z$tJhcVxD5l&?VemNqLdIU>v`OSDiqHlAqRz^uU^s{IB#gPS?`cu1k&UiD_RY5Bwqe z2CjoK5PuRr0^US>#D~P22Id#U4=RJuc6<zWkyrS(V|07VZ&2Qg^rfEi;<(;PJEY^> zBfRLGR(KJf!He1x-?tciV&l_}{dr)=GbVpT>(cK_AIEu6aK8>)U+ocUUET+p`%smY zbxTV>@sQv5;6wi2k?sEPUAn%!^V$tn!WA-0mEO5yU2IIT|F-g<M&CJz9@*Gw$u{!b zy|wIWRsP4WU0?3i9-4fAz;~)8wA&>;YtgOj`)+N9SGKp1X7q}Bc*CcC-H+kCw-hfQ z8clK^TW3q9AOFv@|Fn?tGB%`(PiqhPUf$Qje>^&s&E96O{jnwG$)yK8e7BUuhxT`3 zcT63Voa_CLn4H{DydGM<9vS_5_D5TM>F25@q^TuM4QZ+g&ymKS5T7DGNqmCvB>oX} z$4at^+NZuqXK}D`ns4?V!i{Vz;Hk}*(09{*+Fhir&(iK9?S2*=;r9;y3hgfb3hiF~ zE4EwhoY?ln^ntN`)8b1W@<X{Mvg@XQ;r=^>HxeK2ze9KvaJc^t;bGvA4}|ata7f1? zyaPDozae~vbz=?lV(Z*XyuQq%!Jh3+S~I}k9sF-`MQ68F-odx*vg-+-!?)ygLmw&f z$Kkz{DVt!$o3*Gdpx6G2%GO$!5q~EB_4cGUFuz2vdQ;<dXm&Spc;JJgk94E-C*&Jp zf4)VS_WhE_UzxiB8%pi_!#J&HoJ%}&hCB+Bydj?S3UFw@F*3H-|0~K-JK1X_X9av6 zn}M*OAz!!fBc?P_n5hHZ(&-&FwVpLB*?L7Knc>|bY$&JASW>>8HLb`TEMzu%NBF;= z-{QGpTlQ_K_YVTAJ(JMKUd)=?^(cOo`B{|t-!A#C|5V*~{XaeZUH=Queb?_me>Nq} zn@IE6e_d86UB>-?r-Qq4mke^o*HE6^HdyLDq`QKwyVqd1%DytuA^Bk>I5$!~2PkKM z`*;0)lxve`6SS7%ETiEY@P{kOFW!tE+~RyB**zHX=Ma}`Y16@3(~!}0Cw!W}Es^w= zT!u{RtoM=`-rt3f>}Nk^K_^^?uN+{1HOjAOb5HPd1^?(Qc#-vK_yTkU51B-IwaIe( z%0=e)wCk3XAOD8#jchwri%xd$u8p4TAMn>zI!e8|zbk#D)gP8IO1a7}ea_d0sgrV# z!mrG@9KB*%pxc?`6g(3qdX}uHv$3=zI=`vHnNRx>(rUbvPVLk<?b{uWjp`O1p;Lac z>q*9k-wxIm@x#B<KA*hOv)O6rm$nYuwzrSAE!m9ieR{oT6}`&-)IflT+WdO&z>xue zlwazifdC)1^ow;M#D&*a?tOAY>pXt<p+^x;o`~T@_?S#TCzB^{fBMv9>N9u{ZR@N_ zcrg8~aUSptoeNiWqTlE*I9H1H(em*$W}`n0UFAZ#SN&#Olikc=8+%bJ{|Nichl6zp z*}wTqgs+I;eSFIvxXsxCFXo*k-cof4TP&M!Xe_gcyDpq@CO8WetqskE)|4(=D9s|> zUi2lB-E~&g1-$gRhy6av*7+1X{d*s~cEi}ZmpaM(<*txqJ?xcBvR7_l-UswVo3*yV zciPRpNhfN<;w){`IV*3U1?@lwlfur^v;!Oa_Pyw9RIagAhMo(l_J_Bt?06f$OWKdo zhF<DjN;{QDXJW|nr%kxvAROI~+AH1p#CCoMUL&2W(XkF*G8E84gY(EaHv6@iN5Idr z;M_>^eOw2-iux6|1-z|!=fi$~J7Yv2*AlKX<<$>9?5_i#DV<$<<96`*ONjp^cJQfR zU<WU~rCE1j^6f?HmW~I-Q9EnIIeT5fFLUov_z*7F(dUimPz}5mcqj(vfhA{}c<r6O z_9N|`!oD)sqP<fHkMEtrGPQTo9!hnoj3hXd+!E3VXU)-_+Le?iy(M=6lJ8<H)Sm{v zv6BzhM9wObIv38-w*&M|^I-vTU03K%%JR}})}kiSTYAd9jc&qilucPDb0Dr$?*@+R z)N7$Ji!hCu*~jZ_HfSs1ak)4J9N#CWpbInhgWxp5+)}<zQm_6iz51&%OnLGAKP25j z`h2AQVSnhi;F-`svUdo*-hy%hIXJbbQ2GpM($o{*U$g*AuK0Pna;1-tUmAK{+q1!E zUv>J`D$5$PgO7MlU<04kS`qr(a&p7|b<j<?HyK~QwI98Py?<QBvme~hgzm6C(Vs3a z0B^wM7ot5hvR3kixf`p(eOFjc1NYm_o*P~g+53cX+S8|rH#{@6vmJ+5KsQ@+vpn(E z7Sb)j$9S8yKEU~o{`C<Jhh>Rg*QI2`62h{@%*SBK{>LdpwBGNm_caIB@E`gqNoNM{ zKF2QeFTq`i)37|vm(ZRdge~f~toM5<%9I=u?%l$;04JZ==%1+D=&Ky@dvjm<dibsl z9-1xIj6kn?Q{d04HoX;H<yJrCYz=sIVCTSoTRK+lkMzF1XbRpR<fGle|1*qlu$~w_ zG2?3Yg}T{h@ayElHvKmEc%HTz{2b#uv@Z+e$L-5PcnRr4`?3($IgtylXnR>UW~Llt zM`2~qp;D&SdC}EX^btORJ=uD{$WP&E!Z#2e>JP$lHCNWg+7-^1@pg)Sl=pn{qK9rv z^DUmCZ?!=>0^wyx<~yt}hhO)u!j8;WgS!el;F<r{y9zsK`!kci8u(`j&xXQwYi+l3 z<LiBcwf)q`if3P(vr2qnwb$mX_tUxce!uLaGIs<vPtz$&bR4G@$xs=>3_dmQdt$Kg zqk5bMxAghT_|0`oAH$YR^dZ})nT*HcBD!j4J$k_P{-RjkiMZ5WMEEpyY3!zOcS5#R z4zlN2@aiNa$0l@kESu>h`p4$Al)IWbMyaDn{)6fD{$(0p@NaYti@>eMeI4-{n>qJz zS1wasmanvG(x$jS#~ot!Ayc)#u1i82izruT3)-WZ@A&>n_;&2^_Wm-Q3*W+f9OuHf z@UDAJiC8^x8WjEgO*Bu9Pa65&5MQ+NE_$C(K2kpdT~I%G8FrJ%rL0-w>sbOmmDtI; zncabplW`ve@1!4z+mNr>A521bq<w#|Uhw|}Hh8-8ZQz%H-$8l<j{<8R8~6aQ=CWYf z@2M=w(lw6T$U2+Uyj7fhhQ#a9d%dluoQsf`$aiy;wgDMUV<)}f@gD9Uqt~!=$ZGvI z_xZN_&jafo-wQ_wM~0DHbHA0RUVg|hy2qzGd^UIY?r#|=RdaW5Gv}`j+}%?>?}_SJ z8`b-+2woGx?~Y)l6(2UfKsHA4H%9S85iC1>gAb(_uNT~V^>%;W`$9TQ=3KioN{>$2 zHa>c!UsgTFM~|t~_!C(~8H;0OERB_MOH_|3!}!!#6s5V9_(AMs&<_Uf5wA9~&auuA zkHYUD_kspG!+YX?{yKDLW&6s|RkDxq5dYR#nmMa+?85(;=&6Q%fjwuiY+q9-+fzAD zylA~YeD!*NsCB*XY(VA|KG_#H=JC~&ca!+1V*LpG3bi*3i%;KLSxg<h+l8}RE3EbH z((%a8gsD%ka2JP#I|Iw6xR3seC$k?&vd%VZFCo82wR0Y>Qo2F#kF1nH#<3fiOX6M9 zp=!*;+ndQN-;0g>rwy!)%PN=iU+V=jeY?#Vhvyd|@70*c^)fmWm%M4(q<$yTAx*@` zAWJ(R*c$Te#6=GT{Zt!7C(3JRWFBz5kMcjDc<GdluM^=#Vd|&K5FFY!gl%MR!JYDl z{CK<Z-xlaF;$h-DnK=*pJ=Z)O*kXj|FJT$N&6kLeukV44dKP^mXMD~zvQtO*mh+m^ zeQq=S2-$xNVcfUiEpWn<@Ns;?x~0Dke8%(z>t;j0#{L%h%fx0P?1z!pm6m<+82twP znex!z!Rv0SH1{#a)J55qQ?zX&UIfF70^P6hVmsO^hIgU`6L${Y9Qr7kTK!SF&N-o7 z#R<x04woAH+{!m5;6S{&p+B_6R6p#j_RYi5dC;(bCw*33viH#a8?%qe^bgVR@J?qt z=ZA4!{7TY=cJ1LFDTQ4%>qRqnO<JducK&r%`Fiv~*(&BYYh#)|%I>@ge61s|&bwtZ zALyak1H6+wYJ<kQ-}=gny5Gqi&at-iXTI`cE%{}?9*iMp@D8@9o%|^OnYit`gMI2b zXBqTiF?GI)I&|(5=69dw9?9qWGeckG$Nz^uCtLIQy*7R8&W00f$ERqs?!I)!!tNt1 zeh;c<?uN4NKy_6YXs>iPAF0fw?)dr4YTBcH;_CE<@@@Y+lv9ll#n&4PGY&t5u5^~D zx&B_tl$_4J5oDRrrsZ9PO~h>#VZRW!;9K`=)BNK0O*%(@y?e9BBf-5{$(S0qI2~ls znTTH%IS1Cdr@2KNkqL%)H)6<t0$O7|s04Qpob7%i@x@uLorK>d9jmF0bj7ccej577 zH*0Nx_pxTGtl?+5=SLYkXJIcu-ZXjtEA=<=|NjLqDvQB|58hPy0O1<vk8nrm`d+t@ zbDXAil#MO*)I9hS4qJ$S59!no+BkN%F@9dBI|jOctox0k)z6bYP9vfXl_g#*TQ7~v zM(OMbQ~K|aKEA)!IQ}d2Dj9BscIe(>e7~J-rr+4zWVyS2AAJ@srHd-2v16e9qvR=` zPka~YkVl0VlV*O=Djy)-e$wqDU6%Jzi;PDW8Ms&%j*GF~*S=&gY4?!UCGC-7Xy<+x zv~1>o{wR6d_;H6Li!OH`@D%C`<Xzh2aL4Tg`HoZ0G0J(Ka*kR<eta%w)0%JS&bR|& zRlB9xjH&K}Y-9{KF?WY%4OPuUM<Lq=_{VPDUF?N_#q}xnBy8fCFIwwlAM+t_x+1~8 zCV?MO#x0W>s``8Mn+Yc^A0hz{`UiB9HarQx6=S@pIemR#-wY4m2Ayr^xBk226D^5$ zzE0ZgEbyc|RLJqui$kpmzU}Bc#dpFX+!<;ua-M9`wZ+ou+oYrXR`q>4XS({9ZbrCO z-!vahzii8G#vfffc5fBK1LE^A%Q(mHt$&9$oB15Z!7ssmoL`#ofM+r$y8mZ*gm4DW zsQTWoQO>`R$AYIN;c4IC9Cm+n2mfzqzs^x4*XZt|#(_4C-Cxw0TJV$Wp(p&a27F;3 zbGe4O5Uh#VlK%w!?*=zp?(FbBi!bRG_V(S;T%Sb#!|druk8YB3xEp?${he!bj~^aw z=7H84olWnd>{0UWBR;5ux)bPUbw_$P{-U<7?)E;5O?8X2)9;Pyz#cHTW2rg(KS<Za zf96RbU;Q!t%c>sAUj#lsM_Tw+Da*NunSZ^^fgZ-;5#p+u->ii`HkjZmoa@3td<~G# z0O@dk-ah<4iqC*gMYsrgwN(~xXCC<T>96+VhM#DE{d#vTA0z+7bh^)F@`-2WE%(_x zVZ*BHF#L==Nk#SrqVr&V&^jS~IkY9dwD(!~AT%J~0eN`J0qEd&V{OsCxyZU?JK=q% ztnHRO#_J?)e<4=4$}gtF`&7E)B>qrDu2DVaKGjR<A^&Cay`p&TQ)RnJ1HUvhDV}?V zG!|{q9jL6@&V8!ve9{!Hpd7=OUG7uW((bYQ|3&V5(e}7qO3_i--2W%tbjsBFDjp_U zlTAnbZggktZnVR_=+5YFbO(2hIy1NXv#s0xS=>FcX?JoSHZbT_Eqsy8uH9dfkIosy zImO%k3rVkgND1^F4V<^lB+O<{@_Kipuc00ByRTOQcdJjd@qE5}>5smf_>TK4SOJfJ zfH2`)_>f!^%Ko8@Y0J-C#Jj#a;ht<TmKuM?bC`Ua7!M;S?cv?o3n}+C`+`2|K^D&9 z_gHcYe4-uyxn-wSaQLo)!~G<^qnkullWecEWXWy+{IA-Jg?ne|X{;RgQ*%Rs&9tH0 zYR*b=?bkkWEhBB|h!yxrNwOyh)->@;eE*{F+3pJ`;_vW~Af0S@6)ySPglnBOZ3^{c zA&x@**!bKD^<(3(^iK}>br?rGGrR2kAjI{Dogcl}2i|nQ)AlBpU1Ttab>BsHSmlNH zJq@38{>d#ZFJi+<+Lh#SS5b!YaIe#a_RU?+9Qiai`@K;ACfb(IBgxr!=itwj5!~%0 zUHopR=Du*NeeGUw66cx!)_ZO{z+EuzkuKl(z_YP|S<d;kWHc-7Hsd#e^T81QCf}Xt z9ked#Y;CI2IBub#bJzBC9=WlfGn!djA0F&*x5&?m_8J<OQ=HXHSEGD_PXbF<V_?b% zbTwlzbd`GB2H)-q)0jQw-r2JG#5NgzDY+=L`P^vN1~#8z*$(q3Zi`V1zH}b+8QLzN z9o!oU<X?;)vFpV5RC+r)PkdWJQ#SKkXHKEq8J3qNPC6aawvn7@`#qH$`G?6b-+7`X z*+t1_les^Zb`x=N9j*35DyNrl;X(WI6?|``UF#@oUv7I9a{#@^vP$6!cQ-nMC)mgD zCeP>i#<p?fi-|7x3yH`MGDlv`Pk8ndO2hv!&1`o!IDI-bW-l40Lp~4E)kgM`z(M+8 z?l_??OYIZ9k+O$qljdA#FByifC0u(wlP-~FteE%8vy^eHZ3_L%2^L?PBYabK59v%E zn{@MHu;e548JxDqeg0{EQ=Z9`u@T*&%9PBoE;WAMA|0C2XbcoDIF57qe2UAJ;wPL( zB?BJ8d5x)?^&$BKc#g^vJ*r<SPwR$ByMr^MJ>aA!u=7L59oh8_!21%71Eswh5BwOu zo}FJfS3?};XwypQSTbR4dLa2G>J82;`JNN-J^XX=J)3m7cJ8Rab7@a<I&pij&*yBu zbX$5sQ<AX8nfEsCZgLx2NxQ?^j$P+=e<$tOo8Io{(ZRb#=pWn8#O!?OT-(kD<bu$) zGv2nhQjY1r8LvkO+e3Le_t;4tPI{o?Qb%BS$Jvt3mEyXnF47-gmI%%ZGarr4l_Gn) z<>*}OJUlc#j7@dDZ(lM{P87KZuW!cA^4!whR=vL_UGL}WcKYe`7GLsiP5(f-CO3!- zi*3L#W8DAOm73gNNmp1}`s7Z0`akA#SF3&H+)$V0@x2`VW*s>GOX$Z*hrU@grV5XA z9nE%!>@eNNzD#}9Qhxkz<$vpxtW{1p50<1;*SfZNIJ70H>Do||UR_}-t0waZ_ZS~o zco=zCWv<H9GoN{51AefY?^UYHMV|w|%;oF-m2SP?Px#90G|mr0|J%H^Qd-ToXb}2l z{&PmHb6oI&PBO`OG)vDZK4|J)oSWwBJfId{1kHbebWbR5Xx5--^B%y^MWJ3)yedn3 zmeP(~KW)k4*Su~Lc4OH8)YW?2hYa>ix6j;A*0`JUQ`lC{;G8rbwwOFNep~TT%bZyL zO_iy8m&xG=g7Q}M-(ODVH+mOgXOrSyK<ZAnw1~dyj=<CzD*s_$<!1>K?iP{%R_X=+ zB~!1)CJQb!ZnqJqaM@|BAiV3%dWYeG;GGV^YO~^dgYb=G;im0vgqw2zR&-6@SAaLI zMGDutq;{C~$fOPWj7_zH<x}}?E3{SW;_g;|gePMsC%hyxcYBNJmw4XWp|_QUt)d_3 zSIR31*PY-TVfEaf%mIIjK8e?vIz-nty81hzTXT2y0AV`o9>q>!CN?Tb<fhxKzUG;^ zXDc(YHAN0;oY{YfdBB-XzuRc&{d&qio4Fr-#6#t?*fh;>HY^lv!u!6kkp21f+zIQ> zE-A~`LY8@_HWYXt1iJShAx!;0dtHGyzIej}|7cS<59RHIayrwAeGK>}kMO28!<(OM zw8rn-YFso2#m{EIuhed}b!I<p&K;^;z&NC1>HnJfdzO0CzOzOCd+^($yIa18mmZ-m zuinpk)BML88oU+!-^3oLuUPN*6{q=6{ctnqi<^J2b5hc~8(hC$n`<r3!fEq7`exdU zz2P$|U*$dh4VAI!2f~4PM39F5YySTX*?5gL&EMe+GdG9*T6mW1*IJ6h*aGL-Z-3fX zKH2@6vMqEL_?`&v)Jo@W@i)<KLb6tEHarv5+G*!PUXo^wGi#~+iS=dK$w&^HGHjI# z(1FD{K-}+kEwFfz$z!4GT+4kR{a+XT-^Bk~;GGeyJn$B87<d(SBjO>pb5j}Ki{77g zqT_*puZae9258DYMOw`p1D^zz3};|7XAHcSbE=_Of7StO4L9)(v`J&$L%;U3me~C+ z^PM*bphKle%q|4&kPIlkXY%Pxp_X{zTk^)Dm>+h{y{iK}h4O~Uqq73Z8wPHR&M7%7 zYLB;3?X&vB`h)T8-w@vQ%)Fm_`}k2p?pV7<_6cGAqJOK;ZHC_kHrUD|dXODREq#(~ zroR0(^q{j<&VSku0vB0FwI9(LjVbE@;iH7#H6dL2g)5!!nY5Zes$&y4RhT*V-3c70 zhYjSB>|^rTeVjGm?}_(jf;C>aG;s$BGi&wOoh|58_^^lB+tN1CY_KoLZ}Ioi=QL+T z@%m+76t7?QM7lF4J0j7e{)--4_%C`C+>(AoJTjn1?LFe-F_C6gJ^7HYIbyrFl~u3p zhIc_k!#WeM!<N?cXD_^6=hOz?1FUmu1Fxa1eq<}#tqXJ`tC7dno@U-Whpz#29@@8Q zuRUPpOGD(<`E-)+iN0o&seIsTwr+xrozALFU1tAdV6)yBc;eitee*+sKRFYh0@hiz zft6lo)drS49iJmZS3lzGPC*8GD4<IjK$bB38k0x1iISNOY-|%RWlqS}O?xO4Cp$Ox zA7gNBk7#>Y<pOA+mN=bVnzXWAlRnA7|A)Bufsg9C?tRah86hDQG(sZ5f`kEN2Rmv! zwn;(=4P&AtG$!d7%eI<uopDSO(x|oED6N{(bo3WNrmjH3V4|9FLR;4#`l*wUKDXDm zcd)TbUE0u^wlsD7IWxnF3731ryLEfrciqSP{?0jD+8P74^V;|3^Vy#>`~SbS*Is+A zwb$Oh_+dYH?ZbXAZR)RMuAwW2ppkbF7RMH@gAOV8dV+bAtW;~Lp1HMUhq}Y0a#g00 zld4|39^SzV)`!NzlyiYFtq~h%)~*rZDbeFL4@7!xtd)SClRQvx{~^Xj`?cwp)_xOV zbJiF9c*()%@$Tp+_`1BgBiXy&_!3RvYTd#s5x>HeBb{8)-)9<k2K`h2zkpx*H71RC zT+(kde$m>}M=^eL$Gw5DI{3!2Il?%U_uRL_lb)OO-BhmbxtTntqx{lGQ=D|(j9#YX zxdZ4o${tN0Ixjn<>j?gGXn#L`)uDa}4s9F~;;7L;7f1C-?@eVp)TJ`wPA<@M(;I@O z9pdc={3FsU?b~Yni);LPpIPbc`I4Rk`v>m|az{ITx}_;MwODW<T-?W4%-cTPl0c6` z<tt3>)?5Z{i_+c7*vKy(Md_Ds<n9^z<#nWYp|4x;xAMOw);SiGqdmpteHN7$loRNc zV(%b2%gzHf^oAd8ZBQDuXDw|}TD4#P`s6I#tF$k(Kg{$kdK;!wdfl0#_L-o*P0nqV zOolr>xHL}XdC;V)Lv*R3NwpWUPsCl?VQhTa^rqf--Ry{7Eyn)^I<23))4zcImb!+( zCS^lzr#CO^+eaB2(@(9Xrp$AG3K}wX61SQ+W}WAJmDQMjE@($X={bLX>ban8n`xWq z)&%>`*MKWvYxgD2LJIp?{J+FK?anC8efT%BW}s{1_382YMfmj=6Z-Pi$-1}~PwjjO z-s^cMN-x`Oz2tv6(BsXrM}_&&UuZlVg`qnblm#wm*WP6M(VyeJ6Z{X=&GY7Ec6wXk zt(iE{JvqxSy{T=MUwTv9Ex+iZUdul(z5gZ6?|k5>D;4taZl+DrVRP33SIB?ba4@0* z`>{9i)mxM3&cc5HuhQn#D-PAUH%L}gY)w)I>4W#T+RD7YRafV^z*1d$r&m|n|56S< zZ3D6$$0=670q?(#zPW$Kxv^AiZOjN4#46pTVa`><{$_93U!UVmjLb0S_+fN{hW)j; zWw;K9_pflg!Q~s6sb~C|i<k7~L0$C!2><Dacz@id58I}Ga!xxRzX7_2IMe38B<xn^ zG!f0iZvtz(2)msy?u7(%123|1gs}RWyu3?uetuM^^qECV>*sQsN!^OO9W0D<A8?#Y zSgUE~(v9$f(UBF72LAOHU{yM@FGjkrX96BdwtORT%)!Bvk^i0eTkvn8Z8z}$$tawC z4*qjkhJjtdCa`$$K$PaK_yxP1huT>;L4E2Y=WE{R4dK0>xCK$1#w3m(JQ$<}_JS{C zTHch@nh9}*X*+vj5Z@Gixo;Bq=SSbSL|?s6rtvZ3qH$VFV>K@3y||7Lrv&GYnD#kf zDV2gJ2W}BQ(O0-l|MT=uxcW-C#k?I?yEnSv72f@7{0M8q;Ck^Q1kYMOPI_#y>_@OS zAQujC=o0#^{*yPv&3sMyn)htfkBbp*Tu(n@8QM=D)PC&&U9?^OQQJp|)0*x^?@fNU zzPsAu=xt)>pn>mfeyQ(qhESc!T$m47E!Wcy_O`N<3(t7UZ{zDH9thf6jgiLSjSsH! zs#)qbe!UCTO}mWW@CF>h>~!vC#z=KVX%p~RR9~#AyZQ=vYZGrv<?M1vx6Sgy`zdd) z@oU^?>V0RiYU6O#BRp>69rV#OC$oO+Y*_x2sYBfHo{iTS3;$%Y;r=6B*K5VA-+~uY zp8C!5Y_#_u?b(W7pmh_yLnc1sHVgI@Z^laF!MZB*X2A?UH$lJG3TBwExD(Eu%XcSf z<WCW&d^#@;5w;!p(J#YAk;XCJnZkb(SNsovD>EO0FSS8$Z{J5>1!HdrzHWUje7T+M z(ZH(4B`7nAO(<Z)_%+U=J8R)kFzArBHk}z;6E6RHtNgY9!EpB?aCJ4fE4^vBlU=&G za0kq|z|~yX3-*O#e3EeW{Tq><S+K{DUod6HMBf-;?vfC`1cRf%lETgS8QA<a!UbO! zVF1636P#VT#DoBA_P)eg5Aj<>$C~|0v}!P~QMh@>N9T_;Z7_J!$!6ifI^VBL&E<0_ zUTaaj4wa)erfbU5xh73KG-Uuo`d^nS1?R7zZl@U7DYo~EHQ?D4<tmSxgO?KF*f?b= zkL)9_g%)j~tD7Tz@lg{u@6G_{vi=VmT;9JW<e{p)PI6X;9b-S#S~cl{eQ0SkCZyBc znlTWp{}b~kzoF&1zg6b`R#|63%}o>a2tO;0_~mMA^U4rMn{rgY)`#({T&+_xw<i2} zv=)qC@xsBz&lw@W!M5Mt`&{1F6Am`<%5R@bw^P2>f*o)3QuMx{aIlHjJPTgr*VqSh zN7$Tw7{B7p*=7yAS<#nI-14b%r?a$fb!ur{XKLwUopp4+A#Dpf4sNUyx0*8(YbTgr z$`L)FvgFsh)jI!Q$9x&wZ{jqbwez%u@to5x;1{gh`W5yz`}|xNjNxnXc^~uHZS4!H z%gm43BbfO-Y1UY2dhx4mX8x5f;CpF-&YxYETamUTaGf~8ym@a@<!h~IjLllnS>(xk zp}!M4i;Q_)$fd;BgJ;4$l!smty^noRNXk1!+o8L6C%j6%c^jTt>(bB)^ig}~%y@x| zmNAaCaM^v+p&7U|XFAho!Km`zOdaZ%+LZ!t2kpwKU6R*t3C<Jo^q!zy;)|+1oz%tH z2WRNu9Lk=e_a#kxUQ8eIJ@Bslre4+er_7b=FIj1o#>S1B2bDQ(rO|yO=_byne$kR6 zmnr+(l>OhBFZBf(?D-bz>9NYVNEmy3(C0Yg7iUc?t?5UnmDbevOw?Z8cQbwaW0e#A z434(vyded@lQ}=h*!R<yRA!$)aq}v#6}t!@|534eYUPN3&0nzYXdh)(Pgh2K?`d?S z(9bzXoC7~JnVv*XgnI@zw|dZ-?X9HKnCzg;9mfv&P0UMu<A`KlZWDZkdGxE}y1d`{ z-aPhRq;ntGS@`~@5^_;&0yjI;=kETh?$q!6A@+dEhy7Xm+8UF7Y{m^>bJ^(D4B!uS zEkeAi_)ym(lAqId`yDLzn%Vu*V}8^(m1WQUO8Q}J<^*s}8s#%}%BG$E%Wi|_#lS&e z6OleFNPUR?N;-pETI=3hoJ1Zy?DU1U@cOayc=*d>k<Ev&jrH&b;F&+ZgYW@dKQ51J ziN;d6#MEuhcm@_~+u}xfH0>$pEjTz3{50=oe>J)<u}_Xx!m*q1b;n43(cL1+!8L{f z%mw2EEfv{i6l|IOd=2BLv>HQu`~(LY6Ya%{uidW{ZrWsMfm8_|Wbm&0?bSs$-e3L( za=X&X0=5&K_Dm9aw-fT>v9mX0%U<s(Nfs~uMbK92oOwsrlE0^l6MiFb*aOc-^1n?< z<dZq<?M)m+j!qnU#FA->e(1~`gikQZU7>@%WVtH0H+2xc;K6{`FBwL2-l-_9;xf_R z5L>sqvI#qAl6{_7gB&(E17o-DU5EB%`j(EyTZSg2E0j#{*%!NMcu)K*#XXXlCV9g? zkTdfJNGEFvK3ZcY8QQFn?%5{(PcB;Nb#lj*w{O~eQcL|V!lWZGk{QG%#TM=fZfX5B z`jCJ(h3%y3{AK7lEFP>%-=RL@h1=&J)w_f?O1AM%^3|swLZ&~qu`9R0x8?f33(eI) znK_La^*R%*1NtRBhU~-we;a+>T*UP)^|P6!{x;gxgX}x!AO}XqpG?A&Ng~T%moH1k zul6KTSC;X2<=(iAA2!JM=MU}l9{Ba~N?U%s(oGwjOi_FEdCBS1!b|k;LyV{7@C`-e z^R!JeYt5U+yjB+9NZX7IUTNNlj)3$7x)>Yj2)Nk10!KZAoxL*O7lhkfY<(tapL7MT z)!b6A^aK<q9Ra}+^4UhUP3=_s)YdDtQTf$I=?f??{3iCPP>!qidaGvjK8#*~w`z&6 zv?^1!XQZEyNbEnSx^&N4<F=Kt7cNjb;Z&tHxYXozQXwui{&CXjj-m07;FsLS_?2FA z8{-EaSc4&5T3Gv9y#nb+NUuQaPJ8g5FkaHzFnR^(s=z1OQkL9bdIjD1KTZEP7ncS& z#?&JmIi$M*q-z5XL<9EWKgv4pNiOw!S<4N`wV%M>guabr+<m2k*o@vC%!lOMO_q%N z=U8{b#YRt|30(A6>gc6R)%6rON@eyX5BeKQla;TQhBt0V?Wue<HMnsz^81aeG~ahs z_cq16wax-RCY{S0hAJDV<I=msx8LMn&$>#{=dLVvXV@>+=Wna@WVM!@^Yy$X3ahKJ zej~P)K0Z=O19vVkl}I0aDUsRj37-C$v1nk=wD$_`&LR6ha8CJ~oso0cQV4WQx+u4a zv5`*WK+umns((a3O+PNBWOJQ+9_c-mccce5UMdYi!)~dvhkr}=xi-=V)^>F=7Nc&? zL&*jH5dFOL?jiIrUfZv)F-FB3^WGEmC7uHJGIz<2y)(Fv{<aGL{a5ts)px;;Xj$$P zobO?tB=6Jw#?VDwDxJgCp}vpSgVsWze?mW!U6X-~UuhE^p<R+098DY2%#-j!H)&-T zNO(<jq;xFfr6K6ty)Pwl>^GTdUu9?==&YkVs>YwdFWJ5EtF4m3*?!5aj9<D>vui8V ziR<TmO6{>GP3_vU*Gld^uU#uzAK3H=_E`g$+NV|@JLoqjhbrH=amed*fphrePt)E+ zsrW)&srZcMrU963P976Y_X713_H=bmlk3TreW1TWT%f~3ICeJ6YNKSyW<S(Ay^ncW zLOB<J$v)?x-wW(Frza|xQiH%t{_^m`8k&I@*1^@_MY!@R>)@c)!2_&=<QrTE3tzhq zb_+k)>)>(f)H>>893SQX68<0J+nnA@pN2N7kAnS2ZyfYArk5B?t%*yFx68T^+y?7{ z^&neQYx}UHg?`87^mL@3^R}puS6b(>kG=7A&i$p=taJ6v;6R<#kjJ!gHVxMJYG9+8 zHU7;F!(L~L;3QjpCJmezm_SFV0s2F*0loJ^T@pA!FG?^n>BhYPK1ic?5S9}zx=1i$ z;CT};um36da9Tr#hKjZC4rG@~zZIOJGrvtwwaLaXGDR19i1pbD{j(VQCkg$t_!VGI zI9oW%VJ=<|Z|~t=k^{`Wmp#tqJF`y6AK+?d7#uuU+2E9_8|X)Xqv@aW2v2Y1j>nbo z8OD{`H_-nL4)1rSDT6V%l*(6{las*8@J48X+yCF<%n!1@q2A96{(4zsf<fU>!Qegg zNi?a#gLY7VGjB|&?ih7%z)rK$sc$7<^$yY-+|Hgb^M5&Gu$(biPCCt{Q{qk(V{p+q z<gYEUMpHupeh+X6@ILW$DR|SOl=_S(Tq5`|V|1Hv^<{9X;6Qja>rDUfaniJH3-uHw zkDS*L+V`EwH!tqZ+qm0{J42q!St`*t;VZAoFm?m9F6!x%!i1LvU)`M#`SJ@d%P;$^ z@*CZV{?*}~a)l{gceAv<;l(#{f9-s_JLc#o8{)wk+1wMzaYoLt@1VC3oI$eu&!baF zJx(gDYv5Yh(wYizyvpv6{8u|erIKOZBd>FY3T*65U{hvqsGFsFREO;ENyaeWxl`{2 z1Lr+~?Co>+Go}Fz5T-*Xz9JelksYn*K8@~Fe>?r*@=@o*<x+HK@7vCY-7hy|*EwCB zgl-+45AUAuq;Mg8ijaST{*~5H&>qI=a_33cI!~UvAv{l><*PPdZ7lvh&y(iO;$`CD zW<vf(A28VpALHZLQco~v4Ia9B$4C5e?7vQRaQAkNWV+~C<wQHlhPw2;LK(GqUE*mN z+#$L3>R`ON--|rADLq=Jv~kWwqATFh?%qXxg!?awufjY_2XW5_-|e}1^jOl5_)FlG z!1rl%4~|q~Yq10Qdn1*z>vs7a=oW8BZ>0D5LjnCKI!<Sj3_ND-7i)1D)?~UbJi~}@ z0Ke_=3t!pgpTnKSUBro26`jv~hV9`0*&BEt0Jyl=_;3I}=kVKn6UA$e4DA@KFU!ud z%{OVFUpn(Et$praz}|8-zDdv@+93E9f8cj%S1oU&9-eH6#+NYz2C+du;_JW5IPT#8 zGVD)zH|z?+3iuPmP3xO{=o~aV_UA{iKTkX^iA&)+aQ(PmTpz9**Mr-N%i*@+WMAVH z-|dwB6yFl=c>6B@1mBamuhLe#{m945vQ-fvjc7g0@KV7MZbq;)5!j$Hwh6`WKIx3G z9>TS8ivL%8t5AFm`>n$J@fWF=^FU-vD&ik8PrA#cyTP^he?LQ>v{mQN<JbFurVT%b z-^tCM8Jf@&w(T(`bKK!fq0=$P9uw<@GNeyu%K2hcj`)$r-jeh%WNS%wmzLA!O(o`r zvNGsU=<ck^8`@i%^@sMBX8r10bLlGfmLfjGla&1wb(AQ3fI51UBLR)|vsOFJoigDz z_>@azv)=r_&a%BEzMpI_v9{5Lcxx2|8`$&JT}1IW*<+!H!~b8f%9ovh3UCp(;_dxJ zHaIfi7vUP!8|*E8+?}94-H-Xa>H$xP*An~WV5Qa`lH+*TnVM@4$=E`Ib_>>)v4v#( z#uk$C8(T=mFMCLWHSy4qtq1myOq^{G$=E_NaS3>ZwvOp3^dx2T=(O}Ov0E@Gd#>>3 zY~4`t8HIOD8R9nz?-;-KRPh>(U$%_IV=(>^{8!TrT}!;JyD1wrq6tiXW246SRiEy= z89(-Xt0-y&ayG>o{Y%k=#wJnR`meiB@jQBR)5TWiYtdfzOU;|?S*5Uv<mNwAS@IkA zmmeD{mcIsE7`sS!(<b4;O|(yS8``D|zi1kT**1~BPhP=MUu3UNZ=_16fVRXXZ%SpS z{7&`>Lm#Y8F7;EKZDZ?3EA{Nl?%S~K`p%(B-TY#8g1fBai--M@I`p32tNTsi8c^OC zeFiq;ExBTAmi9^ZS_e)B=QJ8QWnD`6Vk)rzsXok${Gy5EH}S$f@~bbL<-<7sn{w=R zA^xxMQ2kd5l@xY;0{zP@_IWbJR%E~JiHu|gx`%^aX}YVTwZh(fFqUB*Wj)?fm<EUM z@jKtj9fE-OdV9G6+dyrZ;&%ksvCK#u*sf~LNv@zbUz}_)o|~BV->QD*vlY%`?Jj9P zO}iDZws+E&`|xwmk+BWKItcr$mBvktR@7G$uW``-T{njOhk5iFzD&@6?Hi(@nve^{ zUHA>R?tQ5V9<*%rWT8QWF^T3lus6w=sLd{WN(x#S`?c-hjOxi-NBt8x!MdqeI*!M& z`^G*DKaqWcI$KsHd8cN$a$?0kbVP?1omertI7NBVvx%+SSy}&{N&n<cqmd1uuz%W< zvoYC^3;o)M)6g^Gb*)FYwTU)Jj%nhh@7qoK3C#^@{+4e~4BJ*Sb~#4tn78O%)UeF0 zr2mRlhIIbLi-PCO+A}tUMi=+vmkps+oMlpTYzU3|i|FHyn@6!BwBMh#A@q<BuPKld ziU$+g5R&fjY=0Cc-C^k%n|je>L$@1x275w+y%b~8fur4#O`)*eva1)q%N+XqoFDyQ zHDRHhp)f4wmMBBEhDQA@Di_)^!1dS#?M?6hEp&{rH8je1KemQu+wf)5Uh|2amEI(L zJ>cZ0uul=JAK+Cm<fFF{+MEgN(f?Ef<6`wqcU42XM6><<HNwu)Ml)aa%=<a~vP<MJ zc5h+a-$&iyy~wa^*`w&SU?8QpP}$2<OSoexIRkbNw7&;52l@LLtAQ5uo>z?e{gkbJ zvtMDj9XRk*aBp6CG}u3x<Bw^*@qIU6$px1%7Q?Iqqa!W+t92tfO5>0rPBf6|hoN~G zOXQcc<M>@*+g^{-Eq{W%FW$7z_f`Zp*L1%5CiL-lWIwS)oXQuxm@|^G%W3K|;SHo0 z-1L!0Z5I#6z-KFRKj9kiA9iI%_tE}gzN6sL^P6s_-iFpHcT^hfKB%3w{V;W^-RKOQ zk5SJb=)4e((K^C(PuZmFVV-n%_BFVp&%zzK3I8U>S-9hg%&30^7vhdk)*#&R81-Ea zcN|HDxZ_C5!X3PoyPkLKo?txS4V9tW%PM<4FnWTrL%M#p>{*-<hRNm)>C4BdvpG|Y zbNU8%AVUG)lQ!6Y1t$&8{uz4*CrGPxp>V;5_7npfC+NS@YFspzD)+yeF^Ob>JJ>T_ z#zc2<`%}mmO29Gqai`!z<=Xc6+Dirq-_|kh*JrtZoBiu*eQv1Yc<A;!l1U)XLXV?9 z_czc=`FK2EEN@<?y)z513YpjxeB<IHejV*kW~co&_{jB~yX!fF*Jq!ltmmo&4);>m zvDdL?{($+|+Nl58s_=S0{7CV#|C0O~%f8G4zZbV1H$a@|DA`@##68adFQkfP(Gd!h zKb721{_uZYbZ@sg!#$xWYyf&7w{CAx_lwkVl)AnNAAE|km$Qe7|8qE!m)yu38o#w+ z)Qhbc@}5ac4xsyy&s3S~s`!5@bGi6`7Vl4O5Wi8f#`&GYyxFb(L@;<WV+TJk&b{7k z`RM$bK7ibDeC96kIAi$F$n~_}Xgqh|#wjBqe8ZkzNG<U5eGB{v#lc^kpg-E@bf37u z|2J}<*o?)ttdTX|sr4G%Csy2R?-SoyJwlt*FWp(r=b}5svH70vGf&1EJjtgfWAz?- zEdd_+)bi1a;M3G)<ZyPF<c7M#c_q1_>gy5jhB4My^y1gO<34@4bG%*OzMbBf)(U%P zVoQ<xwz_*Pdl9N%Z^(vn7R^hJ^glzp;;C8N{hFVxv?08EJQ~0WbV$2k&Axjqzxt%| z?7PPbH+|FHW5vf(JA-@4&$0FdUo4n*!Mxx+4xE1&JT`MjHuslRH#)m5&;C^v+N;G) z4U%O`^`rD_inb+ld;PZTUjG$rVJv4nmb0FWEsW)?r{%1xG-a}Xl<RWv8MDO*?w}9p z%ZB8>%2$)48#f^1{%U$`<E_|L`w%>N*~k_g?`?>A;?Zws>?RxHUM#uOv-$OFoju4k z;BRy9KzD*AgUmR{=YY{{>b8n_GwS#H68srlnt0tS)|hKuf3D`f@YZPkt)Ok{-(l=m zCz0)kymr<YYw&L1O?-KK?TO#6c4&=i4eD*nvn$c}b3(fyKZ1{GkHLQ-UN~eR8_J&4 zMw=(6Gnc}Gb}|+^a~Z#6Pb18k;zqc8B3_T;46kP!^Da59<o}XGtzfQp5H?PK1g~1R zlGEl1lbkk>e-ZuFo?z<G*a)9K$=pp**GO`yKb?y19V3s`9b_Y$weKG*zkUC>CBn&u zKPSGD`7iusa90dozQ#|yM)7+!zUb?pzmy)WG-tRsUgF+(CcHP!y_#=zAz%6s_p!6- z+bUDs#byt{?&st=-N)YSu^yT00S}x|TIzqx+{*@j1QRy=s7}F+ffK=xfsFxVQor@R zQEUm^RykQh*1#JgvRQV?D^wPikS9fTs=m!<*_)_qYGK0r_Fojxk1G6d1i0;^Ji+ao zsrQrA8|dtnMk{sPJ(t`go*Apm%M>5oe5_dRx>fv^LZu!Y)m%DRt<M~<hU1XnZIEyr zHmm=%=R5zSP?>6I@^ml#(g$f5^KajwSHIOZ&70l#_tS=;Ov=!>{v0;g)Tb`yMtH^C zslOXJ%NpiMcgpn(Xq;$2*BLnA@#feccB7NUIjS3*`r^Yn$df-2lP#ane=Gl!ylYoS zJ2d`!k5T&+e3r5an<mV@2QYwNZ{eAE^H!empK3qg>m9u9jR*X}Mc|%W(8rnZ$`0>y zG^gfQ#QTtp!=zu&SeXB7Q=wgH<3D`Efq<7{{Nt26Liq*4hu;(OQik3c@={EibHo|B zvifuuzt**h*M6gQZTza=(2S}-%{YrE;J$CTQipz9@&n_3!@I`)#L{tJdBk^7xruij zxT;=<8B0@7?Kr9(Iuo0C-M<jsV*G6>Y}~_#3+x;r7n})aFVh{e{|t>%Bz~H72TIr+ z#J-E(LmT2<L%rz--?w~(aHoE#`~>OTYx3m_E2sR6G2+?>gLf#Gb5_a!<ZwCmuHir? zWa>Cdnd1K#|N7P`|0&9NlJW<!g;pYdIC^hQGE33SChZC0j+0hABE^~TQ-q%+TzmvO zJVm(f8Jl!x@Si5#y*24P!e1m@X9GL`Il|8pE`Ed^{xV?~iMvpm@?UWnAI{3JCd2X3 z*f__g{KQRDets2iFC~V`4Q1Z8!{&Gs;mH-Ge=By!d4H*m@RZA#y>GZY^e4mRjuvbY ztuB;TlehRZ`LXxrzGbL<n6Vvxd%j%2zFy4DmmkC5N!}%-TXqZ{Qga?$8?Q_gzVIEq z0m@zS;kCRQ%-!eMiafHwp|b2yn{jB1=J{RBbB_F5SMWwEeQE+1ZF6M@yHMU<rk&(l zOPlg5hRSP5w=l+=JU25>t@-lHG4*M%Ji#~&(-((6#JFcI9<`~bpS*pvv6nKj`&~}2 zpiI_m@W$Zv;ahqpZ5L@Xq+PGHoOw4Xt?qA2pAOnqJZh7+o3vTdZjRFS)T9-E*rZLb zVytcnZ8yv2g9-oRW@Mej#gh}~8i-fl2a^T%T;9csGX~gON-AD&BEC25oA}x$|1#iq z3Gr>DO_ASSTr77yL%v0%r;OFa4Zn}Fn1dnOFMhqrt9K4%L(2FEXur;=#$TU8*TV99 z%&U0zCjKmb$q|hI9Dd0ejK2pw`X$T16~A~WCO*cVEdGXYO~WsWrs2*jd<mVAWK(Z5 z_~Yfpvv*WPbNmZ*19&B{vt`PGehlt{82=LBN@bj(4ACAYT(n0UVe*TQrFwN9m7Ofk z*sXEG4Gm$+(Aff>S)=k$Z*cZhKEk1KXVcsL)V=q<#OyuWqj{Ybd#e3}Jp;{D0(RBD z@A5xhgCk3fp^YPt;}?E3eK>*N)=4^vUwm#8e+s{?lXM!tjpxqbw{h8v_=U$z{;oA) z+v*snHPL_OrF|`PC;GgOwOZTewWM3ae%VEuVd!!5?y2ygDR(n*HV)i`U--|&XYdQ} z8UK3x!gt1R!^(?anhPtF(3pai6Rkf!te~{{8d&L%=3VcJYR*Ob>n%~j&*xb80lq4+ zHnE8n;;Z5Ec5s4l@7iPFD;Io4I(JdNJQ5>3!c%eHdkF9pdxwpuPD2CfZQ5yYpx&=N z3@&%Dnfw@a47+*GyZQ1F;@r38%WGKgg=+@OYgyk<D4sW$on_cB`2g$uUFZQrgV=C@ zz5}+{4(QxaZRy(?|3ltbm+hi!`2Pp|7wt5k|KGu`X6`Eou*G(FwXUxiKSEr8a1Z@% zY>^e?kKz9$adG~O);b)$$*%b^bHy3wyn!RZj)9|J0N%BRZ20~RX|;Z@MknOKOFJ0H zfKK3@KvR#xw2qK5em~JyEMND?NaZuXU#u2d_WR>2cr(h~?@t}$o${NI4YaanflCh% zF1)zh!OjWxPDLMRE{50#I+7ooq0_=Q{Ql6l>vGZOMNgo-O!}9|?74sSd_C*>Espd2 z&-9H~>K}j~mJIQP$)`LW@O9O16V^bU1ZAKz&~C$Z;(@tv{SVN<g6oUi?J#-YEDl_G z8Myvq&Wtv`>SO(KMlZw1cwV^6)YTt_|JDC}>HBlSSp$C#JZar){CCk0(dzbk=iGPR z;7d~;Hve7|_P2!1X$xilgVOPnot_z+Qa0@mPtz?j&iOrl2YLab<x}7$;BmO?t%vrZ zCozg$&I#QoeDO<vwP#8CulA)#mq<M1*FP}4hqL;=oevcEa8|9RvEA{j;55CFE`3<Z z^={)UTu1v~05+e=11~XXLFr*6NiSZc@Iml4htf$ln|3N|h~GlqB)V$$owqjpI$xN4 ziXZ40!{*;Xe@9#RE%0r_KOOno(C-3Hy$Ss8C&#cCG+VEEkIs~LsvZ6|`Zn7e_XX#X zHPH95Rp0~c1c`RiS;VA$jC6DD1<jS^j#JhMX$mR}T4JbUu$+JA&>UH=_zAWwSGqnr zf0#M~Sck4K{)TtWmE|VzUrm;){K63?zx-PJw%^D~H4o$0O1F1Q_20lR6N?Y}g}Q_O z)U$+PgD3B><_U|X^5totIB;@N>0|lwVbVMZZhowe_*Upt#w^b}Gq&7#J85&IYw*yy zQ@RzLz28GQrJ?dd=+l16-r+M>#~JJTLU|kM2T1QWVneAtUw(=_L(sxaH&XVELjg`U z{TLyw_GY!6vr#;M?ZFuv0k5$|BseGC@35X_BS?F;DW}#(kj{5{+ful`(>dV(7UQBi zO7Pi=!oleF+IElHEZAC0UhT{EeZ$BffopUQR8MTx&H(05|3qlh%hY}9?a2NKJMk9a z1>6@~4cq~9+Ph7fv&4(;H-3*iFA{d9CXZyRCe0egM)b4suf;Fg)%e#l?yH|Y=y%i| z^gD^unXSM&O%o>k9=nb)r=OzNO&-CK=vUh>`qlW4Qq~icr9C-MA56IHeVO|<T%m6- z0q>d%$t#{>y_|fW{x>4?=e*Fw9h~F%$NjJ!uCuu^^v*$ackZb=z}9EUgZ<i>Iycde z40U!<cVIILd%_w&(b1;<&BTi?H~uVs(e1|HjbC)S@o%N99>OHc(_EWyY-r5LqfH;` zXwNwCto{GYI_V?`_hFYc_|Edw6#svL=k2z~8j=cYd>MRQ2W=$$_y_C@f=AUU7}ff$ zwUu>OxDS-K@)cbEZ^|ex&wIy!pJwjXNk_e9CH5?cF97#8E}h12<5Im(s5*;`<1~Ff zOy9NF53L*&?yKtTYp-X$D_bA6^=ssVcN(;Nod0K-OWnN!PU8DWcR9Jdn_=H!EK=-2 z;yZoiGW#oV5y;8SzNa(BuQHypmo?1S#U{$AzW9GdUni7}{u1M5@<=9GM5oC3CFhpR zwaE(8IdIzYhvysRv20`IWE*Q_#x|CH{?l5JT`s-*V(QU)kS>$)3l60_W&DD>yyX{M zj#z%dAuK!Sq}e=z!*R>6{k~xNbtas!{Gv6cEWhk|>75kQhSSmi%h~kOyGyd^^%e5; zp{FH#T*@b#<ATLsA^a7qEZM=*e7;Ip3*%OR{?<4q@Sj<?f3bty58n2oGwXIPHu6Ww zrcGO93qgCc@jK-EN5aS#l%YH(&d9fo|83E{8~@@O{~Q}&mR_>x8Yds<?3dlXkQTA& z6449WS<70p0S?Em<}~A?duH}pYQS%=C7r$X4ywL8qHlq(?u|`He&q@6YL1~d8POfA zn_+lQv0JbU4t=gS`)ry+cvpI61`qv5(+}o-UQ=H!z4W>?5d9jVPX+LNEf3a|sXp2I zV@-^Ujb{{Z<H}H<A)Ko<w;MV?)DMw-UUa_hwwv;6>HL{+(p}ER=Pi_B(}=<QtJx4n z1ouvMXSg3kaHBA-kp^d{KhTZM&ylg2y0u1@5N_%e4`rF<*ZOd>*y{qOOd7$k^qY)d z@)-GrzZE99Q=PT=`{!6I;>DPJ=sUrq+3E8x!g-CM#?8b@wrI`;w$6jrgYYr*f3Vk4 zMnJ2~Srh0j2qsTq_tL`#=5}mg7M?Da<F^#b3*p-vT1V$*Q=e>W>c4phQnoeam+qtb zGEO-o*w!o%Zo`Sv+!dvfO-%VkFDs91V#+UiS$_RjKgF+?Up6rnHp_z#{i2uc^mo+w zMK9a&qL<}Y*(y);a_A3fml5DaXKuv>`Otx~Y3>BNOEISv*%xo6v;M`8{~BkTrX+g( z#I>QzoFva6?|jAKJ=F5qXUZjQ1LfSy9m6EwFY-<CJx%=?zJJfxML)*Vx4yOd65kkK z_RID>@k0u4YOU^4IA3(l+T8`M)eg#W8(Rb0oTh!cmwAGA9jDGI+IEt*IxaS!;hUTy zO#Bnsb02KUm*en9Pm^{CKJau2T9j~ZDwYe<U4>o~9Ec9I`w^o)?f33{^m)`CzVP$f zV~N)4_Y@uv`w`=NQQ`AitLUV)yLDl^V|>xuZ|nvJL_bRZ=@r@~Jgsx1O~Z*VP#?`r z;m*1ELU!7OF9zU^n)bbMd=c_jf0FUjx;FW>rU{!_&)UDVcP(M=wLjLA-lPrIHgS5R z;*}1yEtExz*YhglsCTheP?q!n$lDr(2mNfVE~OmPXJE7S7&PUp#0{t58$z#1e!Ui5 zEt@VEED9EOKqu-QinaKS?8LN5X#^)<CQTP<GWd-g#ZDs_`gzjmEsRa1(K$sj6+4aK z3p*=~%-#93N%lC>z35OrvV#NUtCbzh$qP&%-)%fXzQ@RSSot^?$i8u{9Kp^fSi+V| z<BimLfwVTgAM_2_QM=C(XVd<Q6I^|PaeRQWOB3Hon2|x*b!fezFV?t*H1_!~D4#X> z4&p8n_cHl)7L%O9&ad_PHsxo2>~mDm2IAoPG|INrQ_0ZA^HC@4dx<jbzT4-zATR6Z zM)JB%qm`y(;ky$_boOGLwFi?!fgGdFWj}_0w}iTDWg&Cg$l6msI$F?gChaovt)?u= zMI;mHJjOcLIgz+pxrkkk*6>2gxj;J6t0wLue$lJOAGDu!UPsyq`X0QsLVvf?_gqPK zWrwShS8iiWwtK)a=aD94alMRjAMu08;}#-^>rd_T2OQdj3`=sj5z<QTJ5D~G;T~)n zDi=tvw^&?ca63qwPcbHMN6rSl9seL-$vS!4MRtbm^L8-5;4Zz__8rbS%P1p7xl72e z_gn^f+d}wGasj(v!q=1JSxveQ@)&uiohC(^0%>yeU3-o2mWltL)D_s%Cck*mao+ti zHjslohcbVOG$;5TC(V>Yd*G#?EYWw`bBZ?VEL<eMfb36ia=43z%BM*iz!PsKYwgzJ z=_$$-PH}15Iof906OV9OZ9AVL{Tv#E^P2L2w*q})H_E3r8yeowA%;I`?3w(y@6}&q z+*H2su56j8tur=FBE9gVoHw0}&YyQ;^VVtKaZI*RwpN>R#qvRT;N!0B_Dg53$oqHL zY(gi4^K5yNb4{GL@0O*I`O`1-U)og<;pY?SXRER34jW;Ut?1T|uQ}wG`p|#4X_#&K z?rJVKiM|?kd>D^;$x!DrZ0qgt%dsCSIR)qD|3#am2TmO=5Nhxd?yUYb-wV+htBZKa zl(nB|PmoMo|DWQ&WZB6a@<{w`S#&hWmuQ={52|?0=K|6`$D7g5V(<GKy#M#j4{Dyq zym)fdt7je5>utf*XV87W&x@z`mVb}*n!lHkk;I*4bMmhw|0?D8!u-wHLf8A23$6U( zx7CwRe4m+mdAseKKS{nE`Ld(la^AFBo~^6QBVS!q?>ySS33-&}QDdd=di?sY_PiSO z=Z@<Aq&v-jjl(DSFIs^8z446V8}8s7>^v@=fN0Dby(k=d=<(wzjme_w&(JpMB<TO` z{687}|0(`UCqd!t<qf4pv+YqEw7;ut)v5Zpztk=r1nuX%IrjLJmA+v8=l;cc!G~Z& zaPi9lJZ-IF+xGhjXm2N{^RWX6Y{4d;^GA}?EJJ?}8nXN=q?rbXx;gZYi2rB&Ypk+0 zPOI^2oPu=tRSr76kGIvN(;G}?Jbmzw87JwMUF0mKvJ`*L`ftV>{k-<D@5SoxkXLDs zlg^a)L=<+^3ga!ZAl+drtVozCQ!s7Xu%9;Mt$I~{zm;#0eA{c{w_5Si_0HDB>kSCg zK4^jSJCHG|{&Y>c4lCU@;#GH>71l>sgOx{bBD{)>N$H$aIA)SL$*=m3W(6bY@R6<_ z{Bp*M6Fw+8p?vf>;SV`6&*W3M=*s`WSSVfC_S=OYS}Ak!zaZaw61Wp=|08J#FRQML z;Nt-Psq-hPQ+&8Imz@uwbnkHKsR=>V0E?snEH;5a|0FIAr)Dee4Dl)A9)l6oh4V<W zp0EP$2=TAtdMN8D+{?JFlsTa^xCYAU#vK3&p26viX>4arMYz`mr@5?8;m<VdX8@dA z2>QU8*tvuIQbmpg#TO{{`CjCf(mRn(BzWt2>09XiZu!Z3Lbl(`SY@sM8f%rEvBH#2 zcK^)$%Z}XYn)qc=yw2jR-}9^APG51S8LwAyeYk0yeRk#?Uv@LP7d7F_Zlk%gs{i(# zRne1A#%67@>HKNmQPuf21uYTW3xU@r{+YSwsk5$q7ggtH`!1@^*G^7t2=BGNnY*as zE0}z;U#@a~oV%zWr%mEnnzF<f6R*|y)wkx-kAD|c{4Z11f5cr>@it8P;@@8OE^0(a zH0Tatim_teZzZ2#O7xCPSYJek1pe#c<wo|gO}w$~FI)Bs>r*+&@Lqz>pqvfktdDl{ zj`2pyS31=pT(E?A=#NIhmkIChD^@-1P3}+Bdk(ZqeRj-iN<ZtT&}T@Uz+rPJ<t*Ti z%Co#p^sGO>^y~~DvoZB-uqF=Qq_rgb`=kEHSf87rW2U08&|dyneVlOFJbw#1J@x6a z`j661oByeHXdKlJwP7n|nKo+va+W`|l|LIV_}Om7Yd!Q@er&D1r15pzi_jplm(P8o zB=?C(a|`X#T`c<E+Lj(&d>ww-x^$D!XxmnKvU|S?yY(sDH?Vup{VPv4?v>_f3455^ zIy`VrRdk<p#2cw+bBVWyli?li4&b2^m&JAC*04U;;+Em2z!M9|$9TLXn_#o{>c{H; z59UdAETp{17U)agCQT07TJ^Qj{%>;MSNFp<(Vq-=f^;YC3~A!nxYt}J38zo~^MpCk zF9nezyY0q~{p|gD-nYmV%b?=Mqv^jcH$mq&WO$pKbv@^dUIVN1QW4)Tf>qlVf%YAZ zyO~FQ<u`CF8c222MP;b2%dLmnI(TOxxOZjt2dyQ_4e+R0Q>sVzW#_CZ^lepsPx|sU z6rr1fw;8o=l+M`t)qb!f+ACe)Ry-Jm&D`CM$~EB{>N$8`?aM*4g74Knt^dpQGZ>$% ztot18R+`#%Z`!2stX=bpW8DYzrt*Fy>YMb>1@pFzd?!k0+CMYCv^N;zsQo`q+b>?B z?b7j68`)z6JJPl7UqZZamfEfMtL_kg&947&ADZ=xpKHHuBRpfjZ6iF>##%Au3BT}$ z&5U38Wtrs{e$m=8>4jf9EWg%TC+jSYTZ3DRTTT3*M(Zwsg&+4lfqA^s2tI9LZtV92 zbUqNRlFUW0l;&)h3S`Wj0WSZZz_wp_t-beJJMNczPvA?e3&CtQIV*c}U*|o6SFt6X zv(hX7Hp_px_XM>5ML%hdU2Iv4FJS!2FBmX>_qy?l;9%B2_q~BU^=lqYyz*<Fjei^Q zo2>REh}S%uc%`>>GxffMiTlJ)>mCyKu)uGz>xL?NOTol#Y3{B9ukChv?Y$4`?ge=S zizaP1e!-&g3ug&m$#1`VAUeQK(`&W+a_=C(pJ>!NGI?aPK>y)YHU2$!MP;{oJM?PY z31LTZ>aXTkV?Pi7eWX!*7wHrx+;$IPl3U21NO32KIAFhQ%5h0^Cut5q_XfYn26ko; z`k$~<xL0w(dWdAI#vXDTG>vT!+07NpALTCgr@t4h`(RvV>>w{1@nt9ZbYKse_u9BW z>6TctwmoFzU&o<Aj=PaP<o3`WGX0F~ArE2?c@RFd<N?qG@NhPHW0lxfWDog~b9X<; z+m_Dw4;M1Who9X!LyKyy%huGuV%eVxX=d4?6091(;svY5FTG#Es`2ZdgiSlk-iV14 ze4vjM@Doj#feYi;Txoud-<FB%-5Ko<inD3Ml=gvub_nhVHpY~O`8H+L+BDXDONJQO zS7uB^H^tt|o#FSfXXK4t<(>ZF(VcVbDr3{G{9V~qCVT+bkIUnPzf_*xZmkP&e{h~t zTx}Z!PYM?-rE2UdUyR^Ku#GGyu*FgTmC=f155|^7OCJ4!Ji4;9{hg$dPSz^M0obaR zxEucDO7SW02=Gd<m)|?qy71m&T=0FAxNy$G^R;M@aLz)%@R#;-<x~0$V`=sWz3CIq z0q1LrK9_Eap(D_n4d@8<PwPit*$qj37Ff=Gr1IAL?=S!MXNu+1tS9NCn0hpR=B)Rn z^pAe9{=GZ>%sjzo*pAvURk&HR5r44t8qNW#PjP|+wOxHMbFT5W*C=CH7H?VSRoTNh zq_-?`*~%IVrq=R5Y-eO2>4u%bn{#v9Iz(HCW?)_I5wA`<Ck75Pgf-`&33A2O<IcG6 zWOR3aoV)Ymf!?A?7v7y8zrx-51B+#M<49_Jaf<on4nceDE3&(>pS$zp{;yf}3HPxM z%1d4i@m@GC`)0;0wjf(w%6LITwJJ_<pz$*8K!z6D0El#CH|u^}X|C;S-P?0B;K@Gj z1{b-nj=cOI==Wyue+pZ;!neKLx9#Ij>gtKTeqGOSxih~vfU7#{6C5^Y9e8%(-l(^W zWp7!$Iqut34l?#9)^Mj4+pfk2_S&~$1KYs{_OZc<xVr}%*wgzQ*}!fr?&*Y<m958k zspyL4l^sCYzn<K<(i1Pav$WSQQ091QSJ}N;^gs8Pm%;DHzI9U?9l6N9wQ!u;)YWJ1 zmhb0o`OcZU<y+B7I{;p-<NU6B(y|wezA$Gc>{(|ld)9qFzAbC5K{GD0y&102+56>+ zyWIWqPtmS7V$1sDjL(&9S$`tB+imJ^WUhXiFypU#yY7U~womuAe{OmB-nB{dW^7p_ zpA2nTZ(+X%u0I~t^;gixSF&YY+eX>tRU38xTy3yzS*yLWWo_DK+ACYuCXBky3(gD- zab{?RAKDHq(I)L(z)QMV{sq$6Hm|>hUu!wf+A;R14<PFho>bWePuAL_7A+%t)Veb- znTqbSiig)tn6XE#`h^!w8$%pej0-23J4M26=6_QXSq^aiF5>mJdv9r)c1-#koaxF} zodWmP_i}H2Xk#WG-dh*1ebT|UY?8WplTdeyW&hK@b1PecchOeabJza3e&V*u=3Hn; z8v9n|>xpY%-tPTRqm?xLc->8?gD+7BuS0VQFFvplJs(`u;DkIK^#j%^HfA3_*X)d* z)4BJpwEG##YPI^a*}-l>a;bkbHG$0nbR)UT{RIEbUG6^c(PZ?Nw8n@#GQk@PDqr)* zem%$5b`N7KyYRAAt+qk3HOfv<nRLQCy`{-$yb6^K9yYbTzu--h5;l3U#hQKud#Dd? zyo4<ejWIltz;^Ym=m<NW?*F^=_wK6R+#W<%^b+reO7Ha2JB|hRk==ILUkmK?w)Y{& zu<N^&)LrMjl}nE79S?0(`Ho#aV=_~|bM^99US+O;xr3Uk2binmo0zNLgT}Y#s&*V% zzrpwk)-;Cdi~8{)^!JV|F9bTcmlzB6OMO(|1WUo#2?kwYFn@LX#)31!U@iPXZv^nC z_b1*A{Gm@Vr%!@|!2UaMVEVBk4GeJS-nPTL!6{VKufP^AFfCg#noGfzfgjmG3*fOQ zv@3qOy-s<w#|huGfp@fTL97IOmi8;{RT#er$`)LivNr%LLA%grR@*dojAvjo{X@vP zFJ~`6Yj`0rzKOP;M(&|sKnF#8yWXgB`fjf{6JGrE-oHh>#@&Hj$k&PIp^Y-&6?AW6 zH;hyyvtLbn<LS?MUrPV}54iWjS!v1_uaULe>M|b&A0^UXXU%?n#-_0DvdE^$hT;&g zaCdb>@%gIS7VOo)I5@UE@lz>J_nmHBn2*--oz?l28Cy3}Nhh%-!dnwPq>ZNsy&(OE zQXXs3O5an>fm`mqaUA<3p`EqZ%_GQip>I;5-BZzoYf?*jyK||3FcydJxzxYX*pc@o zbI)CP<tgE<^ufwIin}+)i$yq&cUM35jbiyDwDEx(cU6pSx0yQWpQ&$tY{a`nn>4<c zB0Jx1d%m&}Ui2o`^}$%o(_YivG<ZdO=Go3cUo?%~rv0=jwtiP74(?WXJnFBpv97*u za-dO4#p=_Hacvu7jbR(sl=8uN=uMC-*&0u$^K<GRpl-?JfpNDJ+fJS6c8Rab;U{=^ zNc#KY?<x&v|2n0^7CUce?OUAbTd)`!YcX_K%lhKd;A|<|4jQi}=j%TdeJH=mQ<#(g z^}x=+eEM(}S)<EXDO`6`2J%1p!7rzN^aJf<qLsdszVw3z^j4&UV#-t-fDP!LeZhNS zCOm;(yf5RI?Ka7m)-z@*U-wtmXGNFZ5!#bXO)kdfL0w(cR>8mrf^zrIdBY-s{;qT^ zO*+vil5xqO09UGP(FOXi@+Gq}Y26g~(aM`=jSHtJ&xPn5rnH8>FmjUR&`hEkOxq33 za1G(IPteO+4fj#*j&eQ^?VeAukB(H7r}n)H?W4$OgMG9?^N3A5t$COKYIA)m)GIaZ zmf!BP{HD)pyZp~6ZyuZO{10VhVZY?pJTy47{%O*#;o`P_!db6GI4i(OS$Kok^-hgF z#N6~$ojf)kxj)LmxINJ)8;^G@EPfCEBlJ78>4^Q`8Jmv0)7=-^bj&a|G485rj-B9a zy`}nj;T_g0a-Vj$h^!L+hT(tYCc<;+(Hb6z?pkN4OLtJ>McE>Qzp$bhr{Ko5*M)D3 z$q(*omF@9ZYIk)0hOa>#0lfY8n170UkSE))>A;<3+y1G}XBwj*9q&HaGC;wM_$=lO z*GYZi6^1w|Jim4jX3O>5)OaPFgD`&AjXR_Bf9SV)bSGxc|8sdT3mG5rV4%IrtN1UP zRPWBmqp!<6v~aigH-W(z|6BQwUN!s{uX=#_wa?eD<pYdyww{#{3!XKWTC1ufRz!c2 zGSuhG@dK1baWTfm$Q@1l3``lGi+BJ|4t%qFCwO$i@3<CwFTj|1U>fiB_=R5u1M)M6 zjP*kSKSlm|v`PGgU;kIdWh;LejEi9Nj_QBqf7s8^CSv`;%kdF*(brvb@T+WOat?0P zeHDZAW$#jF4r8}d>&?W8e;~V^;NLf7w{!h_4g@wkZ9A0G1+{H<N{6_QI!ztFfWP1J zOD}xD@*6vt>`Um$CArJPI!cE&8D-zFh_2NtXsFhtY#iQR&95BwC!tMK*yKzyrp#|e z^1Vfjr}PJRSY_*egcHapX4}(%-?qQW-RVZ*DZz?udsF)ArVp~cDS3+V8{3=GkvCz= zFT0!niSneM9^i)8vAg*N(q7H(=F$HJoLKehf34k3>G{{%-IN}^ZFf`mLPEQnv+(j} z?P_ucd#znfctIiGDumMvV<3C1lAnsNm18fk<7F@MQ^ERsXlDJ@@|Hx?h{vS$XU6se z<dH2(>A<;s)fU~GlikiQ6Bp=2l1F=o$zynK#zyB6(kU<WVY|vgMQ6sYrF4{}iz-@+ zeI<_V%(~AJCO)_7&^<w8M{_TD$*xE8k=nXU8zg@lBd_2Zo<XB%YVAu#rkG^?vo?c$ zx*L2cUZi*d_C5`bJR@rrzPlWc)5u|Ga2oge+Tqth^Ry~%26z2C%HOurcJ1T#yUTkR z(_{`FaQgM-a6Oli!@0bX*@a9`<pwx2x!+%ltvTZt-Liu^YUOp^!I<rzlMY%F+AWml znEdjK7BqhE|7ZD}+H*DeT-WQ!=WO}fk0X!U{qHD`lRkqPSJ4))FP|&MzsQ;pOq+bd zp}=hXvxF<`|NIyBMyFW4mvtk*#;YS4%Hp(t3YVC0TW)tJ;evVd_NaplPV%?l92@B% zr8&no+=1*a!<m(G-M(UZ=Dp=y2!9FHnGE0AHE;h42DM*`PC=(`<{jp-D33euF7b*2 zS+&tY5)EPgi>B>ktW>sOJfXV5b;hrFjivFM`i)=ppJ#mJ*Vw5HqoW}mRE-gI1$s!u z@|E6V4%bU)|6Tc2<}X|8#ng2nS|7%*vL(MZe#rrZ2W-E6r^k)t*Ct;1MGqOjd)-(d zzn=BaeXCjNwLVO|{GwrvKO3zN<JVY<J~e)&7k)N=^JcdC{E7RERlUI`{hUC4jXtnR zw}m%pB)_)P3pTMc@<+-ey4j?a{6aLc@eB6n%rATm&97u^#KmLK@^)IS6XU<!T;Ct9 zk(o5n8u?kmyRqfI#?DXOY0IxXYL9uRTx&^tnZh+TX3YpbgFEqBG|^hod+J&*ebIVp zV!h<=4cCkEiq=&>0~l64;O=eUR^xX#FZM7$2EHWY(wSOoM(-oXo#OC&StrIOziE^1 zpem2rWa3=vsY_!oF{SnR>oYnidLsZe+1I@3thxo`D$~?Yz3ryYCR|_UW9H3y)%pDh zr<~E3`ZPu+z5IFbkMWB>(D*v=niUo&J`OyoPVxF`-<rN$yZ(-Oyj;5!))wJ9jTdtl z{|;&4KhME!Ha%h9*L9N{D;dr)Ez9pO3vM4>R4kVkjryn~LqBan_Ed}y!s`$%A^wNj zTPy30q0eRdxgOd?bcxbmi8fJOEj|iq4`9-!K_Ykx#w`Q?g*#TWy1$WJS@lq#IXeYo z%RFq<e!!fg4;AnZfuX=Ax9av5g*2$(M0&v{&K@6?DSR*3HFXB?5%q1+weaRx%L+4f zUQ3;7zsfOZKf4U26;DxZNK=mdYU3(oYg&s6S6FQR;;NG`mRD#Fnif|xd^65s*=}l& z_13}XyGwHU#_&#bm?x2gHvo*a&P#f?l5Tj%vsEWoENA-u1p3Z7KPRpD2-LsmmZYcs zA(J{$-E7sL$<DS#d!}e?*>o`NODKO1J2&Ky?K;sK`<Y@Za`#5nsrtkpL3ZC5%8jG; zkw<5tIOoVZ+E<@CQ8snfGsfz-;8l78COjA)>D^_$xYpX0`XJp;w{vbE+^xmxpOYt6 z6CNX+cdX~o)|z9DzvfDH>VI9T6zq#(8$!6W=hf)poVw|?dN_jr1Z8{}U7U|JV;`bz zWacfe10CpTWB0lZJ%?bv7PWXT;{lI5ILqiQau@xPFaG*SMelZXAotSyTW8myvk<^e z$UhN2(RyVpAHP7{Ih@j5#I;0aoxNedf3AI2@8%qSTkl5kf?>ng5lr;aZsXS)2+t7_ z&j!EE<Dos&ACB3{nRP#xhZE{>glF6Y{Z!fNhsISnRInAJT$N?&MYea|u2=m8r?qn3 z0sQxnbf{+D+?suFYbSVs`|XUcd2ef;^UyhXRMC4|#4|QYTng8L+lEv9cAH$<6wpT6 z-}u>c9`FY9tl#W}f3y$01DvlOIJ7vA48v_7sdTU7%_R2jr||bg|MjLX>kzy@m+y+s z(j5IfV_#OhY4N4axGJCUuJLzaOK&Z<GcP8wqv~O|?=9RJ$9_|>#G3p7cAS<Dmt}*t zgS#9}*y9^=^W_wGZ)892FyRNtS6Gkji)4Q0?zpXEmvpCm*=61I3}wgA^Pn6TyHjn1 zKSBOxFJ4(jnC`dgzIt;hURlV!^dZVSLVT0%Ibs(`{Bc`XPds8<pRkn1hAs6xNw|Hl z(>~)E+qI(8>@m?jv6JK%ztRqWnea2%7`@<NQ*<SAYS|d&4yNwVcIti$V>i5xeH`0{ z4mL&|!ZL)#uE&opLfIb^f8LC>v3)Ckj$MzjeJh@h9d2yjif?9zr)ZbWgV)^}-77Km z<Y>oM#&=s8o3bU^!#<aHh64MHYc-D!^U6GqJRQ!(%kY9H=wqCI6u5)CL3ROUx0XA& z;_;Yr`zh073@(uGMaIPe9xjqMeoH>EDTsbRU<<){|1fqKhl6(-Ox_EmKS$oPjF0Y; zUtFbpkuD4N2gN5cX<yF{t@wB*?d#d06)(-C)tSMz2P&JcwmneUbhUL(Wz$u6e@y-n z`cR<#{kNR<$5);9UCGpe{Rem_PJP!L-D{<vApHT-50HN93h6&%rJpAKVbbp)eenwE z@3YcBM*1g6pC|p1E2Ot=4nKJdYb1W!KT2B3pFT@jl0P|-{K@q5IO$H1t`w#F+!fND zBHd}yos80b{tD^djGf=S);sWE+Zukec7DHLjZrt_lck+K&tR*#6_|y0yLA=oHk~gU zcx?h+W#9N`t$Z(&=8Km975ujS-x%jABmcRa4)Dj=TeRnxG1Z>)W$icY2ihaHg3l#$ z`Dwyri}Y9c3fJ%CUf_K2JNeJMH8_69icpW$lxb{$LR)`7k%OLn1b#*HSY_fSWUJUz z)?4Y*<%j$OD<1Nju;K5v6v|V_*zdq!vVXlC8`TRVJD`F6YsOvrFLwFMa=hb$yd=SU zsxJjLKkpVF^Z8A=ot1g_7R$jM6Y9~vV)E%dIlaNEb8OE8*vNRDvHB2wUXnh*{&z?9 z7WQ<rkLS+s!4~U1!Fxk(&_!|Qo-*;+V7;fhjy!S32_=B@Eqs&Uz&3EW@+>b6RrJQM z@-D}gzux)PooZ;IGIh8&qQ9VaV^=GX-M<U{g*wVGdo0%kv11vQce%3A18U#ezK8bQ zUi~5emny%5t`hStIz;?u7y82Jc`7c(_-Gt#I^`PbJOyo1&sTRA4NO3T1u&tnU}Ao5 zO!R8|v!rRsja4O=yoT>FzM?72J^YL2eA7pL&_AL-WgDpVpQ5u1=YMEJ&cNVb&J{)% zb_HW@>$tku3z9uH!&{b~>nk4|^Iu&k`Bq4OtB-15$YT$~GK4i};r(Wdtv0PL8pPxi z?creK$oT70;uq~?Ere~7KNHYyVVOD$2Q*V8Pu&JDK>RYjXS4}D3B6?$^U!b9fATsd zcmwDtY)kUKQR5@rGuz|0rS^tz8|8*L>mZlQ!y}H~CTc(*^f~&!b=@Pr;BOu_S~el; zmVVy%=pSQP?a3_g1AR%pxrwC#-O=b2d6Ou7S2jVtqB9hx`K^7ENd0fl%)UvKTla8K z*J;X^otPnLI=wGa`yLVV`u%6q&_w7<1n;q|7?KW2pi85=?6-(S8>w!UBN|-siH=EM zZ{Tds^OnZC$w1#hY3gg<AnHd>4x>JJgDAs)y$hpvauU%SM0y{pw=aB~XnSU<zXQHg zf_CW*q5=ND-Wx>H4=`i1Ir~~2QN>+ONAw77k}iVoY4qlh`7;-jyg}51UvCiUK8M~Q zLjU}{`rUxejn<3gka{0T^t*ImrORV<Or!&AbTUnwx+o{q$qeVu=#83qqlYORXTqd6 zD*ju&-tS5mU*HV!40d$U&E-FBP`k}rMjBJ;OX@8n>7>PZ%SbwvddsMvwhG?#mXY#F zr&M)3&l&X1^g(49y;9}p?o+$w-hR_ae)Uc9_M1iuH+`&q)95(s?<i|#J?$*r!h1yM z$LY-dNhjO7Ja>$@d4?*;!&;VSd7~%CJF3}Yi&;O|wQ1kL8(SOFW0j4o&_zQJtP{P= zNpzXi2K9GCYPb^P?HP@&-Y8lNtVyRwdZq{B@j34jnRjK9>Fa&%Q-Wo!XOx>B*BRC5 zb8U^**Y(t|_ogoQ-q241Td()tPzQb2*qC=&USZ#udB-VB-*Zn_{|VeL_!68oaXyqh zPjH%No%T7QUQU6#HGL867#^1N>hzwF-c1q@Tza<K3G1i5(zDeXl%8!bVbZhh#gEQR zpl7SGGks^DiT@J#%k*7)r};k@cYqIQ6K^I3?*Qpc@Qj696o<W-^UayD$|c^&Y3BW# zOYEJF2fu;0fTUNccY35Zx;%QTC+98oPd=?P8+xIn)tf-wr3Jp;#hK=P9=#QIIX%Ay zXKyfn(y253(EY4uOU2+lAl0k-rkWDL+dFy#RqsqKFTume6u*@#E%m?68$8FYy5DG> zJ(OeDi#>=x5^p$8pX*A+N8iZ1Kz7^IF16?N-UJf7YToR+Z>MgRwT=AdEuhaa2R6(N zK<9iMnA+x`@0tAZ-iw0fZ2d)GM{DFglqGsWKYL#d-W7sYa5Jn+V_UqBeHQ)^IBht; z=FmR$B1dEC;fZ*$IC#3_g*})E-zVNh0vn*Q6}$Hg-BjE|ntdtkj;67FD7v<Ry)D5v z&R6vAao}9*UU(9``OF|^<oHcPW$9|kW?@|f+oHd;kGTiODr+6-UWPC)zJ~Tw<5xQA zy#+SK`5#Yv<sGsw&VRkfQsBSxi0+uye+OGT__3`7A7>2P;SUF8%ifn@u>kHECrmsH z=`#&oJIgysvW9J*!}xnR%hDHgW*R5ZaVpet-d;R=-ag=~J=oqRZqOYr7oX+*7I+_r zNhf<;M+k4?44lVyXsly6uv2LIwViTuq-!Xl3r9NHNA9D(JhXcgcD?(br5@~O?I2D3 zZG+{Dq-nwyVP5BU&NB9SdW3x9EvT*ViQ@Tdrxu%fWNX{jgKJ>!G(W!xPLb_mTPIGo zjcvX|%=x6!HHvocBu?c&&0a7@n9jmBPeOLKO`Xz%l&+_E3*zfIju+UFS9}~BVVZ~2 z^vC9%oS>g2`f>7E-XCIYoCJI-#`YBHbdC#b7cy7k;h1`k688joWPeLGwM_UK!figl zi}-CmfQNq$AAmA0Q0G~~<L}`dr7@1m6MsPMm7J|Ug3%t%D#G`Ao73QX;rIr|)YudR zPsh6~yj_=uC(Ig<&6kiC58n*c8FDTiz6&~Bx-?<D_CKv}ok<jCpFwo~_yKf8k~HiS zt&8!Sy+Lzn&#mUVc5cThb4k+7?d`!H^^Fa4-^OgciFu&SMaF2FF*>X<V*eh*u4r8L z-&j{R4@P<@?Du8xQDBQ&eRlXSof`fBH|?kNBgXh?Of|Olo;F7>+?;o^(RoMs3LGYz zsDJY#XajWHc3Wfq8~oSUCZc(g{pZ?q&Z`S|`mcO&*8Z!;_W|Hpuxj!NHxvWit`H|l z=P9&LJ$px8cw*X0qjGfTy$(I(9`;(DRrUn-sYhq*Q`_=p@hI&(^MdOEt30iZ9hP6~ zJ8${HuT{O<tF=91g=@~oEx+cxVEJ{9n6Ug>!&8?3K=j|(pO)R-9f?`{xti+%%P%~1 z(aQfa|F^GWU4SdNj}h3bZbSb`x>C}ClFe%A`1Rv2r1$+6{rFCT|7Pr^^LN@R?*Ym` zYx$+~ch2%_94_FGGv_+<svMnJ1y>oZ3*>ov1IdmzYe@QGlJ_mO;sukYE$EO0_OFd! z`hL*u;d#~EuV#M~Ogg}(@Q<4bVaDF;9QLDNuiHIVaVBQ@FG}A)oc24lSN9k6)?R3* zn*D8JekHV39lqBW+N+NCI@zw)K1Uw*Y;OX;$6I-^Rl5TGdZoAaRHxuu^)-=Se$8o6 zKWkEc!J7QScV><1&aKw1@SctHB>OfvFV27ES6;2@P*yT`t^W(-cXj+X4*uiKJ`4W| zuh!x|)g!sT>H_x#b(y-smw{h#;K<;=p@)oqT#7Xc9Urvy{|o&%V?$AGs<nM68cT3v z^nOi0^c78_^R@EHpNL>de#up3$2bK~L-s6}@RiL<=s)DYt<?ly*^Rxx_{lcxS-!IW z`ls^q{R8>2o%xvjd>@n_Tc_y31$K(xr7!DY9`&j|+2x(UZlP(P_PlWZLz?0>^Ur#W zkw;~iJZAol-{szL?H*`wv`Hh}ipoe})7gZD{HbF3-)tD5zJV5KD0j-=e$#2*ZNEGZ zUuB4ouRe{CzCik3(vM#yz4-V_KSBBfr0*mB)K${o7p0#j{bADglfHPB^y1^I{3AC( z)3~So$4GlM9{!W0dx~^NqjaC6zRU9ZNq2&Dr6}F!uaItpb=gfjgE#+ZvjZQ!=UDg- z*z57q1&6widL%i8U10j_K(j3=Viy=%!FpfNmg@wvJklPG(w1t{+BAjA@1gv2E1=P6 z;~CnAt%R~8oBWc?)X0~V{$r#+OW7X%PnM8ls87hVbXIsH@+_6{KFT;j-s4H=e#$yY z-lk*FKD=Rgig@wa^`_YnvQ63T4dj2Mb+EI2igrrQrg6yYZNtd!w&)B4!>VJM`bD`m zEv@i2!g~lmNxQSE1No%hWi#^03F7oF+c5O1kxy<TEJN6p<dZ7*Rp_rSrQ^Twye)TB zyzJVpCw?veYvq`V7Y|_#@ir}~aNQB?cR14|kp-_{4aSP)9fV63JV3a{Nc&B`6rS5c zSupREMY3S+Wml2~tNiCE-;7&;-&yNgF9Ck%zuwcbW$#ZRmq=|YmY<YfS!utY+FC4s zcYUGKpZU=b67U=9ojWI!@L||HhAD6Iq4!+p-RU@xlehCud$GC_ydwK#?hRv=PyhGf zN@@O(pGxiV?|I8`C6Rg%o59HLv!cNs^jGu0iEo;3lJ6S6ZG2C497BHk7v<J$$?pLV zLW@-QZtL*w`S?hsC4HPXz^9>!xU&XsTjZSPe^z@{gZibuYX3BQna;^-&+%&>_Dk14 z?B4^=$b~oO!mm4i%`U=raYoa9;w{)yaJcIXFO~H7{KPQ#efJW6yY$k7aFwYzCyD(R z;#HQDXP=BcT~6e&AAxJaC2?)I*8DSm>HQD;w=E28+a4^uH{@>%_iJpWACq<_rSBNv zFv&VTtuhHyU!<pV^FlA!hkucFtwy&{_8nI{p*|iwZ}<@5f0b9-wJW--=Qx`X)~vrX z=H$40wH-Hr(>$B~)JbNs2f)1u`lPzrpi{Ir#Ie&$KjYeK|E$@o>igHPUb<xG?ILX# zZK)@{!(Hs}t{<)lCibRN9yG^pm-~p_>vWer==V$=Dl18Q^;N(06@8(${!L9CS?b7M zp$_D1bLyzK`XN~O-<<6<S9U!OQN6YGU5xba4>PWZOHrSa$gr}&{j$MI5;%!visk9# zDld`yx{n_5Zuk6frKhi0&0X_|ulaY9WB&e|Iz8Dgx`(%`CI3w3Pr^%i$lrhSN?>WI z(vp9Aj(^dNf0d^>f92L^%DL+w@dcZE77cr=I6ua*wH!;|=jGo2pnvgq!!gs>^x@A> zo;;~}G4ib=xkLVutaKr7XPsszof7xeXuH<0=4W5}S}zr>)h*I-YwTf+w6-R?!?m@@ zT3hG<!553x7IuPX))sT7HR869Rwlbwc_*%CZAWYB#Px&zvS=+K6KzZZ$6d(~zSI`k zpVYkQyb-{)HUB|B%-H~0R{Gc>Up8z57{d-ioO8l=PZlb%9OpyF^^)mA<yQJ~&)Wwp zExMbIo)3GPCmyqt1wS(fTBomWybamc3&7&mK-TF-|C{Om-*!Dy2A@F>ce`(OoEu&o zx~-hZ+~w6}|HKoG=9G{NmWuKDq-h|HTPh%C-720z3+1*5htvglZ@7XkQ=rF*4q&_P zO*_so4&C@uw^f9XRQ9|~H#Q`neM4n)-a(#xXE`?L!5^V+>T*-XNmHNX7#h##S)<aU z(s)*b@eS8gFrJZYaD?$pa<?NGOW@kc?e|~3{<iY3GJX@-50n0`=2vUyvy98RTUn#2 z{l4yHOw~EwcRPnFN#IhvLHF^YisnD}!-M{bJ>ZP|gO$mJac|EF-X-+l&6DQ4y<?So z{+v8H&TW}7Zv{L$C&#=v4`a{!q~C&DgnRJ|x0SB}SGWg9DxYSJxGjTTL-Jnlm3yBq z=dRi9FWElf_x<+6e%k={Bc6NMZ!BV4J3Znxm3De=@na$W&3&%Yn49N0eV^yf8MwW) zxzbds_vRIg<-@rJK^=Niz6d|Mcjv?YNa?o9%b&lkT+Hb{a8I>Bn(?A|^M!LaGk4O9 zlx;1uXHIy?t4f@0nbYY{bb777e}8#v{x<qo;4XckvPL|9%KxhOqaW0<SN47MVaggm zxA5F3cFm^GZ6<B8v@~ePHrjBQ|1s~uYL5Q}@Xh1jU~Je|U%l_Pa<8X$jGtRWd$to_ zM|&1Va2(FhtPG=<c>~4++^u;-r=W4d`;@PGRsKa_p+K5Mlt%qX{>J^~$A++z9>I(3 z1>3kp|Me5>nDbs>%L17ecqGo+YGv=1-Qq@fUA~e<b}AfCI~!k!?)yvrsq=oEc1uUM z0Xz;qKL2MMyz0O5HF$nTZ<n^aIcTxIV)<Q^^91;-Ge6<K@QHlI;m%&$gzEU2D(e$| zd3c9OItm6}b$3<in!r0Tr$>ALlC}s3i6-b^e~LSIDSW)%8S`i_?JEwmh9|Wy`3C!| z$~I-5#s0X1{v_+IdJXscKf54b+5XN!e?EQt`{sNl7S%6ZS?!T3r;CNJaWng?%GyNV z6V!hVc3GZ4F7KqEqn8Z(M+3S7U3&hX=KnIjXZWW0zR0(O?^(X9`CdRq-?@4?*fVSE zNTyh)v_FyFi!2wqAw6{2bntr0>Wk7gl#12Pwqbwu@nL@nIO^3nWhaLH23!*^iEG0x z!7an3a2>cbE{j{18uk+%!+tkT`>Wk&>Zz_-llRx+*5fj`F5D*EW}IN+GI?g&7Nc$N z0B1LpXh)LrRTr)ar?xJ`rEuqPmnjEYB+qzb-vHNyOXAvaOK{6@DO?9`HLepUTL^1# zYjKxr+X>p!;T`g)-6n4k9JVHv_aC`X@RUBC%=<^4#?~M<7c{PF&+^g#c6-ful-WOm zaaSMO=+lxCZKwSSTmvqNGyUq||7zT2`ZlMW)fyYp*=4lh55}m(7~wi_mnr9U$LMn7 zpm}YgzxMc=v9;41Iz;f+kby>ETyD<7|JN9#C?iAvvcrCixMhTIRU5rxxtQdfP#UhJ zh~JL8AxGXXYutb{Tn^WZ>%;ZqcHjgT4Y(w(4Yvd**zClmacgjEaqDrii`<3VgxieE z;(Bn~a09pw+LY(}Vuo^Q+X(;1ondT^4Ws`#>`&niq=x-zzD2&r`JTX?<o_w$Y4UGc zN!hq8t{c~b+q#9e^WBEqj_Zxl2fqEd0i4&zy3f&{jnt1D!Hwgl$XDPyfjjUS>Rm~_ zv0?u(F5x|jJpJ}y&45?II?y_$aNV4xE$46-aTiL%{>w?$x5F5_<inlBUBF$$y^MPW z_bSd&xwr;g6E2Bs!!5xr!=-Q?xYf8$TpG6qw-&b^m%(-6MAyyPJAi|0SkE!;oT;6^ z`sreI72_N8nBQlS-_X7SZEYjXPo$tj8ON75GCpO-=h(1cqU{>{&Q`{*g?d*pek=Ia z)|37E4}mZ6x^&zMmF3=pl|a7@`%jKD<Ub;LIdM(dud`<IUV<?B*LeDlcpc?D@wADy ztp<lS5Z+lD^3%8_nIYhVbDhJv4%dcThD+fZI43luWxHp{@4~+cw;7kkb>r4kRt9I< z+ZV}Y(%43Uwk$Vso~Uz1&=F2n*~c1}dn4%QjaEL%U5w?lUHW;~5q=c^YQ80K(L(kz z$N8)?#XjvOb55~2@03y-oqdUgoJ$Mzr&xV3`Jm@|#p<KW2fak9;NSiZ@yiRW7xk~; zcV-HH8n>48YqACUR-kVM`c|NC1^QO-J8)gNO}NdtEUp{3#4E6-3aqJu-^V;G^tO3! z^5?x+>gT<G2<VB=dJ3a`VYv76Uh&2}|8w5csZV&a8(FKD*Kj*La_D_0#~iYkf46hE z(v+N}J(H|&=t5|O=@lzIbU}FIOlR`o%pC65*x77lY;-T;B>UmXB+d!X#0mE4<I(>T zU&q<z2}Z?}FOs%M+F}&{SoGESDUI48od@mR-S0$yigt9rb69pA+w<hlkv~WNfhb?U z$&buN_%iOW*E9DjE1)ZACo~y0;|}>9<kg+ojwp}Xxjy>Ox#_(2d7X)W(}l9*4F3dY z_a|{@a633B?<f2O|9_WnV!7kA;eMO{7YNh(GkCZsa|ruu&>&g(-|&JMU-&M==qYKO z!?#Z*2XTRmHPr9qzyaxfXN6ZoS_ocN3VmqkpTB|bF?ZkQkzf5%I|tMlejT*IUi$-_ zIeO`9Z}zo(f_?A_n9JSn$3#QYE@(*6aWCAHr)|#p?eC{ev~&CWNBmx#=-4{yH1rv~ z@b<P-w^h=#LFXRPmpb2zzBFU^mo@wZ!{@k@^Tu1DRn6XL#%c-eb<)si8R3yTs$T@A z@>|sQiF2Jf&PaXCYY7~c-ihAt*tvRV_*@fX(~wmAr`U66b#|uF+x!~&oeVVOI^=B0 zk;-E1r)%6yA2@rpPjHw10^>i;Su38tm$S`~_X_hO*@b9a(`E<Q=_S3&QyEWD9=e6q zx}TV(|L-CGDR_Y@bJ{_U2>ix4OSwtbUei$JL~?|6A)KnVg6o#$E2m5BU*O;q^kLDv zS!WjpD~lMLMcBUcNc$piaF#S@JoXjRU0~h4%(@Kv5Uh{ze-rByNX2G*u?(JS7hfty z9~zuJXRqO$Ao$tF+7ay><W1`RwL|`Amkw6`F0ec4RhPNpnspmFcLN(r*R%q>KtI<w z%ynu3v|2RALEZF$Iuf+e+~f9uH!p<)<~`scsEaYt+cak)|7pJe6F51QImF(5$bW)3 z;fqA(K3K85wdsUosxg%RC}kE%S0G)1bPCgYHFzVzeEcKj4d1AH*oXXllx8Gz$k+L5 zknqifZ;!&y5!RbJ1nxZqJ`Ky$I@MWz`Mb3z9`X$?*hIL>7EJfCzRd3jEV-=~URX<9 z2KSG^yzs-ynB(N|zlZM*zTYS8U&-@#HETlW#yIm8gNNaA9*Q}|VXX`4Z`*#YYjdtq z9@53ZA+2tZE<a?}Qaak-0zN}3l<8`ni(e?bs<TiGo|bUxk+(%~#Mw98yPbBe=aYm} zcXY1ZQl_p)%{tdtV-euEh_|tfb*uVxE{$b)|BL$K%#Y^D=nXGNCv|!9cvW`mHe_VS z@RQZA_6>czv9I{3&fbY!@zJm52EW~$9;$rgKJ40l34Ob)(%pfs-%#Zp6GPwLKd;`4 zPZS@$lp7`d&g!Lnp)xO9{FeAZ&E8;za~1y?H_BR=)Bk&_3-iTC-;p2u_D4P=oN{}0 z6KC&c_VvxjIZJrx+vVVwkoQ=QvGR(K?uohHfgPQmc+o$#w^;sgH|>Cjl1`E?IizzZ z?cGv+_{-ON8Su^1eZ-f>D)E%+yGw7red`i;4nDF?_1#^4_^xZcOS+HHSNzt;zKITL zae@EQ{$e>(T#63ZGt~pXv)WtJx71(t4eWN6i{)E6<Lqy2^y+iizU+IjvVMYe+%v6* zo{}xh`rLEXjVn2W(+9oB{!slqZ`T9G@*}S6ZJ^#E%Gf~q4WyUt&As(8FAcv#bv(Rq zq4&+3i{%@rYxKS`Z@hKTt1s@Ztj&uLv!%K}9``b;qi?8k5_s$S5cObRFhl?A>EEUA z6&Uw>s`c3iD^m>#Z(+9h=!DzgP0X9;#i99j7vVP~(X0I4$?B!w-(7i{cB#HNI+Jng zd6u@pzw_!-!<E=I<CTTZ-SlI3aiO>SiP#s$pfT<$k8Biw;pyt7AN@sjV)H8R(v3rv zIQ;+@KPp><m%vq*ZhX4Bu>7DGr>$|)#?udamzt099rEJPYn)lU73?uapUCV_Hq1&_ zKk)(9gm?m<;>)^l>2p8xoFuF*H8I0eH+r@E)?e!_Pamsp0|(XvbIa3D^Oj7glm0-= zc|M`N3wZstnA6ysS?X_3Ek)OVDQ90~s7|PF+r)p;l<$r?>qMg{UT;H4msa|<T}gCM z2<uFZ@&>^u{1ombM)*D^9G^!2m^xo%jk(wa2ky#!v`0MTuJ;WEdYDcIyqp8~r;620 z?;GT-K3W;*pxn%;zqxDF&*FM;TX8wuHr#exFRl;QkK2LE<BGTu+&Hd)o4`%s4&bJ7 zy}41pd)ugg7^n6A#QP8V=DZ<X(?=g(q%XgUylxfk@$h%8;_aDac-{~m+R-}dKh;8g zgtNY?r4^&Tdu@?-->^w_>!^R0cAp?@;(e1o`kK1e<0jbKHD($cc<n(Ld0RCO8j~+I zj|Tf(iuP>NT$F(E6t-2#<9Nb@!_ZQb{{O??`^QIlm3ja7OeSFxQW#2T2TIETX`8lD zrzLIEigMGUMu|FY*=}0Vrj}OfH|wS=tLUN(Nq`j7IzXr?i+0+gPpr60U3Bxf>2^X< zLq&@UiY?N6CNphBbXga7QBl6{&pqc3H`BCheV*_0&-cmeb#mrDzpm?C=Q`K9&UJoi zPjENz)9m}L26n<)Tj)o>Z3X7C%-X_E>bPqUb&NqXa9`@IrR_J5He}Z3LaB82EALs0 z?CTkwpIMB*c{K3m^hn&{{%T~D!mDY&YIKEQohMHdBZt`AaLZfP=2p>e@d$n43fhZ& zx@Sc+lze}VG=sczzK1u@2Wn{-cw?|(t$Q!WaqjbOrcL|#KFRML_-?-TMD9Px*G?S+ z?bH#tEuUmgj2+F5Z%yQWP5ds()cFMM;r>m)`lj~#i*FBHzqT;MxelENXl=*#X{WQB zE6bd6WSnTa6nvk7|4uJJe}#Uh7d%6sduBv?c;?JbXICaBGN+$dXi6{6g_E>HBAvY$ zU2=l8b+iTfFM8;%=B5btTnijy9nQYXyMW!{v=Tl%ql<k&U4<(6<T$?0Rvh~<Z#i7w zRoGwERXBuy7?;P5;!bSsDxAcfB5i^)bq8tj{lc5F))kzM{!CXPjH`Y#`W&tX7sbuQ zO@n_#bLrMqk>VXUqS05szn*cVCs(a=WAQ}pIpzzDvsq7;1TJ5zF(6w;8?{r{Ah^PF zWkL30Ey6x|5xT<41pD$M$c5wutfTkkbpA)<qW1fL+U~w#L1YuME}i|f)p5g0(oNQP zdpeusw_CP@9td6+wRhYg`*>NrJBJSTXiJ>4L$uB5On1&57a1eU7_$~lMNg&t$;rOl z=~z$BF5}Efa$@14WEc6Djs!F5C-+d^Y2;@r5Mpe*b>tc9p!<YRTkNT4%&oAB;~MS! z<mtG^-J3=j!=Kcdkav7Aoz=LhG1F#m>qE`;PM;lfZoINMW=*y`88aSq?_gcXxzh>o z#$=6G8l%{&KLH+@z?jq*nC(2Ydyb>E3ccmEW?rY$F?YRFY`cz}O}>r6ptF&2D0mrT z?RA<b-7MaFQf+irAE9lyvv9@|XuQ-Zt`GE8hMa95sCUF~SNw8quBn}KH{da$75l=% zb%Z}ST1DU2-LG|vdkRZ!;?;f@_SiQwAICM|=HqPKBGN3wUyf_Twc}Rc8YlJ?S}tH- z{tL>ug1P$NF<1Y8n4|wab9CI2&-4^p375=K-&0?c-TG@6Av2r@n8TR09_ADl{V_z_ zw1dk@?y5W<DxNKq3^*0)D$o#BD`^ACh8t;T?Z3ZqZjlz70zpS~>6l~YG|=Q0XrlVB z0=D`aw9Bf#y1Q2VEjgmH_k}tN?4_zwoZ9+nbWok~=pvo+h`+>ZNr!mouW#vetjj!k z!|rr;;SKOx{QDz4=qr<*%t#mge{K-n1D;v{pDjQ)`2zNb1&q(V=qB4}SHYQ(S(A&A zZi1b}zL0)$g4ID4*~brz3GI7Eq%RB&rL*hpbappo^Nw!z3-H6~H*vng=m3%%(g9rE zg7RDFH-Ti4?^aPC@mp|qhof;?YhhYH7X8FOo*d*%>x}jk_Z(5zLp2W<_J@k+<tnM8 z=mS34<rd>?Xied-q0@l|(vXh+mR;fiFC*O6JF9@b5;zkg-41;;yEMUhsswKqWH{Sp zvrd-obSjeQ#VKS)D>_St^*aaKP(->)(vh4^w38lKI{(GI-?`(Q4%XGMbr6=IJ#?n5 z!IB;J0@uDOSy|JLZ4g^sEQMV#ja{%6n_LEapo6V0)`?z&{U2Yly@h)<81I~qOl}zo zwXb(ViM0-AW}Q%agTq-^CxlLxpbjDM3Psj9hvA`B<O?nAa@sQ*C%PQ*;4+6W@DraL zs@aB}ztaiX)P=KlOA{9qoKR08U)xhS*3eTJ&G!_pMn`FH<y;8!%*ph#p3Bx1+Q40U z!Hnj$xhUhT#{XrPu5-tB=}613UFY&?)aqisTx>7iq#XO*!W^|_3XXZH#`<at9f5JV zhVgl3d@a0;P5b(Fg-z_aX(X*Dx8rxR?;X7Ng^F_?{XS)WBm1)JNH5;d9(U=B9egis zEskZpqkZ&v>m!AKCvKGa;@|O|XFipW;g~Dt2~%EgzN@pZdTVD7@q38(>|fG7yzdaY zi1G}Q_d}G&8^$BOq}^%C+JP@ySu1hdDQ6{dy(TW@#(l`SjX2GVmlEf<fmzl)&dtQF zh(E%Zh$Ftu<drPiHG?<M&G%CLcaYYz*;u|m%~>^Hy_*SYyKk<0nEC8K2C=x{dvjjR zbv5t(72*Gh`vWdb*iPIb!u`6p&hs4aq<-zG!m%5rd-ox${&K|I!(z3jv%S~WI{(U9 zZuQ088mn*b$}L52ksSIa--)gIecOochYg{tFG8=@Si$#(CVuPA8hzjPmaa{)SaMTc zymQkJh_f8-Yi1vW?xNJ)%~~H1%AQNV31y1wLDkq<v{&Ol=m!?*LZs6@Hq0ydU0m~M zdx(AEU*fJf&L-6Je)LxKr0JJ4SE=9}ODp@>FWq#o=h98z8ijW^A-^`x?R2^>*;0_q zD%GF5uZ3^nW#QY*?*xu=%kQ4QJ{X8F&%d(6YCC^zdG{q-rX8ENxxD9^Ez{aAT|2Fv zba8Aeq`{`ho_p?tS>D=JXkLasgloYq#kJy=;g;jt<gi06;hvuDxRniEg?7SL;F7pB zt_#<V>%paPy|_NyHk{_c;#=)q3$mv0sRe1y7oeBLx(ag%tBIlGV?SF|)>U|eaGKjy z7@XZz2oe`Sr;pr;{sxZ8d0mCfm0i5S)rD>k%xkt#Hu4z#{>`-M89lyu4qox-h1qWM zNk)h0v%<qdr)BS(n|=xU>)^f8&x>)MAA-NGgGQ1yZv?-S)7P^1f_V%!<*Cfgt;?Cu z@LO^q#P4nV4&$fstMRwvNAUZZf7Ad&a8;&kP%2aTYU(x@qK%siLF6iPT_=!wXHNSg ztoU6y-aXG%#mk(^SkSd^S&aMOAHcjkb~bYP`LZjrrbK&Nk@S>*HF8LMj`!0?PvFZ& zCcBxt-i@E3e`jJi`gevn;idhN(lvDVn(S)2A4sx9ak8(=#<iV%-Q?>gew&G#5TowY zN3zAOA9eZ(X}d@#`Qq8sR9D`Gab?RQ;uaCN$mD7A!IsTieI{<=>hX0qfG20PPWv<D zf^5WJL%wwR<ck&K&1al!Y5zu??CTAD|AgO?GyjBN&$ncXXA?`skt5*W102oeE%rNl z@?-+~Me3@#&iTj_z0b1ba^eZo9H8wI{bsHdTT^J~cNl*Kel`9|{0ROk{2Kf&{F(UO z_%Zw*{963fHJe$_UgNIyYV43LPPTCQUVXhi7oL4?nZZ|b*u~fO<GW-e)ev*A$3J`f zImsMja&8HHTVoY%w`07Y;9XYgP)?i3F6V`N-@?VS*J&-oPp=l>tBo`#md)MUU&MVH zBOB+=b=bUj7Old-x%VRWj~ZM;1{cvz_5APZ?X{EM1q>h;%3{*9*yE=@^sL$6acz%l zpSFk>4|-*bhJM`LH4Vy{;Oc4G``Cdkp1A{S8qf^82zwuAs9kSDKVW|)dWPD2BEJ(= z3YYy9nE_1`mv_4D<iYal5i#voJx)9R&>PQ;t#u`|T$wnt#u8}Ne!t>=Os%u9k8eZZ z_GGT@x-A8*F=z|}mnVc%&`wVgE|tua1NIW;$hudfSpQ=Bd))NwEn?VXUJR{;n|$Fa z-{Y~v1}~4++PkUu%Zqf{G}gu&V{;wgL#NJM!t@3B2pcqQLV4)EE?t&S-&|P6Z?`QB zJU>sXO}srshoOO$NEHsX<J+5o`4=N!Z|=%P?5>=~^UuAl*11?bwL#-}@jey0vdg>0 zws!XqN5#9Z_1$cl`BAEP$0ctjL$l4S1+Dw}zEGblyAB)wl<}uxD^Z#19~0m={jTJ< z_6$ib$#-dq{}Otb-fN#pxY9-OE$d##+h3%9B)Qdxyz+D&(ZTE25v^g_>{+oV7HT!; zp#Ca{{e#+jHA8$N`Yt1l)`yDvZ)XAeyX{}$YkxPM_idJ4x{3IkN3`bV?Mp6}Y1)Qz zwpm4e(px*x-l+)nP&)CAw^k=!(R!i3KSkr<gv^v)F5a}jfxV4xKCiv~=~ZS-c^FgO ze8`Y6dJ#C%r>&}Qj+6JeSu5y)KHJ#`35~Mp4+^f%+nuqsidP?sU*as6t_ICMB6{4u zjy1}n?zfC@*-*=_*qOZ-p4EBj;CFXsyZJ5Lnb#q@Zg%tO?U1&YpfP$``?uN0*0`w< zt=m+X<a9CzdyhLdPhwmSIqcuhbRav}m&RBfh&SiTVnOF^lo>X9<qdB6H;r7U^4TMA zm2docKXaz))JFEba2A4eJ=67Or2FnvC*%0$GkZFF(G{eV0*7?lGmCQrKi^WAZ0(>g zb6$ct<ySfL)4Z>f(jLSetbeCR4u=<K`!m>vlgwq&4<=cOz{<?T!X@A_P>F8By6lf8 zt#f%ya*gF@>i@YyjV)U=>pJcl(V6#zv=$hE|Fj;s+^h%6<`jw-`-S?5H)o2b!7GKm zI?3H4v2<2?ML&4#VI0>y=;!$AH(D=0%(wQyYK>2OVCNC8z4Ovlw5NU#{8Bm}5-kQ} zj0YF+E(rO=SJFRzMEV`1?<G!iB5&TKw(jG*&!k<3ulr<sNV}Z0+WWoS#Ob_7E8lJA zyAl5>(rVnDPuls!%{Oro@X$O-czF7X#&5k#=gC&-A{xUF;2y*Hyu+ujw8q%qkNYCw zDSR8jww>RP<J523%{bw{5v4K9x@juOs#5Tg&ZY02>`aAuXXso;J?*BqRRWjOPU?%! zM&>1?i>K#RGhT*UHx}mG6ASwn4rP0;>nI$$Y$&UHFB;&97Sb*yZN0^vI`D;T9`V+R z?B`jWJyE+j+f2G9(uvOA9l~lKt=$Vxua9c4^7}sp{8rY;u!CwZXyA!tZbyoDlaW)0 z>)6lTerCTi<6G6?8yCBB_2GEZNe385>|V!8e9`600DGw6#ejHK`Xgh{<wd!a&^S25 z3-`j1VOj0vmfZ4qQG2Yt-^;JtTG&5*D|O!rUD$7oPNKab%dgwOUWE<BZ6Iz#LF>HU z{(Mh9Yrli!Z`U=P=ebPtl3TLU16N$jIW59BmBpM7yd{~N8vl_i3!}u{fesc(kmoY; z+=d+)eMxh*Rkw9b>$<LMn(nGyaUQ%}>DlgX8tJ~RtDLd?=pcC%*UcUZ$t7gu6lDGN z(t%dFVelMd>md6rR$NlthXGDgkoA|V{)$uE`0-DIt7IK|1AU#d)f1SPkuJd-dn<s~ zj68K|S=0~RbFGRm<@-kZLOp!nKwoGueW4s#pfOSTwFjh@-`f9SS$8`s;~nLel`&&q z6TiKEF?}$!=Kn4q8Gi4#=~Ewu-U;b?y#>h}?O{>bUDp=RT{7Oyn999BV`~(`8GCxy zwd=|$9v(P5pXz&Db&VBun}oqtbCFx$ns(o$_U0q1i`U0h&hqOX8pEOOx}u#aMt;>z zWvZ{=0nh`ceqP-Me0B45EA1=R*r$EY8k<!Q?SB>>J>4&LRjfGQqil_rF>s7QYrzx^ zJRQRuW2IZH0Dj&lTMhx+-!~7_H^sw&B<n5k!K(8a3*+5R`(Eq-@G`WU9mM7@njdF; z`UiMqC%hh-z`4(tUA}Qfkpsh)^{#oyqIp*OaVwyEep<4-USf>;P;cS$@Mi_K%6Y64 z%xg{0jgwbn%SmfuISf}dDY6_}=UvXwtfB0D%6w+QGg+H7lQcd>(zD@B)<@D;p2Svg z3LZKJ9?c);{2g}<jplS$-d}P@(_d<>u8c8m>Ive9=@0E+;tj1}nbY<VXYQ~kFNkai zE{NQJ?x`5#Y>YMTXF8oszPB(NJGks9YtChD?daOVan0u)?C01ItPC~==IH8QHN-_{ zU>B@f%YC@mRB&Nje(&1CDDD{U1nwm66fO+Ec>3oFY;{hG`yc3Mhtu3SMm-OuCr&$* zf(EH{z+%tTF>Glw&wYe_nvb}6Tak^f3`v!BI-5T5MrVKf#KLsmtUTU+K_OLnpwLd= zOq{>5aDZ}Kh#O6T?|l~(KJd#2bHU8bxyTc}1=VY5aw2^7U~bPE_NS08(TZ*MleEo; zIon9yh6wc7irz2-eZiVo*ilK_b53SBK9RkS$czkQG-dR|6B+Ukl7E1FyV4V}2`~m& z6S-4XI>x5aTGmH)wDKNlM&Ij3@BSY5EAhs;*1)#4FV5|}pEHlv`q3WJ=q$y1zR;E1 z_2u5eqGU1sExd!NdxBOa7w6jS#W@=oIzKVl+A^9<uy?`g8r5D6l}Y(wo$+uiv(AYf zq~7i0XXN}m^e4uhE5&!blXJ9RybF&9BDXl`Ht_6CBl9Bg>=f#aTou2HKPy_-jPa|V zR|7s?ZJ-UstBs@|k5^9`UWF$|MxhUPARU#wQUAC`za#txuEXzo`m<!G=Chu>l>J2V zQhgi!+1+C)JBQ>-<WkGZA|y`w`u4GszCB-kn|Y$_{#w&$hE6eHE{&o4+30BORaM#T z%p?1-ZR^e=3%&T{Wn0QmUAARfH+J#R69)?wI>WQ|U||q_pnAi>LgbSNS<jwWSkPLL zQyrEiCc>{lXDN31RItN&Yz}=ZILX=k#!jc^@`HuPIiDN^p3Y=zU7$X;IJbtizA~%B zslQ2bEKw-uzDszHJJNQK1Y_&6v6xN2wzfuQBbU)vgNomq?o?jw%g`7di%l))T-@op z-6N;#caK!pc95?O9rMP*1<4x=Gum$~Ot)_=T$sMGfbKX$>mjZ71%(Ak=0NaLUFXj1 z9ORGIB&~K}w|3?(xeMF<CXFw*j)WY}O{TdsgEY+<=3eYMnQRS?R$<?b!RIk+QekFf z5_<L|#_&n-<{<j_B<#SG(9I_?|Cv-^f9Q-#n{^LpEc#X=rx<6S@4B`)|3Exf>F&}A z$V=fU{_yk?t<R`^WV2JdYv1T?=l}B$Ce!wlFWpn=AIHOLYjp7ynMVrE*cZ_+xI5`) z<l@a!+s<R(1h%CGnKkDw$aDlV`OSs;XQWfH-f=Wp=-JKMlfyW;H(AKPGg%nL9mAc# zoy48OS)>c$!nl3hJ!mD0`kM56Z!TE62Uxt9sn}A8E#IkeM0*L#+HLOO)jWdVfp{5L zmEJNk1sa@yKKiY@;g0kBSml<&8m-s0cji)4i|>z$7RM^r7Pes9-_o9*d;Al{{R^p( z<&KLdh!g!Z_8$KP`OzDdUi8&ki+|j^`^9(XM%STFfFpFk{@Yh*!=CP*U2CUKjokHx z{N?T=ClI^Ao!bSO+iA{(!aXBOeEWIe9J>qsf;8yZVfJZyX`Uy|a_Z4bntOT2F@`=_ z-2YnKgA<G_%<0_-y%~|7ZT3K7d%lhJ+iCN=a@()ezM;-s_oZ73$vF0S>ZSTi7QLPO z#UfW@-$g!@#fp1MKe%9VE@jGzP6IFO$-T&yZIq*Y+pfHzFk@y{u8*)NeWxEkkV=o- z`HzcpI<FF-9hI&bzKk%>t)?!zXCxfw%?;+%A&YfpepiuB^ERdJox(UYo4sb>w-392 z9eXJ1aR*oj*k6l1emnN~W!U3!hjICP*=K<}hC7Zsfjfyig|pa~5yFLW)wl?*1{cN6 z#Kmy6xCUG!Za&V&iT~ojJk-k?0pCsR-)P29;FjQ8a7%HmxMjHIxOUtM+)CUkoa&<W z0P&x6;N{R<y7h{!UDH-wR{VX7`YH8<-Xrrbrwm{=;ChvhFy_4Ey=7$8W$bOj4dU9- zBYsN0Bz#a0Ez$3C@yzF>OVAe{DBS&)F6J5!{JfDlM><gK>nq?_tCjo3(#U}-=!uKt zRsut|rYQR>Vowxt?xRiXnU^-CI^j?Ha*R9Q((4McMRl>3<F*m_39p^tv68y1n11Fx zBBfIr(NMm4iy@`zjm$IR=(h?BR-QM)y4j4db>7Ie_`hS{l^18hudE|H0q+!f6P^<- zddtvZV(dc(o<rR=mlE&qhbGQ-Ysc15yTL^^RqW_4ZC60gRXD9(h=z*O`cFH*q4l)+ zIMG}6NmpzsUkyH@*VpLVwZQb`rg&d?2#2vS@-Tg_T5ja7+MxZqwbOXRgR_Rf0591c z`b|4{Wh|bxIHz*P?1afg?g8M|L3{DbLzG$1d_P6L?RRo-q3RSv_D(}TyqdM-a@LZ$ z6EpySczsxT)pw)BADaE0Y@9X2<8y|xry7(O+t<Zw-Ffk;70`~g_VAp~y&V3V^-efe zQIHKPgs--7-@K2VNB`swK;(hukncm+R{xhw()V9t_X=N3pLW+JTe21OT@M${n`_t) z#M#Ihqm137jJ2bT`J?CpZu!(BOj(D$@3pLP8Tw;iuBwlqFPXMqK|8DNb+e%hybVpW z9#3yaPI&3+`0erAApEh9e9Ot_@re4(KH8#<zT@TbkBNT%eGly=m@4ODes5!}`6Ryh z?r=%D;=RMB+z9pgDCvZUMZ2i3qe@Rc@#(12k^UIE*S(~>i+SKabhCZvW`~VFCcBjK zH4^_J;&%|ggZLdLJW6{+pnE8C-q;%aHq!Q^=Osy-B&}>yD#NosX}nNa8}P9JIl8x{ zi}c>ybd^cJ()jhJkE*`;aq62l^_32(`&*<p%BC;d(+BD3hi?tK^X)YDrR415p7Q;~ z>0HW8zW3qYOu9yV&Bbrvx7N;<@a>MJ=4`*th2)d$TSzg7ZP&W9b@aYZvG0v>7kwxD zCU`~t>FaH*VZetI*dyZFVA+o-Im@~@Z+W6q(4T(vo^|Jvf5xxCSG18#!X7lk<Cz}n zxedEd8TaxkjQ379NKcj>$V-oX&`qy&UKr<ktMu)qgZGc_pT4DV0NRP}uFZ$G7a#7Q zzLs$Iu!?>-*&C~&p?B_IbhLAp<=vs-*}1fDy$OBRN}|`dOaIz3I)5YkS6LU4&3O6x zjzT2LT41<nTR(?Bvih%{LGS!F`VhJU_1AfI+1h1SU5*|n`phM)I`dFrS(<Yb)WLl- zJ;h%0OmXg}HT1i&h3G6s0J&#-^~R2`@p?Ko|D86rOzi$DkG_j-fqe*C$HE1yb0r&R zxU@<qaypkS`-beXcTene%N;9|a2L1r#q&gN9^0e6yCy+f7wfVQnrqBd|Fz=leX<z) zC^&jJ7u(2`YwC>6ze@IB(OQ4vH_z^={T}K^RxDN6PQ7F|(VDDhC+WSa){(v9M<40R z!OG7Dc++_a^K0>!>~HnJ_GC+j`Ji}0_wJowzNUKwSK#x0klQzvHpaX>nAqsr&m-&) z+Q<Aj%D&wie$ULT#RjvsP#Y_rkN51L5%BvR_+Rx_XXK=*hwL$>>$dJ%pXva<<E@?c z&YkOEBYieN8!oxL*nZdtt7fns7-gTN*Dpfg;{Dd!yWVe&ZQ9d>{ls0<6<)H>3NQcJ zDi1G@m-Eng*);HikJUa)`8|O$^t;*jyXopj3QZTQ4IU^gB770wUb;rY8+~bu?VK1{ zfR0=HMdY8&8LU?E#@0eblKzq?_6vQN$7mDsMkE)o4UN?&wzY7ad)JOPNXOu=dvK~? zoC|Rmt5b_UA4>-g6E9fhl0$#BF1MewVdReP4A6L5f&OeIwidp=bZst@SevV0|61T( zYsYwmxk6RFwKz9p+uB@DGUk@0Gi^N~>In~ZQ$FKH0N&;dW;(lyZ?DcPe7~DwTMBLP z*D}JY**~#}Z>5VS?ne$i@bh-;v&|}txF&EH&VBHjy+>;l?9n7HLR^}#ZOl=tGY>E( zqK`)yUkQ&9A0wX!y9fJBe}p?Bz%xSlKKQtnJTdajBu|t)`OA3w=o!)O0c_gR9q;EJ zkOvBfr*og!T<|2_0r>kcdyoWcKfkrVRQkUMXPC4Z((a*rg?aewB+pL5i?lEDN(S3Q zIcXG@p&q@Yk#69X<>{c}fA6>2zP%*fGQPb$tFX7U%!5YIZwcXb;8qL&$$qJN#`wJp zy3Z#r%5T{#BZSxRTQ;6L@~WQw6`Y$RjZ0JFg0nju_5I-NHIDc>tT@toa8E#sQ@oQa znQ>Bfx)?MC_8!VPM!3q1@I6Ypx!iT8a<yhByGMw$`^dA8bY6LT`1XD`Un=>;oC7(m zwFL3mU-7$*I_dX4{BAeD@8Eapx&v-_3%`@Ta%!ru`|~Y(Vmq*EfiL<*2wz6{Oz;pt zRP)_Jd=2rcLzwSo;>D+`!y@8BgsE-adJx_~e1i}FWsEhlan+i9r^G9ybLmOG2x%k4 zd3B6Z$34_-5ov1pZR1C<#T`fQoKN~{+Ew~zqXnOSyU1G&nFk6EzvK9a@$2yq;n(3G zz!!gS$B*If$DfJ64?l`Oj9-Jl6F-8#3txSxA3u!013!e{i|_5B)}3#{S8IRbS#SQZ z1iZX@Jcj&i@_qk3-}8Ony?ht%IV$q~1AN!|;`LT_)c5@_z^s{rUWH5JR^hsE?YJE{ z{T;$TiQZ-5AICqAFCC;BKZHAli=rqj!8PLQaXq*`Tsy86cL?X;j^Wa{9k`lW^5ahO zyB0rzTZP+?JA}*QMsdf{71Q{Axah^C#l>+a_&$c4&+jDe5N;HA3KzM=vSK*dD*O5F z!!6;v9ycGi4A+iZNq9SM8Ez@A8MlY}Xw3K4skSjjZnKJQqOrhR%T*icyC+sW&*^=4 z@!e(GQ1PqyUgi5<!S@Q^cN^brzVBsxFY|pb<y-sKyz=!X>=N@W{YGn9qts<5ZV>0- zPT(4-`y$**TsLkIH;jwaK|fpq*M{rH_2LfWLYF~boWK6E?=8QQer=;CFeYkkNb5w* z$*X$MgO>4o5p%ti`8|){I&;<tpII5!TNxv#S4qE3&#qx_W%4`N^J1)py}2{jbt!f| zejmL<_NF9dbNAuDb>@2btu^vG&i$nLt@|Q>$61|Ten&IhZ5YFz^d0VD;rDX(rEKGO zQ>Lbn#$SZL9pA?9$FC(#^)UCe;79PKe}ytnf){%iGhZx(GGD{}18x`Y@dEpk#?FIl zz9XIGV&+-x(7heHw-cteScZO+iXqzwlgw@<Tsn{9TKN4-^65_7M)Eb1rqP$LhkRPM zSH3!5KCP!o=XX0E2l2E&X9)-F>S&WVt_|0O(>&_ELHZ%T{rc%P+NuwjfegBhBmHJ` zp{KPt574?(j5)x}7WVozZDzdYyjXm3ZaI49B=~ekg8QVft(PUzBRkRW)3_doF_f}` zHnu0q+t$i^A*AaiE`{sHX@5}6VO=NoI5fQlJ9uZowmPMQ&e(}ABYKEWJ^fU5Q@`}{ znD&0wC6c)&&Qe(1KeXIQ<}`Ona(-7dwRB$$I@k0W9l5)&=*V?_M|%m9g>L*Xeh+>% zehNQ=--};^--jQ?--bUEKaC&5-;Q64-;ZC1Up>5$`?KJ==*Gg)=Q?sJ;Qe}5NA7o= z*$i2O?%X_N!7J92@Q>^{+xZROSpQHc?qw?WL)Fb+uRhHe3=OJ{Eu$Y@Bt+i`neXj< zpMn=o(DtI$3EEG3*Kxv*n=qY4-$q!TFwYJkeeDq6gC@;PzGWvEvjgy*;oFm41N<H^ zX_M%`tqJb)itH-%o3L`uKB&!>nQ!e^={CP@(uX2n=dK)24*i9j*5hf(ucam~X39;N zZ?9a<V?AE*?Di|+-&MF?TpBlk8^j&JIk=O!$mNz*hqG}lxK`Y9ToNZ*d-I0xVON(f zCm6wM_NE}OLhjzg;@%ALpf{#=!&8Uf1TAObCKvHKWc&m8+N1m#?AjsvOnF4>Md|FK zc}076Ahsx1PrnJ-osN}Zp9N(FBl};j!e)qWUKWgGCUjBmD$4JnENk~7x8BN=<U2Zb z9y(;PtQDkdDJ$AvWp7wg##$MUeM42xy_Y!(eUWZ{G{9WpqT(H;Rg1{;qsd;sO1Qiz z9&G%m&Pf&PUrU-0<zWw;O&#Wm7G9j-{8O3UKI5!9@nyuHyy%RMq4+NmKf%OLApWpF zo_YEw%Gh%XK7UnaJwNdQcTVfly<zhOg&+R);#?JUlbzAit9J%DLu7E%S;PeOFAMRW zun9|2e%Rm}9tYnKm*6|-$A^5Zlg$up4~Ae<ckB&CdJK*OA7jxNe9=ey8buGmKXIXt z9_-J=PRyRtzZkjF)K_)%!>Ww2zsR(sTW`JxfEhPoyT*b4ObL8Hy;u6-WA}YAXw4`C z{uJ`Kuqj_~Jec6@eyc517Z0wLQoV{akl%0vIBha(KBgTW_2Cf$F7~YvD+ymDi+rQ9 zy>=3B9Oq29!kYa!622ZB)dn8jg`fK31eIrV4z7$dFtmxnJ^X@-OLKmdI6oh`{cB;T zBb@6V3l-&t!S`={__oY^gf$1ZjM<gxBEI51KfWIUUxjs%)*rsg;Oo)H!>tmS!h6R! zZFZ{<wsV2X12#OPKB7AM%fFiPU#;x^amrrcE4!PrU#mY%evPuXk5hJ?uk5&ocN)B3 zg=Spl|EjpB$0<MJEC0ZZ*QU$2U!&}8<COhd>gv&T6=lB`UDz`}hPU|4<3+V+-#BIG zd}XWssw4y8{VI50JRWiDQsf88t((DJa^Out>-mPqi?Xhabb=*&=Talr<Me~2^NMRN zidWelU#XwB$Nuf5XM)y-nb%{tm|o;d>1rDr<~rZPzE;CteivurCK?`_I1Z1!8GBMG z&f86S%CG*K0B7MUoID;Eu5P^PkK^I@_u#jRI|m};;5XCYcPjb_cHUwippU(x54;7~ zuLtI*ff)woHp*3-`)Lw0Fnfr5Et<$?|9W8F3C!L`^v`i%)*6_ikAHlqHfdcNBA>a( z*_F@Sq4m7vv-m;$Q!1ZTjwkyR@A7DheTrtB5O08cc0M>+;M9BmE9ns4%Ds9%yv`ao zOnMKmkAhbX{Mz{{cx}6sdy%hw#9b4#Z0`L8_Sjj6L=o4`oOe)p!d3QcrP))#`mn*- zt7|V|btPdt2&*j#>nAK$61I!5nI&O635%A54HH&V61I=9NJ-d!!m3Ncwi6aE2|GYo zs3hzVVOB}lVZu%Yi+Y+@Ux%=hC1H8OPLzaIv#0fVNmzuiV<llVgpHc8D8I`s(?{(@ zZXb7Bc;B8ZOktybt$wf?*}z@Yu1-@y-;_<=%WEYPxx>V}Je@%2Nu=kM)2_0kkENks zBde<v9xn-RCETw+Do=zoF5i)leoz&<nzKaMf>&ZI?!qptxFu7W*O=c6{&4!}M1!AX z+YZwCVYeAsdw}IZPkyOyy`H}P;efSapn-i!rfk1FiJCqnySXdFjNEtoI(7ErvXeI{ z#rM@EIF{4DG#-4V1jixlYW}(%!k+6d?-#r`sC?{CJ*#f}$>*0dJtg^WC7<-}&nh4C zTso6zvXFezaau~!b7z>FzOy9#MWlD-hS33(H(HWc`x68UyYN}CPSS3E91r{KtQv3F ztM2BzrzGDG$ycfNZcWdwY)#Lr0A^oF-k(5E!DR1%3sZGFc@=XgGfq`n8cU07HPewr z3Hpgg*X@+$>Vh%KA7?CrR>96coIYz_qdl))e&Nm;3>QAOt+VRf1MV)rgL|35{gBU& zYNZl6_S?8)0A{qYF#tTq#sE(b{uXO$eqC2-BvZU`!PR}a*USrF9xNM^wVqzw6by~c zb-el1KLX#Y%T91}^>}DeHV!SeQO~w3xyLSsWA1*)%+1w5buWSX>OR7*I(2qiE3F4Z z^!k`-FZk>%dWC5xR~Go%P2ZVubg(r(yk*~bExgyAI$hNZPAY2*4?CT`Wt_0L6V~Rl zo%LZaklkzme;C)mhFu3=_R?DH40(PZ!=1u~ufXnri{j$AM%*G?Gj0j46{j`THvBGJ z3bzf{kCQ!h82>Qt1kM7^uL6{X&z(kABYrL6CxNpPUpW0I;Y$gx;roaD-ieP6ZiNWb z-zeWd<6HHS9dJM2vI*A4XJH@HT79uk_-XPGeY})TpCqgTe(R3RI;$P8GkpIE+R>9K z{|x>7GJc>Wk92MI)iz(A3&|rn>6E1XM<eg<B(3`N?er(>%2@^30b=B-HoqhI$6~Xv zbIro`HEV3ls0|c<Cm5F>_<gYs4O7mp!^^<X9Jz_Q2*&#;cM0XqpFOLfw6-Zjdp4Gv z-<Ls;=ian9H}NftbLU)Gw5cS?(@vh{<XK_TWv*gPbS~?o^p9;O?Cs>;PTK8!s|{qY zT!OvQPjh#!0)Jx1amUyzOq+OP`C;-O2G#*!Ii}pa@%?RCL%wq|*t*PllosrYT??@D zQa1f1+ru394eVK7L72XO$~Sw|HUzJ|k^OHsvi_XNzLT(D61K#o`5@n43s_s5%y)lC z=Mi;JQ6l@F*k-f`?kD9|m4B~@-e8WzHs;D=Ka69S#ngYx$otCK3x|y}LSI+iB^Sc* zhQjn+%+q^T9@*)3t8B{|IX7S(9e!&O?{9+>-Dks~`3~|8b8iTnI!wh5^e%8toA_36 zE;BgqH8_7^9GpWXICmPHL$AQOsN)G|)+k<q^LHwWID^yCn8D#LaC|qkuQA_S!0|<J zt~5BG<~v|;OdA}(qH^MA_TUI!bqS7dFgRkje^t7&Uh)bYw;H+*f@9ZPigcX?j_(A= zmFD|uaAK_8&}P2>h3{qN_s0#6?74acj`bxt{*JV2=la*ck$s}C!14D6$Iak4!O&?x zIMma&&io?IUkB%ML${j^PP50ssg!Py8=PJ*-KtI7egvFa4G!M}hwnnSCFXk?{MKxK zzro;i|2R0+mC$LM!Kv;w=u|fjojzc2qV0|zdUKI3)4|DtPW#OFK_7pG4Nhg_^nqvz zPL~>-qOXAy=XhVyc9$8PSb9C$Y;d?6oPG<PZ1a7NukB=Kl`LUD-z)ejT!PaD1}Dal zF`lnPmbA0CWQBF6Z?b0i3cNmPc*?uKcL3XpWZBQbWvBU_F}S>A9Qu^XwdYCuXUR2q zL~`vgYY6iV+^>RzCj%ZaIQ)&$mB@gW5_<g3;LzfuN2zS(eY#iBVyB_Szkox9>0fIM z+;*?-?`QvC;#=Ieqq~33mgyS}T)%vrKsyxWxze8vbA`oPpn>@XU^ZdH5$%^5n8>nM z)OBVFOa>m8-ZNjLt}{#EY8?5zftv(wxvA^h4cw{Yz%6a(O$P4k9lt(e+WCXPJ=egM zomISkaGbU+l~Yd}xUW}EO)_v70oNPbnT)$|r;JnIni4uU8o1iu{%Yej>+P@LDIV-| z`T7#zwqY|;`yRu7>goyO)VGwU-e}<Zd8)|EXZm$1U#WeY4BRkq1&cmW<fYf(-_$s; z#J^``$SZmHC6!CR{S~^F;9TO>$p@#DmhT^jmQ}!Mi!9Cw)+B4Adtbl$SSd~0=`%kt zFn?fR-s{!vQ}oUFcj%kCx99A>`Ch?nE$%1w^Q`1#g;kt)>E2}R(Pt0EE86if19O*w z`ArX|*$+IPj(3r%rypLa92yVS*A1+P4Xihf1FLkbWD~Y42VU=3`GkS>X#=Zc99X4& zki}IO*6ZzqpEI!TGO#{B4y;o7_7el^^~yJR+2zY718a=`eeG2`j=smhdgVA;<V#O4 zA8#B@7<lyt-XFcX`FOIlAJhq+;Yq(-8ILDR`+@rSQwHW_1M^!R%-5(RI<4Dwe@-1g zZs7fg=ArcU4|(u>bu5)%E=^4x{W45-^yG@y@5Ym3N6`T!Uw&+0ZuemN>R8I3!`MKj zgS=k;ywlY0UkohPUW+o*SHDu8=@%?hKR-<+&;0tASI6;q=WYY{^9Jt4<G|(p*0W?1 zwvjQoG2fUZxa_CkT-ez%EjEr!yUEaYwSjxxIB@Gr;J)7nx84VLJf0nI4l~EV{2(xE znj)F9rkR-;_!r>LZwhB7H-$1`-1MgE%*D9bO?8=yruxhr{Br!MgjF`hGP9a$Gm{9b zZK}!CHAOQK@=n2BLVSp_s+(FeG0MJ(vc#(o39j@;Ut5;)%?4lH{Jb+>-Nu_k{!df4 zD-1nnc=Yt~YN@Vz+U*C6bFWudJ;(4&#K7Xd%~$A(rS)Te{b%)y#im}r!8RmXE*u9| z>3DRNXh|P@z2nil3@q**bzxy^`ETpB{m-n|!v@yV2A1ZC{~eF~TChxi|8saGXkb2O zU}BefMg2-;D069-mVWv9r|5uJsBC2CdIM|rIIv3fq%Rp*uUBWOHL%(YtQ*FGRXUfx z(!hGXbLkHl8s21Jt?=5-*UxH8<Q8YvT^iQ<WLBvzRy&T2WS!fk;Wfb09YhWI;_F&u ztn>lV_e~}&>I=KvgjM^(E*>XLc3hR$;!Agd3B%?(2ID*vR__a&V!|T6uxb<L$7O;E z<9?H|@`5JJkKZ4#5epZ+&EVDT<TzpfVZ!|7{c4=BpPMj$J@VtEd(njX>+!q^^W%4L zoOJt5n4f;%HDP|Z-ySFLkO}j{7&KvZJ{tV<IALEKC+}BH*i2vEeiP<zx5rIb%$M#9 z<COQX3G>&Zcbs&e9Vcvq3G>r*tqJqDZ_<SMasE3K=BL5O#wqVU6XwUSZJe+V5vF^_ z?l%5i#=q0}cNqWu_$!zLYX84q)|GQt?ybK+UG-h`T$OW+Nq>_sy<c7_{kurt@VhhR zmB!yd{0}KlYlwp9*JYIddg2c-whG?0J~)1vuXJ(JjS}yb<JZL$Uq}2GO*t1Eyyw0~ zc{54B^fmCVA-=%}ue4s(#4n+53-3xFoRClMv8T5zNV<q*fT6d4{-OBa{qA&?<dw?# zFYuB7o7ceWSETRu;pK-XI=n=DHFWUcmEwJb_=P@v{JOOA|CsnM`QrV0h2p<Ye6ugU zw4J_9{2it~&zSlQ`RY@O?>9;R4?g<&=bwW2HRA6v<^7{6@2kfDim%*KJhqeXD~2B) zC7s7NrRlbk?u3tC^}hBK{7uCF{<ml7SxS!$#P2Y0)*HOm`tT~H@25$>>NVm&M*M11 z-;cfq-fg6Ni-CKuf%_rj-);Q6@I5{#tv9@1b<|g{()cCBZvhXFZhpQMU7Cr%&fxh@ z1MeNif1B}dH2y+-50BDvuBV)ckDp8Fbrta&4V*Wb^4?(lD~x}c@h`>q;FQ)UMmg{I zwR0&SMu~ruj~@Q`Da8G?ficPW)jnAMIfZCbPWrdMM*JUsd%Ei9)XBruua_zRZ;1b% z50}#TUlQNvt4k?Q@;GEwpD%xDpZXc`x0!l8Pddq*L&pEHFJEm*UwDpuTY#&zUhjTB z)>*Zea0FR4qPuBzZ@<MEn`+M3=)OIF+7Rci!d9vfv|1f6&b!xGXFR$4_YiBwoD1Sz zFz#N`JsknwxDPog&X5Kit2O<2S$q0%_JcisK4&N9vc_Yzf4|_yw<Zg`_d(hu%b&N5 zOh*r`*7+{IF~r#!EB^gL*iMZGV|O`9SHt~pf+-ty%uaG=n)STS%9jC0cl=lL9n9S2 zSg9k0oA$A{Dw!%wpVyP+{=Siq#{cal&fsq?1I`irYGA*F{a1GvTk#`>spqcY{*3Pf zllv=UA9So((!KjwwD8XD1)y1wF;V-uqyy^Aei-<imkWm?`Yk&ApfFW<#)r7egtM63 z|F3nL5cmG;T%Dh`Y6rE!Gp>KjNPv68IUDw@N9VEjVqVFe4(D3n65wn&dzYr7pI43L z<DLiQ>xdE0{Z4vU%f%0P9?stPS@0=$&8$23uZg6Ga6bq{7VaK5ov9~y73-NPtta>C z(q6@S(r%`n|KHI~wB~*{@Oen>VBmRtse9CdNqDin*jAy|7YgCT3*1}H9ztm2^1jh8 zU+p_!;?d(>9Y}N(ZFFyu@>G~_Pu6<hI@_ao_DH$u#b17SN8q`$+W=Y`{M*f54Bfp! zTaR$Rjn3R<g9+-v*<R#hHr&cv5w`9jMHl3(pY+R1Nmt8xxjI}d!<}@k#q${8R7_{; z5{z&^fC*Dwyx+%7yzU|_Pjp4fp;I7oATPWHM`?BDN_TYEb9P^}XX}uAufR3LDP58> zytJNQ$9hFA=`HIn$2+U%ulxSkP_`_-iT<fQ#q7z04)8X82xoEk8Sx5hW<^N(Jbv15 z?{@o5!0zQd(-(8c`F=&;GBow_#B9okj%u4?eTu&KEqE$}e&xdQ`kvCp<E%~5uKs;d zSApZq7-!JgUp5oml`d+0mF3ojvXbntO0wsw8`p>P*FOL*k|)aR@qmYK;PAV7f6ToD zKN|q=7<((;Hko_-W}5kD9DChcw5IcnyQUM0ZE^g2XewwQc9yw!2rHjpsIJ~QIhRjk zyy0o$w8w@sYE?QL22YKJ`|I>?@UC~}j%(^h^nR>Eopz2>uMl+c>Xm{9{`S-P-(lM0 zQs}fNL%VSIQc`UmQ@gK$UwYm5IoJhP2-y!HTg-jR>@hyavcBn-%kQbwu?IL8lh=K- z!_Z%KOM1V3b)H4K)>!dv2k&g5(zcki>@z*8_ogMswfCxv`&)EgRPZh*Z!LM%-t{KE z&e<wXce~Kkmc@oC{i(gv)H%$zjf>)1aLaLiI=o(<j2QW_TIUjN<N$9scd*xNQG{{) z2F}Y~RqXd_=g5BcPnkY&+~oT-`6N4Z4~pKLoIPoAF4$V+zkvkzU^u!vfU>CT>^JJo zM)q%0_VGI>7Ea#8UD;Xg@!QS)ss@g?FG6+l!%+DF%2oM-Bl%Tk7vZQ(!3fST!ch6c zl)Y!+*=1Yp3BeEK6YI)H?RDjn5gxp&V)RwoA#UhD4}5iha4lip9ix)d{(fm$A98dL z(<tpy$E9$MI2)J1mEO%PI{hhi2>9x-pE~S&l{y@z4o*oOno8>M&eu@~tL5xEw2f1T zAo9Z<H`Er;-fIi-YlyXDs}=sy+nUJo$OmcDITH(4YhPT3yBK*Vk^44BmhxR4(f1nn z`(1n=hevb|<4O8SY6^E4(|3D^CKfVxavpOC{<)L8zO&q?OPWxYbMjZxmq}MMrFaL% z4$_@y=Z*`~^^<P<5a+!~S2xsKNRy|Y^t#tk{3qV%A^pI8>;)lh7ip8Ear=L3@eHNv zQUOmzcrQt7;!*r+{A0YMG?U*R&)f!mOZO&gj7M%3bdQ|wHrWF|?SY3>eum$YcPnV8 zG-108ul+6Mq~Ns_VJQ<P9iY$r?#0&|W4Z_TeWdm7UhvL9YfP^Orq2EAtiH}Pm&YAf zS7_$<56O2sY3gHV-=C{|Ve)xr{3VyYd>T9VkS_{fczoRlPjut77g+p$*zm|c{6U<5 z9Ex1Yn++DUh<89g&cEZ&#IMHp#wAbo)Jiu2mxkEl+&d!pan66@>Tz|rT3ie_6Bos~ zZN+&LWKuwV*po|r&@}=LBH*qx8dtbA!{OZV(YWF7v3_aZ$LJMo_*v<<-zoY%RB%%4 zRffL<iQ;*<7&rxz#Wa$GlJ80{-%6hu|Epr@>@xPWQ<t%Gbf2eAU%=+`h|zgIAAeur z3$gbV9*Mk<Gw;PQ)Z*^4e7pypV_Tsn`2hFiZXP}0^l+E%13y<9C%(;X*Gb&z?AD!e zm3z>>`FYA{OHe*#K0=w|w{q~){&Y88iu+rVj6L+P>J0s;^`U}`b9^oHnYAy6lDw_v zFh|SqwjpVBPep`0HA(tXESZZEH<P$Xs*^D8tF#^}?6DszmQ8yF9QqRVQ=292iG_BY z?qcYojr7*;3LJ9TJ)@#K81#;Yi<fCT^og<exX}05?+w3zztVh%Hv0+fS*i=EJ#|;D z#>A8GT=kpS^Ip=naWgh)?0*|&dN9Q+DqlL;2yuRSpQk>h@;*fSo-OZ}xp(rnl*q~` zICy;J!InN!18rRWFfvDUAHzfIAR+3j^3`4*e&Xk9;yiuo*WjqWIp6TJ(yC69G0G!d zLG;iYWxpkSJl>Z+)&45<8N<;QE^}PH-^B$z$i)$O<uO;E9K*d7M>|%0@6a|lioU|J z%-|@!#<K2qag?r8LwzJ$1V{Z;_zTAh8mG&TC*OV@AYe@yQGX1AtNUJE=G@%dpp`xQ zk;3how?%aC#+qDB9d~JPKSrSShFri|m@DTlMZGbjw>GWFoy=8&&Lrmc5$57G+@Em{ z`ra<`a~`wmr1J=Sp>D}CHDHgq#<*opFm|^yY$pr*Nxz5r=ssK-bvzCaDNbpWb`SCU z?POuNB#l>wn}+y(q*I#xxbeyvCVrn?gym1u8h@l9J+l@1wHo@B1Gj}R^!<?~CM-d^ zA4AW#^G;x#I6sevNZ(-6dpeEYNqCm@>QB0#`g~j;?cmA$26%fuPBMQP{wvyq_K;3+ z9c>Y4JvYaZj~QXwWR|lgH!HI?r~6RUKDys=7Vi_+M2l|%1=<(p^fs#6B+x#=2}Ewl zmGc&=`yLQ&G>bRvb?>#>hWSI4?gi1kE%cA7VEk@pLS&gU9EXmy;ht7#hSL}lY1chG z$wF&BSy;B`42_ju`G!fqpL|{($&%MYTh5yuz3Fw(_K1(RZ-cfweY6!lJ=%)SE^W=Y zr1`q7Gi7P`uqw&ieRCmUZ^%u5wkH?2xPRkX>?5h-*i*A|TOr!Lt>E^LRwGXsBkrIr zTCRVXK6cB<2lyRl-mJUC0;zZ8nt5BXoVOFXQ<FQ;Z<%Vfe~2>}O}Ps0#hs9<bgbm^ z+=AG;;DXrNbIX!prxF`cIF+7KmP}7kIdkTw1Gp(2bJ79aluQlp!cE>#oD)XU*=DQw z+d|eSXFoEnS@5~*B|sasT;EY>K3{LDZyg&CT1j)G!BOD}Ge=VXCgSE3_mzt_aKFo% zoIl^k-;|z;jyYr3C%5u$`BwVWUuHQMx545L^sl{jL++~|*sxprL|JQkD4bZkdm{F{ zF!Mj;aaKB>RrbKB-VCb(uL-dt?Lw4M&0Quf+=<BDt23%H>5*By2`;#^m>XLu?)oEb zLxekWym=&ea#_1uN6A3dGkI;t*qxqZIHwXh=vUsdwX=LHbK}zcn%d~c?)zu(jr2U- zp*7aG-MD3r?j3EW-|Eh$CgPh2mpnai`BvVV-8wd2G!pLTzuoZP_i+bt?DMdOeezak zzhr<>zi)#VSK-Fqku~?&F1^X<73l9F-cAx<-9UeAx(}RfbFb~YIeQH~Ik%bBUG-m| zzs7wlP;VCpKCC-BA0pq)u3eznoCmX#iJb0rz0a4|0!GV*bp_^Eh~te#K0ycf&X85Z z-^{e80=LX+m8?!r&9pyK9%{wz4%~~eIrz)dJN4L#t8{nl*Q=A<>7GP?Ogiq{h2~8@ z#?dOh1EBW+L{H(x{a96Z)89+qyOO>l9o?Jr>nx#b_qCYYVxMcGZ5n8sMW$^uJ~CT( z-?jT7Z{9_T^XB@J#nSJK`I$rJIPd3^6aBQsr)eAM+@7A{*^)G-*1`*tvzucv=Ub+3 zORm>@WZ2ZW$9vUv$!VVLNaq3la%L5BX8+ZX6!u@NGn3Giy}aH%v76#C=kMuD0p7py z?uUIC8fGrxO|@x{6#j;L8)Y|_T;4*uIgR4`;&+<wUhXo~oxOic9^ES`e998MznDmu z>0J@d(QN4dSZ`q-eRYuZyYA8NTXjx(!_JrV`vW7>NYlstgJrz26XN&&FX=wo+eiL` zG$Cw@Fu{iWL!`~zpSy=NKj2&U9#$uLTNQoN`qm?bk0hIzYqn$sLw6o>ig84DgMAge z_N~)*%Sb1`L*RD^ocoX$^Y}i@?``~U$8RIwWNhw}>HpGibx-4}*u;W!32(^oR)^js z??o=INK7oW@;jy9w{rg`zx(*TynSM!trdI3$D!Rl+&$^={&<o(^2_Mk>v^Y!bkTPR z-UWqwdH-rM>lHD0bTZ@MvdF~3W4zDP%{-!+bke1pV!T<Bo>*9vV*Z-o9hz3=Ob&0^ zwR7ijlDm&>qie&D-hEQjX`98=@i25y-RALI_4_t!7l-F@#}s#y>R!{sWyO9j8;ItU z`w7$7dYHNno47srvTbcM<s78UwE1mW>CL>=v2{CTc2j0I`MXQX)R}RWnWoGYCaxWy zJEhz=?tXyZ#`kmh9rQnYE_x<;Y?D?znBW`!M)!N5@Hes3FD>G`&cy4!`wV#-=5faq zc|*j7e0ghpdFRwI*XR3KuvqU={3pqKKX8Y+qjQ+^*TW`mA8<$cRvO8OLHsX~c0Fmg zk#-w#+f1BCzYJlj>n`$ko479gKJxWn#XXAT)7_)XO7f*lzJAr!#5Ln@Am2*z)swHD zH1#HKm~<*fX@px0e>G{Bkk%rtMVw{guHvphwe5VuJ_2qB$a^ec>W_aP`D)2GjJ`0; zoOam6d3CBL-&NQc^5olP;&$TSMZP(dog!a~d?^!$?&-qQd_uI?PuwaKw-Wy^$d|dY z_|AL_ao+iE*(ii(KVfb@;4L!wZ2WhSFGarCY#eD~Ca%onTWRw3k<Yu^E=(HE5+7|P z-zf5P6j?lq3>MA2`sw~s!P`l`114@i{uShllW!;ac9L&rNxrDbw}X7!Oq}dE7m{xS zJhGB}E6KOg#4R&;YR*2L--pQO*>$AnPbS~KIDAh&n>5}$%foXQVZw78`83y39W<^4 z$S0j%^8Sx(di@$o^kukHzHy~Dj;_y`BHexxaSr2*?zuiq`aS%vBy2x^JLwX*6a2n_ zuw(dh@omE9;K%W2<JaQP#Ifhys>Z(vKZJiF{weZsnS_<cPZGx2JL@pN{qu<!W6@H0 zPPUg8_|#n+iS>?+N5yxgW6m|Y@0)jNmY6q68<5ozY!~y8>z_alRXfG8V>!R0t@?ed z?rPXjgN;yQ&D;4Mj&MgY?RXz@L+hJbV@3zrFdJFmeaHA_kGw07^#<5u$a%@+2IR17 zpF-BwA$PS-rZqCrUhkJ8|3;G6@IC{-Gx%Dw-Gi_9H~aDR{^bt*8vLF3QT$!_o?TII zeCj^WrSK{1V@F%SvjzV4_Y2*(`_0$^SI?CEYa*?9Rye4CXijaDue4vxB+Y;?pWb>< znDVKA{EU1N@{QLoI1|B}Z)z9r7>38hcgm;!AvygJ{5@X3&^xQLfhu3xmrwm;h<rQZ z^oQ8l{X+cBo^SU(QsrCj%cuVFPvl!gzVZ5n?qpqN;KhCU)IYvRKDxzNzYxE_4_>Uk z?aZ84{I7l?-dEqaop|*JlDK@Vet^l}?FU@@>+-bA$3K0;&qF(#bMCvN4b+!4?o+p@ z-e=#xFaF+g)x{1v2XB7sUUl7#aLdRV=^(86?_<2W&*)Z~pM6SvX>==nuNVKaj-~ZA z>@@ECydTZL$Lx{dEyC=Nh@b0A&zmP3L=)-V7t;-8=Zm!#^`M){-#U*mz<E1;-~-uD zleQLqZ2Bl~fH;)NyS)<#?^T(j^bPaf!FP2M-K8CQY@xe2>L+V+P4pA>ktX`c{1`e3 z{X%QUvg6uGqn|jQZju;5JXOW^FU}qR^5;j@AEcA0e(Do@a^PU<HHmtCRyde?$xg%j z30pOO_A|EiGamJuu}ycZd~^1hzR^dx?r;&W_VPOi4@`L9+FXn|UM$|l+!{Nng`G6Q z7!kt;%KU{pC9+mV?*!<bLi%oueoK1I2QAVR_hB$L5w5opygG<>1C$>JFYkWuh`~!^ z=D+&-p2lK@39nQ1y+QJ+?|&2jB;P9M1bwk|4BkV3-Q_E1fV3J<RgT8uC&;&le5GS> z4{5&P%a<f=+T_z%yp4SSj*eI=Yko(+<~&QGIF=S=jdTXVldO4=d>Tu~lQrL%bEX|6 zYjh8|@=4a{EUd=TQdy(1aF;KiWKFfnCt341<g>^(o~)6K(s(|etXW3BN5>h1SCD?d z$1jpK{e%fm$(mcqw=MokStHx*ppTxCH5%KMPqKzPKF*RgpDeSiwaAN^<H#C|&H0iw ztBK#w_$aybNq(pK{df2~@oPx)8Gg^l-+*6>--+)KcMQk9bXEpmvdCLo=>>1ep%i$P z%At){&2cVpWl+bM44OuNoWR}1u{bW$iTw_J&E~Cghj*8-K~*znk1!9?oX@g52=5@g zgYXW{ads5@N5p&Eoc<9Z4QoDHH;zCP`QmZ;o*Y(P{W!Za9lV*-)4w(WBR#S?HrEMe z(j&Te5Zld2Sq$6w1nzKtM`vNt%bkU$@9+lI`JIKtrJcw*?0~-V{bjrFiHH_4-Pz1L z==B}k3DSX#yJckK+_?^R;IrNmnFKv_Ke)RW%Vz(XlPa7K4)v^y#M$H4V0RW89o9%l zQ-kal?D@pm#J!$6Yb>*{CrB?W>OC7v^q%o?6E1>TpZTXkh&qLB+Q^}9nKgW`;d>3= zYrwDgc5a058p8h++`P4n{sjHO_Ur?^*=L0u*G6Em2MrqvZ^&%$+fgLb6UL?jKXE?p z&fM*^7klb*n*sqxHWszjn4N`jEZ+b5sD*t;_Z5Guxhp3b?AaV(Ywjf|zTZr`(K4&J zh7*NW`W8RQuQuNvU;O~S@_5U$mw2|`@oXKe1#FP5)w7*oE3A^8RW@_c`0;o;yJ>Ex z^SHYg@2*@~yo`0rHST(*aFC5fIQVTX|J*w98y*fGJ^P?%pZ)6e#Nc%nJ@qD!N6#tH zGXd?+vQzyZq@UhlmThZ1`b{XIU%Bv>of_Je(kWa*Cyz${c2a+keeKoy1MP$UB%7l2 zC->c^s+jveQhG$ZU(4?>ejT>%>XLSPHTYf|b<;)`{ke;F5?@ZhUey~geDChP>~ydv zo+T@2n<~l61afoCw&}GE>+Hxu_uf>=PY-98x9J<JE<>KcKS9IWl9hhm_IUcwrjze| zB+ge>waymJiga4eZ_%mk%0Hb>UOP3w59%M|@dGx}&Ge^Dm&DVXS6-Ujvg+F87GQ3s zuXOtRh^spr8?)9VHQ&*gwPazj?fq|8X+2f%SFr~8Y~YiU5xg6T>}LI`DwNco;+By{ z@gaV=H8o9r7#o6n&uM~p8phr!q+QtOQNHBb_2umGC~v{{-Y;{gPxH0z8(r?&NSJY= z{hrU2w_Sp}=X2BAFZtZG1+?J;Y|0B5JLb+qFSc&Xu^y7Wg!ge-`^*NBi<>Jd+&f7F zahtabSffm(voD~tc0sc)V01-rw6pYu$;db9ES2z&WL-OP?Ix}b|0n1Yk}(JIWfzd0 z>}TjQrEkm!$*cV*vK6R2=^@@ct(M>4^64a6@7sV*68GsNt>_e<O+dW1gm1Nv*WNAQ zu70UCiC62F@Yh-W61h;d#Mdud=#Sw)u|Kw(wft)MVwYgs>FiFyW~|e`I{)~cnj3Ri zgE`AK5D{OrqT7>}_pL@4&o?9@$y^0=Znjb`?KO`=pD$l}?OJ%Dx4aeK+gmD{Yc4Lk zi{|3<!J(Aqo~=n`iq>_|zK-;2SJ7N^aex2)3N&x>(Y(z^^Zy;RUh1QD>+7KP|7sg^ zj@FeaE78F?w_jK#UCfNn@?TBn{;$Ga>8tOmKcl`&X;ZylGoB1%z4@%MxC(w6Wvx@^ zvgtky)%08Hb}VGpjLf&E54>8PJ-)u@m&x3e#Dl!m@L*25M<Ztv0-4`X{?d`D!0P?B zWZKdZ>E%JjxSf3Ox(8j8?}*L&-u4<N#N3#1<k=AKw^d})Plht-M=f+v*4!j_vaDIV zc(#LQBs0~ulg-PdAK&-fzO3GmnAb`jGU*YmZTD0D4$9YCudZA+>(T0e%b3$@Ol+M~ z?E6t0{TcmJ<JqPw=QuN4IcM=iN3I5W+4j)ZLi?>-3o&H!EZ$I?#oSqY`L)&>L~iPx zIgP1Sdpi5&P3i0xZ%${WUu~y<f2lQ{?MKGkNS&5cZG{$zksGLQMN)U|--b?LT^~qx z@%u06!`AhBSDJUHM;H?}R42GkhHvdVpF{g-o$39AhZGjsm<vSGQ&ZEQWlql<&b&Ds zh;%rXmCD_7;Tq;N>8Vq!AvZ2U+&veq;g0Mz?1fp94Foz~ez@V{6z#u3Z=b8Lt1fiq zs$-$8Zk}>vzWRKKwWdnm%!9U<i$A>emwA+R5BO*dh%v^M&X;BL(%aHC%ylKZHD8vE zU1iE<eT+5{U#Xo=Ay>5iauVJ>1n(X~=4hU*w30_*%5ex&Im3i|V?c)A&y#PMd};Ef zNh6z_^6AZTt!pan4#HC=ya)e#<k1}1dk0EmlA9-WCQp()($^H;g0J<LcJgSQx{<g> z6E`nXtY<mxE!(AJWi#>07vuNW$mhw+=^@K%^~uWZK3S>p>3rh*2s;nI2cNs|tRy~n zv{}3G#lsOZhO7XW72q;nKc_#r{hYCTL~Ry`v7gw+InGF3COvZO?d+3#nSFBK=`4&^ zbQX@|PU24CtO>|F+==t(bLi%gOW7}nix}A_->c964*BlM*$^-!XT$jaC**9%CuhU2 zL(Y0Sbt(ZL!e2c$K4WiDuTG4N%_or$+9we8^oJQmIm?)iU33#~;Za}w8vJVfYS9|| zK$QBsyjZGZS1Er&Z8;VF8WEbFDxLaI)vcGqFVb~n19~-GhdJX}x{mbCh>uP+{FZKA zjbDu)g>I2QQTOrQ4AOh9!B*rA>lE(UFpIb8lg0h-u=s{R`;CPE<;Ws_>kZHA@x8q^ z+6Uv>X|Tb-+X0Ou+P{MyJyM=3mXS|mQ?b(7i|F?O<a9X6UG<zTt4?&eckYX}6OgsB z6nmeMc@JT73Rxj&%f0leC$y(|Mj*02xBkixIdP}>enZ)n4?5TLzHw0H(tpB9wHfWj zxD<`CuN0>@xF*bg@MTXvc0=!O`e%0p2h9ana+bYEu5K*7Shl(qCQkY>u#YYwkJ>6h zT*Aaz?D0`v?eEf_xHxIz#K%p%S7wMbDpzqcO`PlsKPBH6ks&L5vS$!td%E%eAnr@J zJx0cOZKZK?`+ee<R3UvQzWq7m4ey|rRXE<81r>Ie^A7RN?V7)6Ps=SMZ=+ojPw4mU zYR4I&6z9<xJA>A3tb?QqH`1nEye+P@+Oyci8}I?fLXCN>OpLsfFuq5^X`RoqW_a(o z2O00s$7vt-H?b#Xk;(T4lP{1?m+_8BpbFl=7C3`_Q0`pmqm#Sby<Bepp=_^>LRLE4 zehKfkp0}mg=jdO0i%xGE)4xV4T05O@wXJjCv0ie$_WF2xP}WV0eU5j4*Ym#p|2Xr; zy@xY<7ORvt2>z@k&G;eo*I1`L?;2B%;A>1djK7z2sv5(z2dX(%96Oqc6TeVjcRzsY zp}CZQ+-V>UYX(QD^9Xg$ex2W*T-I13dl7dCSzW$1-{)&{S06HC$u{^!^%YF*QRD1Z z8A?`_cy}zkHIb8^CY$hB7<+5qO4`YUFEjZ?Q<v9`ufC}7Mbs}4D~?B!KRQ1YuVd^% zhBd;ob=19duAzL-LLa3$1n!Zmus7rM*GIkbgdM}3!uiLd8eomV;Qj5$<iF0QgN)B+ z?DE&W*Iys%K85-qv#T`zkJXd9pG%nLv14J>{X)`;e_yN4j1eP}8)NvGI-mb%)Op8i z)LDC9Js1s*8Y_xt5QVSm-J!Pi)!!S(=G&@MZ{Z%^6raypmuN1h_bL=V{qkf`agB|e z$`y~^8*FUsC|4S_t;Qg=hiK}RxiX<Li|?8@@b00`*)hMMPavB}?}w#vQ*V|xhV?eN zoy$zlWYtd_!`Rx%a}RHldw7Y?%HL48i860yEJ#n`Jj9H}!dLt0>~xlWZ*D*E^MgkN zKaP##)LV1#0PQ8-Y@nT7I+W1Ht3zp>ZIzcP+Au^n^;Nx{?$U0!lYNXu+6sosuQP2# zImNfw4Q*6z0^wB$pZn|J=jn$3hNq87=cYUt|Muek_kV!j4$VfdChidWx8e@qPk?6n zy$pG(y)k3?=nKf$8N0}rCZE>U(k9<F<FgOpXrDh1{Ul7DZ<42tJZ;3anY7FCD-0~; z`%(97iH9S+rhFOlHIT1?d<`aF9KYP;V|?HZ4R2rT_;N<;DO!(HowRp5n4s^$PZn!B zm%~pdku%|VGIv6K89hSjj#<U@l6~0!-Sd+QKjaHPk8t(nduMSb(+j6u=BhIW%s1lp zsJo6wU#w-{_I&ncs~ou;b!&;S?*X{ICVk5I$dIGU&2RM^rH2iUPPEb2N&j>5>MX71 z6N(E(*i+*Dh8~iSs~7}#u#m5_l{#11joXIn$L+%Hx5Zh-zox!`g)Fxc2>A?g`*4jW zPUmos^BrQ(fWN;q*`k-$*>6!F4!bx)YmGzt?dc-oeSQB1oMSO?27eE4PbX0y7C6Bc z9vOqTV9x|@^Iw1H-5>oBdvdBR>l+xocH@rYE}23D%8+2(J$!!*!Q6p+5VsY#8|TG8 zL3#g*vnlhFxR0SQu2^7M4_ys$ac`s?+gF~K&+q5hU~>t19%P?{KivO2f&z5Clu=XG z8+n{cPT$_|SNm>!jdH#6{;z+Aw*QwF|No)I9Zy=@m*<1F)4XgTX#b$O&YEmrQ&~qy zu6fRYvv<P5fc?^(kbU_}v4L~!x&iCURytT0e)^o}H+4qyo%!UjWv>|w930v+w6`*E zJAtQv^HZfc*G=<SM>OB@s%a+M=LLh5G}*2QtjVt_DJe)vUHK;Gj-6>ol5G6H*w;_} z(;ZJ9`^GRB|Dd^Xl2@0d_R}vm<(=U&`?Cjc4S#Yt6gd6f)2n9<MxP2znQmVa7S?YZ zUTs3|T=@1n%U(Zt{qX6#ifLxp6>ge$4gYbqm+xx(yt=R*YP{OM<g$SMp1Qt)V|xSk z4_>ITPA@#Ydh(#vV%gSHHIb|BYl#1ViT}|H$^7I`pI-gh!HjL$$){?fv+RodU)<}E z_ux-w+2?h?IP44u>>vNsvL6}zz}{J;oi#Z9Da-!s;CqI%W6)>V=T%zv#=*DmU6Vh( z`t%*29lZakP&8;CZ=M-e{{ML(oTub&{XY6a-2Pd%HXpKQ56pxzkKJA~5UAWU^gup2 z5Wa5PK*(P3x0Q9l#-ZIq8Rbbnef-d`GUpt!9!=$YiQPEhro6K9%AvhOnO|j2z7Vwk zy}90nv&V&V9&l#7(2y^;uN-(o{<+<P@}=7&E|lPPL%Tf~WsO762*!E9_;+ATHZaP8 zk<33Z@Z50t%AsKo&Tn6^o~WI1eZFBvm8nbZ3-ceF`RJr0qRqO!8}j!*)t|484rLAx z9o}8UeCi7>uJ^y3`Q-~rwP9~3sT%VQXQle(A?quPF8E4*$psTBS=e9l!u-c)K6YXL zxuIg|8}@#Nd;|GK%D4OQGew-Iz7Xgh8tTh?r9WtJSaMdXUmglPZly!^i?=mX^0`p! ziQDG~`tmMj-BrUq^sT?YJsOTa9kk!`)1gf2>0cizre8|>sV040{`2|g_EvTe?L9lk z)#Qjh{U3*}c?K^2)U3g&@bInS>~Q%(cp|L!o^|kQyW+B+4xDrU{rNL_^HHxAlqUMq zGCSWm-M+@<>yHed{*=ep7nuHV^Kgyzd-!egU>GjG!1RDyhyQCV>>B&+b#J9lS?$Te zQ>#zEx0v!8`_{TQ4qNX{4xVl=hD<kkKQ?^&;~tdh;HqBtH^Zm@&I?m5Ec-hL9sc(o z2-=gN27G@o<n|-$@d~?UYK2`pwI*Dbzi0QSc4v26_CFsywK_Ri6Ronpd(Zsv0(!~D zd}eiOu<xnR^kUf1u<J*=@-^SMW9O-_*}G2ceed&Qy>$62d+8rnzv0k{y>ENo>#6p_ zvwP|vS6}hG^<}TG{&Dr?&s+U}Tz%;gD_!hySC#a)<IT|l@lCNU9=knS`RYCI7l;11 zdf}0e?Dg=geCiLYe|97QC*Qu;!{>g&MvkaYgXxjq(?X|L|FsKUoczbte^JsC|Gjyp z5B`^K4_CfgpF9Tih9huK-JyYi{i*x^xcUgNKiz$L_4P+o$HI~GZL9zOzM1_$$*vzb z*WUl)+P<Fr?RMRZqH%px?e&X;jSDO4BtIv?L8n$vaQUZk;dz%~%^FN1t-6s_HPKw2 zbeDbU`@hCNukNwu%JS#&Yj&M8JmKJ`e8*l|JAD6B{EuG0a0;PS2b1}LogCPdf6N!R zVBwv<9JOwa+UUZCH@zZ<7dMm{8v0e{*%xT54c1p)$Xn^Er)NF?hJ3~DO9sAb#|GY# zzh>YIc6{K%eAQ6-!_x=K>V}?qa9|dkHD@?bIl1)_cq=fyqi*-^K;uwm&rsFVzmnYE zF!bH$zL)*(p%<+Fb$wlZoqg6<evyA6?|irQfC~vIwa<t89vrB1A$^h2vuxvq14S4U z?C3xva38hjyYN2y-@p^Bfc>k1?027gp`veScwJxF!vXsX1Dy|t`kou^>Z^D-yZ7lA z+%^fX?<?=??kl!ipnpT3)&CjOel_;KV!MSa?1pG4@W<6lk*sCQto~W{(icyy{_qj& z@jtBo?h)1Q5n@8is)>2;i>Fs3Bgg+s-+L^bU6o$Wf2)0R`fmJ->?dBl$o}n%*2k?h zne4#Rp@T`=ditD$|4Es(cN1#Aba(Zm)?<OE%MM!S?#cZANZ{kuq|Icf*e|~r_;@Hi z*`EBUHRX3lVqd@G$y480p0^(F++1xR$Octra8v%Ky_4<KU`PHf!x1|<I01>2dMcQ| zFk`*PqP5P=UpN%ABZH}@I`a3yp=$=i`8Q@ZK6UwU>ZxhFt%WhtY<jBmVe8}7{o!Co zej#Z-OIYW_9eK;{9;`TM*_YoP{&How*A7n&5(ZBn%x3Bj<}#NawE9EH6?<1#zTw4i zK0Ewh2Wsq<)V7-R@aterF*ham+QD!|)au8N2JD+g&l$4pDTC)6423Hyr`q#h4D>%w zZ=3hx;UitZ_~#c79SL<M?Q?4?!fWhvqigIrQ<8Qt66yaAbda9&U*Cx4t;eR==e*dL z4}LtHw#shI&)yTT-#gezPx<U%&`v&Gb~tF;Pgndbm`~;_jr<$U=fC;Z{LnK{uRmP9 zz&^eDxxpY*W<O}E0*X%hxb@W!=I1_r{f`5a-J17@C;nsp=4U_kYz=+lf`M*3GBD$a z6}~JQ315eMXEYYREgBEsi~B_MoNypofn=WjRKT_d_Iz*X+d(@uuxIG5r_cX!<;=3a z=~3s|>_IPgjNBHvBjk>eJ9osuOj{E-?e4WFhC80(fAr?(CgyF*bDj(QbYlJ&3$N&Q zhUXl7Fh4Z>i-qrN?9HFI*Tpn#h5H6#z&r2zXt4tk`%pGK-TLy{hu3`}kY1naet4>V z^NUmM{uj?sLwQpJFGJJ$(DbBqN71qZN<0cBwnyyuzj!D=v+f+1bDGC^!A2HYk5}6- zWFODh<?D_F!f%L93BLvR?&$3B`=eKe{|fi1sG(qGCu8yb1EI=pJ3M{jxm{ah{cHOI z$cpt_Ka-zoPk1o^Rrl<nRggjd_RNKc*5%8L7X0gj9`x@W^q|ZJN&qNRfHE5>Kc+9i zqtyTF#a~5kt)woG2CNh`3{RhG*TZ9BxL`h`VBkrEnMIoZaOEeQUfT-aKgj=Rpg(|~ zUG`+TC=o6fFJmfn%dhOS`vxYbE2De%zL;4v;ADRHd>Ls2Pu6GOfW0?xpY`R+=xKcV zi^{o=yiqINh9oGK8O}%ZXuAid=j*bBDSbHk6ls(ryoO(a`$GNUNF%W-x$H@k?$Q63 zxwipttGE*W@0Dcv%5h@Z4j_euI3a)xq2voHr?iX%Z9_Mug?3q*ZQs%WDRk+(yg*vo z(!Ks7u>%C>qtpS~+DW!6^HtJz^Qu`JSxz>U`79t2$4(?UxtJ6vA1$AS*zfPmm7Ijq zzPr!=|NNi-<Hyp~%$b=pXU?2+=FFM7mUBbi47B%{VYl`o#0CF8{;Tor<ByF0a{Sls zv)O6fz+5(s?viYBz~6`dO!x;Iora!wGsX>YeciFpM$Ax~MGl4Fux^nzM%etW^uz4- z-Gn3xm)<15M)DtBs^-5`%5tuH<>pr!oX)(9<B=UUG^ueKR?*u)n`0p>%HXa|J(p$7 z*a_<Ia^4+odu>RArk=Ob7PIP{9*t{vz#9mackLZHDIO3^t1RYsS*pVce0Nj4F>YA_ zEK*aICf-CJ_2)`u1R0IqoTdBaiN$&Hk#;5e{Fgk-XkDqy*n>O^?2G;W{bjUw?bqkV zJyvVJ*$L9iDe505u$rpgoOo__eB^yT_eQpvehA!Wb1(C(cv_Mh<*A0JPv%B=3i1?1 z#sSIG!rb2MUyk3gbUya^`H`<Gzhju=-<{c$V_jraGHT`*C9U#!xQa`RtygH+OR+e< z+Ee1Ghl)#je2jlhPkp~9JN|`pdKM(SX+u@Tbv<YxW2>?4*m{oaC{UXN+JT@@V6qyT z=(UTtRht|*o}aAR+(b$$-<coazvkb4TDnA>a%7UBP8WU)Ae*+fZ1gx~${4+^ef7pQ z8!MG3C%J)bzKB@E_hs^o!d>vi8P~wKhSr$(%ct+>0%vWN=kjgVcVr$J$kIxsaz@Dd z4qVKf)ujTBP6hg)HZ&tSQ=QV|Rdo^3f{ndAMKuh#6mYWIsH03|TWD>>RBhy+ehqT~ zUDgpvvU1q0OHjMDIpkG=$Oo)t(R0)laACo6H6=TvrfQE|kvG*NZX0lUt@Yc~<kZr9 zAkYyHhJ#j6y_5@vbPHe~?2d*_H7|$7mGVZtk)`>TwzkBH`wJLa1vpl@cf>75Q}->H z>u*d$8KjyIsWv|Gq@ls3NEs+15`i`!fj)&^{cXy81Wi8NW8cDD|2S57aZbx<ly&;D z{@A!(k~5;#cbHAq3#oVZdtxOrMxlUpR?N^+vN*qsWnI{%d0)DiGiD!x8>q265G|&a z|7zy;vU}l#?-*Ss#52C*<2%APl0F#ayPR)RMP^rOd12oFIcM!|%P=*(vDN$zGM$?b z#PVubDBm8wTN|gwbII0ZM{7$wmugMruub5x&W8CpxNy!j{?3MIKx&|*=H0MiJ)Ih7 z?d8%E+MZk!^L$5SN<esT+RR7Ff7zKY-EIYF85tVlTO@0+8z{bG4H}2;wt4YJjYW6c z{MNRPra(N`r`wLT&Z`0^-FmEbeyP?nGU}8LNv$H8EoDVkraYRmqF+4U5nX1+M8mWp zYYlbUH8L~YC$Qtm+-_kXwXz<82C>#iTVg@RtBlCFy^gtI2;b^F&vALT7xFrFp6|H4 zI}3S_=sf>%d28G}(PXs2ykn+(xQ(aMZeB|v@7Okqc}<19W7{a^wYqt<A-e1gu~kDN zb4s@#*%5KVPFcGddrf^2UW$km2?`AQu~O{Y?wmp15~NxwR&33`n^FedtLs57<OYne zXj(KAFs6n<F2+t$zs~uxkL2CILaSCj^>*5fd3U(>1(+ZwjP8z|9lbvsFk@{yWsKZ5 zI%qp0V`&{qosuaXc2ehLUPyg0<F+x9TAVqUdM|wpCRQ?Kgai}OhY_hc;8V}!Ud;Y& zm=d+GfcM{qD^>Gz$)k0_DR`oEdxh34ulkqVBS#^?{4X)GkS;&Pmh?i!kYmJNRX>92 zn%YLA#@py_&%=M@wC3`CUgo+Nnu-_iCh(MJDg6PO=S)qV-=)0YWrl~a*1^fRxFPP9 zRZpNJG4*+4DXWj0nC~IdBv;jntQOcVQ^Oj8w!|Aq&|1BIDbyKg+v(0-4HsbL6F5;_ z44y}!q=mMfZp%7d>z*_9T(U@)`a7KVoec?Vf4kGMQ^thcE;G=vbA0K~5-061;07oD z-=SYUa6JBo<zfcEu!cDS{GkQ?`yCvhv60?Mdm78CTWB}r)3lRZ(N-^Iz1X+(hvy>w zkWq%lB~YxRBcb-2R@+YLfnYuR7_0+W^lna@lS_>+U6-id|KZZF9+;>J3b;^z_?vy1 zd|Y3|zAe`9D0aJxyY$kveDzAi3a3O{7vKW)2Dzu{V@%0>h|0(G?42}pVXgz;9pDoh z1*KM3D&$j@8B<&LhWe+kqwSedV)s!m6qB~#rx4cg7Vj;jROx(jg0~2N>3n`wN?xd9 z>6DnM(`Vj-R0$iB8V<k_|MYe7AukzdZ0%2W^cuG?0%7t0R)}3HHm6me3f>|*Lzk&C zyA5^o)nFZN!(08!<75(&Z52Ha(Gu|3VzIk)>vu_ct8_vV@f*x;Qmu)%)3Ua$h?QvT zz2qiI&!++zRs}an8^x4&u^*_5TF31hm<8@S$BZ?oK<J2lc|m&kV!>NPuCk`lut)89 z^A_f((LjHjdZuSQF{1!yXiPsQ+8+K4I$mtAnQ2C>2Vbq!fxoi`dFNW3Qoe;8pOgna zm(~8Rp2_J3yy*=+CuC}3f5Z!S#6BC0+%mz~fV<j5=QTP%QsIC{{afyNO8O{KlQ~7V zQs5lMRw!Pnx#^sY39m4#WF99@J8;C_t>?d3D^=2;kc!<)J+dmP$cRm^u?kZoCEOW> z<bjH}17$32=z*?CqsHu*y(BlpXD61u^r^MSld)ny%2FO~M9Sga5j@sv>fq_&`F2fF zcuzkIKj4qh&q8q*@7p!JN5kKt;o)gu?$G?BxtwQ#_v-rZ(C}Ujf2W4`Y4|%eyieDE zr-t`w_&YVcPs6X#@Fg04jfOAL@M|<Yt76(+qv7@1*lN}AcnnBy)$o1|->TvL8opJ- zi}i6-YwEcLPrifBguCEwJ-@;;bvdCYGfH@#d24QWp^tJpziCfOGnbHr^#daV(^)&Z zr9Fijjf-?G(1mnnz|ry=&TXCgXX<&APvz1xWnNhaQ$wtcT%W?r^|#bLhgSQC?eAkx zw65-G^*h#RgEKX?`{IU#p+*kuzE~`eA6;W?^Mz)^SwHJxo?wAl`McrXVR(yqt+6%K z^Aq(pD2w(D^<+ArUdzc-E>o_mTJx!rbh(-xk(B3oT2j;CoX9iSpkdnL;(IZ>(Ocau zn`d@=)Kxj7+j~p-HecAQDteamEwNr_KjN;QhTbKiFg!>(+TKK|@$N|2WS!wr*8F1c z?o$yftaS*Sw#{d{JXV!rchEX5bt2zz<~E;5JE-VGHz7&DqVg6Wy{#0!uB>F7HaI7B z$r^0;!0x_WGM{{JXaja;dmP`%4KsTJSP%Ksq(c9Eh5mWz`R8(>-YVga$^u4#4Ju%r zbc^Wq64lR+Q5!xt+-kRgMdc<HHmj0LEJHQ-97<i13E<Jnr!49fdinVFv`zu%kjBdo z7l^zpR|_H{2ebr@!8z3J5$>V~B|H8BtK&U&S7O|rvH#CVRy~qHjN9St%ox7x&X)E9 z^{saL^gzzE7(47pMs=Gn7*IiQ7`JDo1>b<WDL39ZZl9YqE(-SkqTpFOf@f`?v)Qlf ziCJYmPTAv=oU%Cnrno<F0UT3fwIymZHTdi1!4+p^=7o)I=Q-817m9n4XlC5I#i(5| z5NutN>gcU$oz3UGR`JH~#t)zC&-cGRl-$h<GCs1~Iq;c?t2YDbJJ?B^j?66hy}F;v zJ`lgd*`yW+#_TAZ>2k-tPDdOGI^zyF>&$wqt_bh?THoDq*m=*{Tviw%Z*v@&*8l00 z?a8N>r>~+H=fU;sd(Ipvvl6U`+j`4F-%A~YXYb1V%wY_=tWNyF!W+q4U%v0Xp=!q9 z9w+#rRKJ=AFUlzS)tNkrJp1WU@1}QSyd91@2?<^Lp^{$pQpD(n1NN1rnuT8iCu(hs zHSY3lL6*o$S$4t158;OfR=5G_-m;k;0{o<A_iAR<n$4CvoGVdzJf98fcX7ijJzecI z)6b}-z?|_(8xK707~AGLXR{|W#l?oc?H-Wc?M^0ld(~V<;*A5z$4gZze(>?%ANW+< zh@DyQjTU&oJ8rMgR*%Sf@Q;q$*JZDu_Gh!=Er~hTIh(x&ihGtiWxIWjNAru92m#sa ztHBB`&j{}{vg_9X)x9B?d%gts%mH=*^Q5uo%#=5fux01Q8`iTxw|6Ldx5K>c@^oH& z+{kz>8M#Gh@+vKpy%uA|INWn|96THT#yA|B7>A~h7ze8`4&tvss&_w-HKiTuf1H^j ztNSB6rrcYxN%vdq3KcXBHM7TbR`ktxF5Bhp?Q)hpR@OVqS<vt4oxR)FTa`3>7xyme z6)rPfc@&g>nbk-vG&FLmJ8-h*1M->kwB=(y$O>KkTIf@jIZh{OIsHz$GynDN*E#_Q zU5V!eZ5Xq>=)RccYeA+q_AGRL;n*JSDqLNIeREE{$&vlovQ#wQ;?!U}EX?G-@P!`Z zBGucj>Z+ga8@CNC*|O16RS|!eXRB`>kYYcalUYwK`90UAKd@_nIc;=7d_85(pRjO_ zZ-F)|LxonJOn+3(v{)G|)c#D`#moZp(osX*HcD%i`8{*ep#sj9Q-<H6ne;kI&jcCa zu+@$YNIiVlhA3gJ=Qj|1*M^YNl_9Zdr%F^x@FVNlPyNGLw?}7;-d&J|@9((I38}9{ z#1^}&XC|7grK7;-td_^@_jCB;VlUT!FKXV8Ufb%OR<8D(<yUvN`qk>T>FP6$)79lo zGnBtYB(?RB;VsO0>&{Twz(%+(VErUimaL9<s99ETsI31~o@QH5hRSwd$kQC_K<GYo zs^w8nM(a}^b%02K&(sD6xT~XQts{E-Ugs-#?yhAY%i8L7t@N$lkZbv1sXSQD8h{l8 zb^=^SPB7+bM>OSw<!DNgVCAAIw|cdv6#hoL>O8S%rl@CgA!h~=1g<?QzRn{VRxA&e zS8Dyryk&hy&8}4_wMdGOmZ^t!SsC_xK7$Ro)yobBqu_BNb-4%2i}2LY;56<uu~PON z7+-pqtR~%6Gc~!T-TadM><{eRpx3hQO73-8$$_y*48d8iN~J$~RcfeT9k-S%K#BEC zoBph8o$`xz0<xcJ&Crx$u6OBC>zv$8FG5;(5&!ev(1}RCY8}H-ns)8e1}qj*pfx(` z!E)o}`gyf7MvDig5V<jaljs?qLNC|XkiNcW#Xy4SjH9Vn;)iXB&rmC)<$;&$uZz4~ ze{tbS_RX%-&tIwG=~OQ}g~D;yMP2I|yV<3o-4K@<eTu7-@Lv1kr+f(Sso-+TE$~U` z1R_07(emX4`hguu-?iL<dO?wUz?2m9@KI`y+Y6cFo30_ZvJt6qS6uvx@B%zDX1}X7 z1lX|pFUKPJJ6YLl4$x~yYKHT=#Lhb7LmIKD`DzLhS607Y-@ddc(E?hcA=i*-9;3dU z`707@0aA@Q1uoT<S2~yHS7U$N6(0j5kra#w5LZ>+RLTAv>EYA~s$nz~H<s3rp5J{* z`qavWm0tDFQ0+>j*fpak#xJb=Ql&edte(JE$FR9=gsa2Hx6x5(<Eivj;hVz8w$Y*6 zcq*OWU7bEPybw$GXd8FOFARSv{NXl^hx+E|E7{|5`{w9&XgNc49996_iESNXg(uc+ zBs^WH8knV`;gfaBEEVEOU}mWZPxOQ*%Uux$qUcq4lr(s(#=r{q_nj>3*g$*lY@mep z=Jp~ld}!@|RFW{_GLK~a;mQ+P=euhlZN*?0zMq!Wkn1x)sbl=RclG?Z<Jdi$lRD5Q zy~Q-~HGZ(el_>Sdm<8fT3SD`z?BraXd&AzEGcGENncZ*LzsxnLKE>*r=Ld7fKN~TR z>c~}eHn+=jNjJOMx#o78d_%pT(_R=P!~APRo4#dVnDc4hsJXpGR&0SE4qU)0C-Y5j zOnX^EEqYC*;~IE|!s6kA7qsNUn*-&-ltlBg`XK!_(b=rC1?D!f4rI-(p9O|F%Jb_t zFhh{d%vF8`ELrjBHLhMS9@~0AJRp|adf+Ch*=;>=lhmxK6AIkqwk|c7X?PctG7axy zQl{ZuOv-@Yi9W+xQ8U?B7N4&>D$k67HQZ3X#od#X=lhP^mHgANUwJCU{;UceJ9b<O zDSl})pRCTXJE3<p*K4`Yj?cuN=AVe{o3A~QsS&rdXFI;u?nY-DBiz_il1>i1Hb9i3 z@LcTYDfupXWCPCI_Fjo85idA<y<i&l-9(?Q#vX4*do(K9?Im?rzUYlTvSYH^gS{j^ zZC`uUKznb%kq8&dk@%LQ+<0V%8QY{Sxw^s*&ssf-+TRgct4C4$J3{M3w#gW1e%E`? z=zSw>)EnLRPk48V`$8r@UV%KdP%Du%l)fzopC=|Ettd|}QGFS~*`)|^y18BXclG#q z*;5mWX^x^75=HYaQ8X7jRqea_u)v(MUCo-xGG8~S+JMp3mhc^DbY!idetjSpaja~k z9*qt07I!3)!NlA9^qdEm4Js74JHA0h4Ovx4#6`>I+cwHtVoke8ZO&CY#kvZ<ZS6lE zw@(Ex7ke}I7Bi42Iyi|@!A@lrs_D~@w;b;vUZ;^1@j<}-v{(vh@HzY)tWRYg0wMl_ z>zQ}DPD|lCHq<|7<ogqYL<aHepE8#Yj-<*nN9;JYJVxY<hNdieIjPAlE4vXUJJ#Ng zk<@(JfMdW3%-|dNg+3R`1=`qCHZ3@(IF|TX;UM5f@>{b;eM2IXIe8Ghk@(LE%$(FS ztpD#L=A&G<@N~KmZy>D%pU&0*{c!p>Sz`&_Z~STviGNG~GQ03X53=V4@IKnV_31JD zlew+gBX)nT3-93D_7`(M$r9U9(2&BNHUD0r_krr1KM|p1#10Z$knal+!8Dtm9aI<P z8XfPB3P#$U_dkS+^YtE*P^!t<=uA=PVyy}6$0lG867`4mntLrP5Pz>e4#capT-25Y zjtfCybn6Yu=)CF`v-9d#ZcrYcEJvQaJO%WV$x|h{F1|C7**_s-8##wG&^|nm$qLU< zhC~pmyLu~#0P|ugp9ek-JDczb8PM!(ZIMxiy_Tl9QLtS^>dOr2a4fq$9(LZcr++0F z&+qnT%9L|i(B*vANr8kHdWhGz(Lvv{$NX*PccbHDrKEl>Eg11}RngnL5&vrU5&PX- ziuon`WyKMZC;_ZX@_x%KcK6CYobMqweoXHBJ1nOZ9&Xue#M+&JdNo&a%r0A*D$$Zh z<g5`Z?JgreKqQg-JD~oUBLY`TCOsEfiy8Ewj%YD@!FL1e6wC2VtfAWD<1t@-fXGEt zd*OxNvQvWY)@#igO3c&Rx;VERR0MBYLyzchorZRk+NER>rV&4$@Y#_aOLF7*AdW`N zHL57FErMYYwgC@<$SN}?HFgjSRO-qRWH9kj^;Se`Hn-y|E6Nwc?A|iasOAyf$!EbE zTBuLweJ`(bdy2XA2pgL|iC>(x&@Fjr66jzJ?aR77pETHZ^o&7rB>Cnr8ccemKV5BM zIn$62<Lo6{E+$Bc2EnjSdL%n_M=8<~AJcRd+$&r<v083aUfuRWGt|TDdA1Z=pFAiL zu3*sfPDWs)U$RcAp!9f5J|lsr2Py|5;XTBTxO$+&F>e&RK{VW-(_zbyUub>fM$y={ ze2W!;C*wx38S1Rr%;Lsg<3{0pS0@zf{O$jfI(2==Vp7mIH;Q&~aTAV`b@rlbkY?;Z z`uEDSNbruGft?MGy9+fFUosIl%uVoTe`x_xEWRo;CO$>#3P~AyM9$4u<CQI}19eUG z51VD1k0=t|3UgQ6DqgG<{I}RANC5521tX$U5}xM+&H^X63R+Y#(>69b?O5+I<d<#( ze)MKa^ep$P514;4-x*tQ0V`V5SRTbGkRMo)Hdnb?Kt`jmGX?xYEom-XC1aviNk7yo zY5<Q$9Y?D3Y41&R0ng;*Q*$TkYSS?EU#Gu0k>1oZjrpQh$;k3KL20O^_rz#Vw<H`v zdlUIatcVF#RX}3P%vcF6>t2W29C!AM4rCOV|3)m|H!1zuRXpR1wVs#JAcwl$QF8`L z4;0eSh7HbJ*|LH9Rd~298B?!VVFHhYpr(P6w393mcv_NtU#GcqO5cSV|HhQ0h<{0! z*y8a)?e6?;fBNtqKV>|k|GQ<SbfLt@d8!<rL&+^3YmO7?o$o9nmUp9bc+abu+@2|W z%-B7tTuLGfZ%sCF0$^j0l=N;V4p2rAohnxQxf1&jR=RgW1A6I>EU68GRj^?d9IMCb z&uO<u8ats(w@{`~8{==WW25t+xZ694whbIZop#4fFH5zrLYIgX)HwauYYY)>E47}0 zXW|iEhwg*sjaM@ju}AW9R_FsxALw*O>1BM0h5AFq_8T;xN+eE*m2X?3j6G{+CX|$K zD2hMBikr+!iLen}z<kqfoGjiIX0V25Mztp<ADzkZ_MIKftB#%Rakpo>HmLU|x(5D& z2W2<H6z&gXNz>z?(;8L@H>R^5;pc!m9v$%~Sc?|;hqi<h%UyZ{`%(1nbNMLoUXkV# zTq;sob0Ic0J0r)`QX->P;Csr`x;qDiHnlD%{$JY`D)q_Cwi*+jeNBmX&>Xrw-F`7j z>A%uGv$fFvu7WIC)5Dr1ZFWoKl4w(tGZ($+AUP9p6vn3^M5m6~53}=?PrXaZ+t?x! zbpjltcR1zW4>xN`(9-jkl%_Sa>+pbYSgbwKUJ|ijI$QeMuy%fxYk1V?3hfN_{xDh0 zFZ4<xrY1N{biOMQ<f%B$r5Sh6Om@IcdSK`t9BsdpRf?ACmI=0I#?5yl5h%IEV{k5@ zN6T#!j)5l)`DAC>dfuMkb2maM-zV}?_^UB-ekR~@Cq3>+oHKz%<D(*PnWLKfs8`oz zX3oeV9pNYObgu6yO5iqP*xb5{^*)_OR;{wOc-Y~(ky!EH+da8wG+&DZYD_$yZgj54 z`kT3(h*6=(7EiUY3XMc`Tv5U=%+MA+3-n3f=%uz~!32yKimpS#p8h;>4q@Hb5bcrX zYEU^BP?q#nZe+&+4pl9^L<(gj#-^p$5WWx58raQ*7j-$Kr0)rhA2@iL5~Wz}x)t=D z(e?BM=7zLEOW?&UDBuw`w-S582)lY$Y%er|>mx<FK|QG3mZ(T;9jh^X3(4T7zMl5Q zv?kP6S#hNib|!5sZx@*hZIG_B5{uygdM$gLq#|KRHAS-1d-s!+Dlp>{da$Evu0mQ@ z`(lUf7jn9V3EG%FWqpC*&FDVShsWjx0wsE6kw|(yBdZ+Y-J-s8QyZOi;=h4|+MUM4 zn|OJ_!2AWWQ)$}j&q8aI)>@p%!a{D*9us@~75ffWRQc3YB1l{~R*D*ac44hP21LHE zbRwej&vte0_t`(&Ct=0AmeU3Q{;c%Fnw63>8_860evSWH&UlRP2s^=hBaU%@!#&?} zUUEL?3^|LP$6Q%O5Avyxr^}pRjMD=NbFk4N0zB`BQ)Z`b@9kSv{)>uGzOO8ExQ}RV z`0$k#M%*BpTh17?adyITO8UY(X<y5U=AI82rKX<K)4wCd$RF-2-7h{EL%q5}R{gE{ zeBWbfQ|})#`#Ww7t(bP%DN9aVFk|-As_CBUboP4{4L`fC>?>0)_Sa3W^@Ym=-qGxT z=8GkyKeY~);r)Mhj`n5eF@1@qr|G`b(3d9Nmr~uAiu>-6-r!BnC(AN7%)D~i7f(?q z&YMxg!9=6l!@5j*6LLzDwSUo@%Cwm;%SeyDS8)t(lLFp+av&{xp`H2v<Xo|QAI0z` zFdTx~k3sEYF+A@tFf7p+7HBQlodR|<z;60~6T2y3HyO&6LphDz<Ns~!{u=#|Dn)Mi ze-*?3KK=eWhE4y!$FTYT6AaDmCD{&bn}`oW?7w#hi#DXYy2Nj&H73^ER&P*ykOS@R zN@$Bme92qAddC>+O<Q@$UG`nHl=FxbCZBZ{t07W-tN2xrbzYr<?Y&BNuso78k>A8B z$19RL=o6^0ca_L%V`+QbE7~ONlQNZNY^j!@O=78snshzXioTLHZP~!mRUL7OOfDN} zmsJB#UUW@8(LViBpY}Uc#KKN8x!$QC@MKE{lBxW_2WhweMz<B-ow6#$jxNR!tCXLz z=!>xHZ^4@|+~)XM4Ln=$v2b2>r$6<0?%k}mM`P_;KJPBrMr(R3qLU8~cr$lt3|zab zL~us7R;QtlmW{H?b9*B6L5~S#CUT6}Gx#l=box?V|FOA$y`0!^|J}BP#<H&bueBhy z8>0cd+cSf62|t*?)y)wsKBp}zB%$tkXMR`Vx3BOmD|+}2`yPH{O<-mDrvKJXH#NY1 zYeV9#1DY>%oT=>gz(Zm|XqyXe)ON)Coc$}<0+J&dobmL4rSz)l7^;dVMeOp@cFoh+ zO+V|&r>19uH^PAho(<k8)<f_{#-b{CBYYmLyb-&h(i;Pc`i_Ma9xVFQXBB<vtO}(c z@WzCW?wIhR7omf4X3P{1PSJ1U%>-|dmXm#l`raBo^O)MKE^nu4?M`B|r`<@OqNeZ2 zzmu)lUb^1e7;&olJw!+uS9<0dg>TWb=U#)J<!!37!~P^TV6SmQRi$8El`?LKV2AVF zZQKwF%adO$9U$aa>2~Ah@-0TUr>?KlxEWf^YvwuR%t{(J)4Tb`&Cnw1jd`N(`h@s% zNsmZeDLVgVdN)r-!JSo%G+we-az;dU+uV5-)HM+0z;|2J{dRfk{T*vMS~oX$)ZqDV z=`hrJSbRkIcK-t3u=^{GM@2lA64|np@hsoi;cO%li1R{S)rqR1fRpQMa>}~5sPE^z z>{lC6_ji{{v-6NlRwrKHXLN0J<d%#{!!?~P4kz4ZdsR)sm$v31D-v%HN;Hf5b;b4w zYuwU}r&7B|*B&AUkJDILuUZoiL@PP_og1j;mJx|ey{qT<sXy(P7LVrqX`j$rRwnQ5 zsCA}nuILE12h}qp%^i)-PjmTxFP8PV{ZDwE$L(t+exFn6<Mvg#(!%M9k1F@;iE>}i z<(5s9`)r{canCoyO?4jq>C>Nn{rSm}xg(YJ1~HuO$x6;f!qsPw;2|7AVmklyN=SbO z^k?TtxbPhX!rWe!N~M4Uin|Q;PL-q$d_>xle~~78@E<O#&--9Ye02J4e~}(xCs0m= zPcC3JqwxKNT6mLJ=M=H}Ymgt#Kl=N_b-FpOlpC|}nedY1jo#PBnWj!6OhwXNoA2b* z*|p4Z;Ysn%6K%S$lUO&G(*ur$FGS$?YAEsI%ZZ`<fN$UF_^#U$-a$qKE<uao`I4u< zo?l9=(BForP_-IjI@WR2`HfS4_vB4e?yJ~fbX6rnLtX5gm8C4l8}D%LjkDSfcQ|+R zU5b}pZ1M_K!woW6_0y8cs>JWXaADOM$~%2Lc801Z(qKAP?Mz}G@NRUO&U|d@nM6u7 zISojgMk2EV)yX8c7;yW{6k_tvP;;tISBom8G&j@y&7Pe^G?etLbh}^US~g@kClMVI zuyzj+1ItXSO1!sE<W2D$lF@aB3K_}124`k>CwE6!U{f}*fx8Zbj*L_K3}TdA%&c@W zX{u8ahlj`6S(cMYrLjQh3{@4x6RCf@G%qiVi8U;v;npPQxZM2-yjh)$8T-kThTWdC zORjUJ&p|9Ju_gXiO?MV*`dcu!7ho#3*Ez-Z!o%hkw?!)}e(@I0HM?z=4>vhYspg(H z(}IhXb<^J*6v@Nh!4{9>;#@IoZY^RBO*tLl%`{Us(wpoHCf;I&Bqfmj6D7(gdMWVu zVlqkY^a&>30aixhufsO~P1uS;y<YS}FkubL7(1NKa%+FLP<z=x2O}UJnGJ>LZ<!;- zwDl8dj7m2>H1d7ca2S5XJ6gFr#f?#k_w{&)=j(8)I#W7$Fcr)=Xnb~Mn5|+9S7jy* z64S)l4mlxW<^GgybI#H8+PJ78@iM6v>ubq7E%yT7Gjj*=i@E3E{%Bv1Mq*b;d&1b~ zt2AQg)YnFhz<8{K9W8^;a0p6qvQ2zo!gaDsRg3_RIp)J-zgYb<ZVXWeSBCHnZARDm z)DPTRv5GdTaB!mv@LwCGE_STBJw@-(`yMpabo8mIKAZV5G69*x{&IQE2>WmicqpZ& z=8m;!rF&%uL4|UM@%xmYJ@TZfJ`LpbS@|R<EL`lZ4jngdsyo=hd}8I9#+6Q`x_b0m zaj)vS_Uia*?qSO3Ry%%GSH#RPy8P-F#AxGP?E0~qS6SR0b8#`%KMGdN6K=A?m$+d- z>Yc`I0H*pSH}ULWb|!uCsI?hl`FTD_Kjbbj>CtIm4^6S5evEXK9=1u(H0CYhLB{Iy zs0WsxNhDZvhbPuD(aZVj5A<@pTYB${RVu4aKXp=i)=1KFdrQ5vb2dGmA#G2iE-(na zVeh3koG!`u*L#(ke<bErUyXXyv&$BP!?~I+(|DSf))ev|OP?TjXXOV@*jJ`TR+iy6 z3})W2AE7pnx@e+Jf$4~s*9Rgc>c!lV7{9q=2wHQ#x@B~&rgTfZgfn~|^&D8`Q<p;< zxAhWElYTYQ8aGvT?;CbAHGgbk<YcGRr{;zv3gwUX)z~}BfUMek$o{hSB+W^`V6S1+ zx`Yd;)t7F-6IZIv59M9npq~$MVsqrFaHbf^t?7?t&R(na43>_%VBG$0cGMoF9=M4T zn{<g6)9Z9ZheUsusO7Z%)#$$#;uPHxYX0f*<1>TtsZ`|`xZ^oy|A#x)vL_IOUqVH0 z7_;9?yWB8lvuhO-%1$G8?^UV&p~;Ndfo0QxKETL%)Znr*{W&ef90`tbcM(vsvd~=8 z{8R5SJTi~7Bk%~^Q63$$zmt949)_ORWX3yJw~yKJ>{@2}|KJvzCsr=@X*xVKnW+BF zSv^+l4L412@|b;nW?7BwDjbB%_rs%!K~HQXi8nf?IV-f*nM4$W=5~puQCDTm?lP5M zIgOj7WR^7zd@nCgGB5NuJ7A?m{|PsIdd1;Z%}?~~{^g4;DR(9ulV7<QI-G+C_V^iI zs?MNaWA^Io_%FunFK2z!WQ>-@CC2&FE9S<VTGw>=h%<ZFdEH(?k4;sbZn^;7r#^!( zuGrIPO?%v`57b8M{MKz9+nrD%I>em~UsR)?i!TE9d>0Z<YCii;AgxGqRJ4UJ9)xbe zcx6QH1t``Q%C~8l%4i7|MNsEWCa}m&4RSx+tNkOx63wsT*dOtd_D2#=?^}zuI>#LW z!|YnmzIKKB*`vqPNocy*YK-geklWKzweBLLb}ccNS5ta~nS}+Q<;yhWi=pBf=A6|U zuipEbJpu*LXA_dfot^YN;zLrpvolB(YCa`<Mo6QFCNuVrGG2|UhSB0PR7q@VK6S+Y zY5Fz$H@d#>xwDepJ+s^2u|-208rtC8-&)N>GPB3*>BvBlJ^9q%F}G#Les-@bamKg{ zNw7Iyp1fvrwik>W-4>VuF2*8Hyxc{2RGuuhTn-XySWsi8I*>bJFN0rnFAC+Pr(U&{ zoSkkCv*l=w<MypttR!YLaVObQ_-1Zybw{bX^CE*e<KWlU^bLJrA9hQ32PUXPOofh` zIAT|2^=w8fkK0S=Z%#{6KTi+B&vLrw<C(Qi>1L%K%&m3s&!{i!Q9mjXw_h6p&LiUn z=QE<5_M73hhz@Y^b$jwD?vVOn_E2(W#z~IZ7o`1Nn!acy(F9jSB!;9U)4|GZbf9W@ zJw9#8UmTYE&U}U0DmSjVrN->p+5EsChT5H%Cv?50A9|j9n4s0ADPnbdI5|ZGyX^4Z zM^ud4){vdai9NwiWx>vDLe7FkcZphtpTxBSiqV7AMx7%AUuRsmp!0mHP19hOQK@{R zoKHgkGPhI^zOCB(s(l+=u>2UV4Wd(o0v^??c_4@c@u-!^X=>}L==88=Zj7#H{fqyg z@7*Epc8OW+jk)^O=x!wP_Emd1wbr?{vX@1aPf)`JU72i6+yo=h5nHZlb>sE=UhDgl z#JISpq~VAsR#qabhL_16IQ26^9Ypv}Kor`fF9kjLubk%mgMGxcC}{UT3$zY7+!#aY z$|$$U;BTB2)%R$zv-!i+{3t$?d6&+UJ*<YFx#0Y>p87gBPI(ql@yH_M5B4AF&$(`Y z*d3Gpl<M83`Vc24sc{42=GScyn;0rBcs1|p*?<Oe$A?Hk;0|Ib*3*`(>`y=onb8lo z)Jsc`vts{)y?LS^1KCTXJD4N&Q8OyHK*@^G0^;9*HC0vGsFmBqxCu)9OoeA3&yQI8 z=ADpgE!T01^IF|obhzy*vLxkEoo#KsljJmM$Ut70%DdO2`gG1C<W%S~eq~q{;z#4O zSJ0X)=R`w3BvwV?X&z5fL*6RaP?MF4Ox7t#Z;1{j&#UsaO9s5^bxy)flAWwDXMaiY zsdk+re$^YSGF_vou56PWt_y)iRh*ym={qUpwzD$b!!kvG8Kp_2%bXFI67@Uan>j_* z(K}hqi~I}UQzSAkTmlwT3i!C?j;*^!w<4$XXjh-vbK8Iyz>kRiR%ul*zM;)jUj(|b z$Awn<`E*@!o_?0LO(iwTO|9}AY+b<jWZjoFJ(u$=rycI<S)p?c4f!3OzZm&Gp8<{U zmC!-x`9*7zrX8i*W)DoFE^5;KFCoed?gOTjzLjgL73beZ?5lEJ{uTRz+++>q`V6=` zgxKp2PPz+aG^ZSwB7J-Xf05jvDAq<_)FZdzu)F`h)-sWR%twi#U#~T11fO2fUxsDG z9y2qPC>W2^f@a?6tRCQQL{409bc~3rw`OZOK073<d097e`)O=yh?q@@InyiY8N{5e z9+(5%JDFEF_n1$GUG0Q~A%>DOeC5~&$7?~i<RR*s!%PzoTLF_o39%^L5=A{SFd-F; zEl(sXiu%T~u%(U25~Q9PO7`ytqmLy{95m53)%#wy-vFDJTnT`!Vj&}q$lT*#UmA92 zIy>$zEzBQrDwG>-Pu+-iI1;PQm~)IyiD)3=V>p6-BGNM=agH^K_Xe9u2R7Q`h)-ie zn!7a_KT;Mo)zo^_`h>&<T6tEa^JPbo)M!Css+X>^h_3xzP9Q%T#+4l}+iU4fut;0v zSt0(=u=EO8{1@U=D)d9-9WjE9iVJnn#I-z&7L$nGsPi%_go)LImi3Ykti%(_$o2~z z=k7N<*Wy)?Xu_9mVtZ3(xU_V&1GlS5B&gIaPqm?qqJtJR752#g0uSnT@pw|K3cZhB zggHRO!&2m{=ElE>ZoDwwf@SE&I8I4a>@WJtkBxEkDc?N&Ka9e7Og`m2j@;6G-wjvB zjV_<s@|9cW`_#FsIGx=s>nS;@y`N9?k~)9IqR==x^0&*T24yX=h`j7FpZ=VqKd16} z&vHq>cX>;lM?Jh;av$PTO1qx|^U!js;i2Vog2t6Z^)e$LSnku-`W*eaNZT({!(-ZV zlAMv1bC9d`tEN)xo@I+DonJOJ?5E`LvPJ08{mbO`<^7~d${bb<`IS>?^^+?Wg-g|~ z7y0JP=SB0u?1nj%&S|_K1lO>$iT*#byq%MZm(#l&ZXlXb-F8E?5-T93@QvmB-W(bi zDX`^kXL0?#tnVv34Rzu5)_hY%uUb0aP@ld&vd~nEuez4|oIZQ~(glXP`1)%X1m-WU zzmMCL*hA}kacCAEz`LFEFPHL)^0(e%0oQU%h%$HF5}}q&w?yX$7VuuaLYY4d5dnXd zpH@D3)rtD^bp3gr{``#oynMb;@0n$D=>4<M;OlyR$?4rAoG=in7V%W7IiuWmifuH9 zdB)hDYIJW*R1Q^{<~H^kRL62FZbXuO+ng<rt#ulELrzsFIk1r%zmIe_IZvcc>9&Hq zQ{w%9e@G}QcD$?<vdhl1<bDc2Yy2ly?up15!f&O8hrUy2VKy!JY2oQ*A8r9jsaufM zyWE<5PMSM3S-G9(g@4gaKTXsQ1~?HKbgJU>vF2v)wbU%DIq`;G37k%eFe~1lBm%>S zvvM?F%KRi@=`tQxS5G8OO8xP9x6bFWRHg19{>|pZ^vr5!F>(BE52nxqBDyqxpN9`h zIQTrMdGGSo$R77rGl4&l>(0u$p(>O|J{;MBg|UpCi@;lUMZwoyK}2oHsdFZ`x6_xi zaxd9p!HTb{l2g$#17?L4RElP5@hZ1Fb$A?fD!nP8U(YS8WE~@srjj}z93Eb7a>tSW zCMJFXH?l}=vqH`7EgKq%zpUl_LW!0T(wF&`^u=Lh?x$R9JhxZZ6CTb+Xzv{LR8DR# z72fy&Jg*}TWGQ$)y!@g#w_h_S9#|gY^SNd6ndejHPzc-%^+9?*koVodRbkFN&P_<n zjj6tpX>`KsI)2IgoNvjDt|Z=AygyI!TRf)3gu$J&tW`@Qt@%`hRsSciIyEA7zNMdU znte`v&FHD|OTIcMeh#N^%GA@8EK|>{G@13!tgH+-Z{FaH+Sd?;cMfMc<c12}4luMC za{3JQBKN?W>TJ@XpvL!LI^TCcF=BUf!u2^cM*S+e!8oM#663b~p162YYZ4X1fk<*- z98YSQdTQk?FmCGAPxypuxFNlfasLv&NRN6sXR!v_zid`WR%FjYYw5$EGoN#Oc^Nx$ zNV!V;y=LhdH>)t?jza$&4D-uOZ+_P)l*nmZ!#v5zjoE8@s$E(cGJf*|X6(wECic<W zxJUNh<&Du$zGJ8G=KOGew@`JMQc+^Ni#2hYhPo(e$zGY}fxv0%Jh(iku_b<tm86UJ zF3L+AGUjssjG=b!E0(EKx8kjmJ9Xtgzgg7OxvVD6{vh-=18>?-px+j=3s?O86u<px zSB?wE%n!LzTgETHvJ(H2+&X!xTFhSJxIGzrOGdaYuD^kKYNaWhqUkO-UIfv4?$|au z^I7A1CvZ91#;j0+^H3q~!6;IG+`d$M8fOvVxJCP%Dv9cMS6R|hrRAaS3y=fu*j<|T z(P|@i_RrDZqIaGGszGs%MdMP5zqCjNH_uoid2eJ*O%o&D;QYzH6uy+zF*7bKzXc<A z_MN`hynoDo4Ln^*;f~0k*sC;<A`8G~!C&NkpFD1$L<)`DpCUJ^wh;X|ZvP9<^O(P5 z_!rz6EceP?=ftS{;pN-n7uSvqOwl|MvPM$ZWiF41hqx{CWzJgtL)sI&JnM)5P1USn zs?g>_nFS$Zn|#lnDxXzTi@G?wYyo2^ez1d4ye)is)ZS&DspH7T`<Hv5)YB_HQ)L!b z@jOC3GV`jYdXQ$nyw-{z>B6>Azq+=ClghHQ;A#$5vX#0uy;k?=*`e3!cpZL_Jw&Xs z1BRy;yn$7r&qRF8F!spcUr*>n?UV2qd=jQQVc6g8dL<TwPe<}RxO{fV*eW+}FR0e7 za7Thi8Q*FcZNf|Z_+<@o$@7GKSWm>!j7s~vuQhaPRj|dWy|4wy4)Ff&H68KI3*|c+ zTvT7GDJ6Y|LfC%dVcRf(|1pCXZgdH!PJ~WQ)NRv;x7Mv&`yr}ps)P9YMQa4{e{suc z_1G~qtg1c|d!moi+#&9((b|=_c`zfZg5&sOHhq4>{L>>|^{ExJq3=V>7a*0NT~?(( zX9u|@K>Z|lUPQ)XHfyC@FIoZ*oSc@Y%Odhw6_w8w`gyi~zEM9f(9fPaU1px>^98}n zq2O~+S>*PX`9=D<G%=ycB`fY=XQ`sQbzXmAG>a7Ts&(Wos`r0Hp4_<g&edz(lJkot zeb8EH#14=8_%&rZw;|eJqyY4Oa^<tp&sg#ehw}R=#!Wtj+n%DglH;Z<kbB6q&RC!= zK1n@DUQuuRS>X-hn;Nr!&l>~A>`}Z|WA@Y9Z&ig~_y_u)6N!ivIbwN5sz%Yl?4a!v zy%q8M^&3Ij5=#do@YC?Jc~x$TNOHrsG*Nya+3%(cZZ#HX1-10335o8Ndvtu7qxUZh zGK$${^YF`vmbTa_lO4j#GA*o)qKQlP`nSqh$axeW5sl)n2_Vr%Rt8C#M2g(x#h%ao zYaRFIk~U|D?nlr(l>B05$?yxwPiGb-%;(MfiP213`rRX9rO`4qnCY0aByrvWlb+^u ziYGI=`_qNi%>z*<zw7*cL<|Xh$cseVzs#sU+Lq|@UlgDp*t;mv{rn>5-)O%;qb9k9 z^`EmN$w&81;U@V1NSpWnCYyh3AiXHD56Hbhb}yeNlJ-%V(+^|>DwbZ7_&HK?8~5Dz zXBQ<NJ+R1mbYkr#TzI_gDs&E6j;5%)E|Pg6kx0!wZ)d8toDITPBBi{6*CjT;6G<C9 zn(|l<=^EsA(yY-P3P-{g>wI^I@m8#&XLbxazjr>h$=DiG`$x(bo}j8<3dTl>J&!o^ zkVTyCj;?U#>@n0gdseeL<=qI;7gPQNC#cY2(ItGp#2p4e68o-v(IzLvb8`>x%;0&d zPWP)XM@?>#=Ena8HPpS1y8Y_vg)_U%PQKe3o#vgL+754Gx4FSthwp^+y5z1GcfB_3 zqr@sol<T@m)kV~66`sG$vnw%6)zwk%f9D?ln{^vs6%Cznv24;<mQ&BAf062U{H$VA zsZmbTM~G1HQ@^qGyu?XEzvh<p2i4F>uCK~zkjSW>T;B$#fqAmN=XP!-vgWUqPp~{M z@rQl+Jr%=NY&B7TFWXn-UbOH1i<YF;=tQl4JeyYj%(Rp~dr0cLhxnvGjTOnK{>ZI+ zFWcwl%K2Q7tBJi}zx5Zjm6Q4ssr!%Xqty94H{ZQ%pO}-HpW9bKukXyo97av|-j^wl z$heh9z2r3HN@YCli>S%XX(ETT8Y6ay_Y9OWilg@W+$LZa<m4>$rq+CFa$4$W26A## zC_E#2r*jUr)2-M}qxSc6+kie<LvI7x($Fovhw*p5V7KQo`kM%KG~XxFi|aQ<7uRp& z|JVHQjz*yR?T)wm_uNc6%4t`zILEk^)l}zWJAZS(thbJ2IP2~Bw|Z2lj(fW5y!_{O zvEtnI_K>vkKR6X^Y?b+c9(;CD>!yZnZGq8tr%G;RMc#ajoi=~k<&7528*nxLm8JRS z#O&eQ9S^N9qIGx2=JAZ|LZ1W<hRSES6AZtq6(6<zxgfN0J+=wP@n{{{!F=+hbe(fy zKD#Twt7_jy-e}}ewGodBGY@JbCf{DZy?p0(p#^un4hQ(V58Ln2s@&LSsJAntoTicZ zydx{bo8HQtb?{mFm`h9Zrurw=oL5J^q`e5=y7R%OZl0JAC3-H(tSn)KO*MyG(&n(o zwut|W`2RBhS4S1p`WNb)8XDyWMH!Jv=_tE&Q?atEpZ7VF=_%{3jqC6iOjgr0W`E8k zcllHqt7?IIeXrp4ukg_#jaN^4GPMa__fFtdatvPn3A|P<nFC%;tU?|3EMBma)b5T7 zdcd8rkum$J?4(GFS$Q+Hzm&S*fN)-0@0gv;%1BI#$VxFto*q{@_c`p2Ypbq-ec!`) zZ8c_%+%z{^m%o$pU0IjYd{F&Uw7!ehPiKthXRd(9I02=(_BJ5z$V!`Qd0LY#QIW%` zR4IKBZ2q*rL@hnMJ9V|LzahbiCSCvS!2Yl7?GfQ^IZZz_D0m2$%dZ8)Qr~J|zK#XR zzH$16?4;UV12=QRcWHh!Rif*-i~KL>_B!A<U!Annk8f~lw8ObL|H8m5piJiRn0-FA zNW{vReU-+!m9z!up2M{GYuzGTpxazS&S~@ps`FGs?N=V=Y%zSXG~c%KQ0k9^Ue$Wo zr$^F(^S0<Vnt?6TrKIMPtQ9+CKg8GufsnH!!dLQ+fMh@1wLoUii}sJ8sBlY^x$`MK zb8cjXe+Wq;Tt|N*aA0j46npe}-rjRn1*clRhNb_%vr~zCya4am8rE}Jdx&+mlv@Rl z3YE{`?Hlb*xw?V6PouY{x{db|{f8c*bv*5WTXuobMVd;Z10T~pSWQkh6nPhl?A8=H zVm~=dEM-<|3#t=XZ?IFFTgPWGw`$2ELQ2X~>zK3n#qhJNZg(*<W33%+;5A}@3ta1= zUk&t=x#ZGs9aJ{e8d|$iV{`{k-zGMq1Dak0jEvEAjZq6ZS8AFz@br(_Q_$b{-5`4W zWOXPPb(%Y5#+4Iwkx$LS=kv*{F0EZ3XLkvI+jY@<Sbh1_@>Q37tof&n&UD`VB5%>D zfleJcnSG8e+K*cw!A9QObQW)TaceMQ+3aNH3q_gDQ?ZbEkJRwhHB*`KAy#%v^U2gf zJHgm?IKF|aYlz}zEzSw{@NV?qte$oKl;zzhQbTf=)X<!82FGj*`$ZxN57=J(#}_-N zDbIaItY*nGBWCm>?1P&6XGfagi&48R=h#!g?bGnZXW@%WGNrMD_G;FXVl_1O%#F4c zYzB{-&a=q1HN*qm$Fr;F&xhC6_bjV(>-$FT5D_QhtsY4&q`nI>L$Pr8AvB$-*2Zs* z9wOoe-&5L*aQj-X8TAT2hpVH_&TJ(ogr=jhnp)X&O8ABarm^=A+3C?L)$#k+QbfX$ z($wo@JxH0aGJeP<-fAPM&At1w<<YL}9OOYVb$uZ(sq<QTAJ2N})yeeAmCHo3OyEz% z3eVD4Q_ZC>8#u*<Zj08a=SNm+8hwU7-AbRnMW5s*5z#x}&-h~_>{)gcsAH<@sYPa> z)N?D(u65+mExE0F)Ut_IJ?zs9-8}00I?*m&NL>%*yueGW&h+S9o`_7b`)I?Z^xO$d z=W0wJ0n@o)I+uD)ARoxhrG|*JBtO!B1+#m^-jX|;T4Y4Ooa;}WP5DEdIUB*xX~KyO zy|TWSw=^t^KEeAKxD7wSN$m(DOwN4fXUAa^Jd1g&bzUoZr)qkh$(WuWJ!rp5jpOz= z^_Z?EcPjS82zwT1gQYxu9oo&w9OPz~JU1PiSUK&vgZ6X$!uv++BG3MuEyuEBRzGmt zy=$HQ_Rn+IIxTq4%G8CxU8?IA2|SuTi0l!)Bzz+t8{ua&GG-5P1Bs{m1-pj2{}qTY z=+SD|qt&UYaWb~XbWI;a+1v+8Bq0*zR^Ge#0&i(JsCR6Ll>#S2iN<&&EA%&xq5t^> zP7#XFWkod?>da;2#iz5H71cwz7C!$sJwIPdtd@erDhsvTecQdOH>}yP*2&pZiF=r* zd00k#DXW}@#7WTB)gG&;N%}DfjOyvfBKq+OdV$wUQ(+yLT~*+7;g+R&yx)ntba~Mt zf1fq(7Y-_?Uu9W8?-}%~)<_L7m+VjCStpVw@g{4myuA@A^+Z;BEBd<*PVlFsN5%0j z)8j3=8F>YiXx!5^R|wqo6L4d8-+^Cdw?I#!Wo=^0P!nfw?x62(yW{rd6D|K~-yK+h z++MHobL@+ABewYN{#8?5<nvp|t`Cr1!|WXVhIcB-8h1`Ss^#&#c#7|hpMN55JiM~r z^Qo2fRiBd8R|r3|q2AdmYvvSVowrY8)I3;~czDy2`hFT%`q0?Rcl4;w-B9o0^REiI zDYB1%pPA?$cYgt^kJT@`3egLw^OwY7jo9C%W|0GLv#Nb)`RUeO38JR8MyS?toR;<| zd-1TF%A;#K&nio;rpKRJA^i62GCz0i%bNA{K&|>#u9+S^wERS_h<Jikf&1%pex<o} z)l_AT=2ow>y6>L0FXq{i8E6@}zqNrl_LkJe&X@C7<bB-0>_KmEsxy5yw!KGvAw8RT zl3dDonENb-t&y6C^E=nUb@yR|FA3!z_hn`SZ{khQKQ4Z3`2~I8=9AUI=+~?Zl-%>; zQU3JVN@|=+BoF8C?S<lR$Nrbzo65;>`)i+{6_#Un=hz`m{CO~M$MjCalPh_@Sy!WT z8uDDC49!>$TS7+TTJ2{(Pwx<Lx>$WXT}33lKjV%~lOCH3fIb4H^W0@5Z7nI#+3b>= ziLb@mf3#kBAR1y<p_n3L<+nWCODm(!yI0@^omLoM@p+8f_%CQ<DzzUw?&G%49qT&5 zphsiSs4*C~%itbQfqOjB@JF`Tb6npx(ni)kNcnZ_^^3Nzj;?loMr^!rrf7+9riPtn zQ~e$Ma@KHzem*N>)Js}@#yp08M%R+c*_Gou(g}{6DUsE_t}*+WOjEY!)JE)*He$Uj zu-fFbDx3SO?!byVn<yd~=YQE3g>L2A@9qyQ!Osp|_ALo}y5!zn{CBN~>{QM}pO;X_ zWuZLlD3`<Eh4M36O`@<o#2w}z7r*EN_A$@I$LCRZlFQy3o+Kho(0P~ghR*gL?#N?Z z^L@>UKTn78Fqfz@ewk`2Yu9Ny{U5ngH;YDk*SV{p*}~#&R&Vr#Rn<(RJFI4hXDUzK zOjT89c1|PO|6G1ursDzM!5fj~z9+%yOX;sgfQw#c!RhI5^IQduciBG!|FhL(-Rkc$ zBkajN$!WmjXM~JSbuLJ|dEPr>bWsoR6~i8^PhWf;ZTNU^kGv&PavC{X^lGwfu!7s= znuzRb5idiEH%KPmAHIy}1y&QxpGw)4<N2J-=XF09NdLiYMn*97sIO({3s1fbbwWe` zep=+ckX6WyNe3#xs4+)RqdEK2dIUUb9NzdLb$O{_gm)Hr3cb2a*C<iiayR59dYqSP z9u=)Fv%-Wwvcx2=PmJ073fwF6%M<-$*5&2f^skroFKjbp`}#so3(vO~o|`q)V73Ms zkhSOML`G!sez;P=li_znMt2UY)Gy`bBo}Wb9r9oU8&L6p{f%5Q<(>nnPQ0`4h@D{< z<^XR~IATATUBKKQv-cKee+w;DMa3^F+yEzph$qf|qkhS}Y048$#xCg2+8@jP@YLq` zxr}p`yDD59KEZo#t5~@=vw!s3u=GtV3hAjtM2b(|Z!W16dR(6UR_g&fL^<K*)1d9M z*e3_rIhEfl@ak8<uksG&pTW!1ESF=jiV9LR{}k)A;dNLiZ|f2^H5|k@vzQSwu^U*A zGrAsi;c$>z?`1Ys(2FeI55d%<F4hpo^Pxbl1~N;;h6{BjoKyh?9&sk+DR1;SkH<sK z9Y}?-p(RdLR?^HwK+b@~PgI9%PgH}aZj`4wF5BKc9k`c<Og?WWUMK&QSL6FrRxsYY z;1^AJ)TAMK3*lPUnURXgsw}`82DJ|j58=$!#O-?6vl0x<*nT(?DXHc#OH6eh`>+08 zg?8)m$(?DzWp{ytTG8D%aMohK{Y}aov0uc?Ez~aIWG$mucYw8{^pM-+3!K_WiGM&k z$}E(*bD1G4@B{X2Vxp5z9Vp0uR=t|b#PeXPZ$oP$)6(av+0k>=0&L}zDSe(=5<O2{ zhAk!<t2#4ReNvCf$J5go(YfmLZ9s+Rs;@-^a<2L|-vT`Ys9*+uvv?y2vsGqiNg7zb z^%)2#V8HXUiJJXqtlDAxLGL>Lr;pfM3cYUX{Q!#vPHHu|E%5{UH{8UR!EPM3ot&xq ziN(D>TR|<Gat-V;c%ldFf52MCzSJ}Li2ZMA$-RwPBGT)Cy_DP|_I-sJyH4|QklVEH z)UEGi-u%6O`u7~OB6P%lO#gZ~hs@;HZ{dyw+=f18-^Z*HjkQ|WaKwJ6fNvZ4{)9FC z??#9@?atYQxdW{KI@n2HsqN)Aw59pw!U(xC;t0DJ()S<GW)-dclrbA)HxTZx5g*IH z6xwPnw3WmXH`Tg$bBD~LmX6iVJxHnDNU1UV+CtCP6ks0^es;BU-~%L<i}jto%~|0! zuj7HU%j5g)P_7}mAOD|l5Wc2DEqBnH^O)7cyba}D{1U@<EfAdh%Qi%WLyDFxmc{{B zGKiG%M2{3kvkFf<GFxiQ1c|zqcTNP+0h~fXdJWs22^~;X&;euig9R;6sqg|GqXmxG zCR7@-4?`uS2zBnl1{kvQ@Q-L2c1?LFY?1EMbNlVfG~F+Q?w^C|_*x27FVbd4ff{%9 zzHjf!J`#sgC%ZcL1N&my625$&wV0{mhh;7ldpl;|d|=!@g?B+yBA90`K2fM?Ej9hL zzzHopcNEgwc-~NWzFkwOI2I-x^uFB!J^d+}JH<Av0zF;+`T))oEClAV379eak^^$r zxmfdqM5?e$<6FH+B5d-@HpOq-Ec?c{etuj0KB&Tpv4|0!slt(Jb;V1i(CvM^9>c7D zjc%DQ8#84K@Pacw?h3u7<4Sxo{>YF$4>-;>Me?Z=hJC!BqJr}i{eAvO<IY@agVQ<S zuI*i2?w>O?@yC6yCd&tX9r(&djqbJFNZX$}I*$Gh-oo4_D~A7>c46dP$GZ5GE`iA< z^U3#z+|~@WZrFF9p`ISy?#y-k{b$B2RZX0g@#cHt>*E)5`f6F62!^P)qcQGB+FIP| zXvG^o;a8mC{KO=+I^Oz;I~-}hR9y@9>_2nbvA^FR2_?QU<mOmV$cS^=yRPXI5n!Il zxbNKdbRU2|!{}ov_rKsE4;<8=mK&8K1*`i#?ui`2?<Z88p{e*rrfklf__PJ%NLhbm zAM3v&<xZNQoL5bW|83fh+xBtP6Y3nLpG%u@`^LeN&0n$bd8K`ulDk_rc{^N*klZt} z8~?$u+-_CG)a{dxKCRCUac8E;<b$crnRD^`j@zr~)h4*>@L_ph-n)mJ(CeSi4m#7$ zF&}>Psd?DE(>wQ$l*Su~^L%=sA+nCqKPA<ZYM8ThXN$bKh~M_MQanl}gYVi633I3+ zw$y1}WU5calTVI3c?iGbg?Mbo?JM!wj@zH4y>UE%F5e#5QRghYXHmP4b9^;UuHQnl zE@WO0+HbO++D9D9wN7%+ken%mPfax=GeT7B%uGL4@nfUA;*)vjMfq9NKbCcd<F7qw z4p%&6Z2NqoW^ft1D&^|A5#FqoP451D;)Fq|^D*k&#A(<z=XOp*1~~6)ROOSe@z#Pt zRwPD9AYUGq`iyO-IA&h>@tl3@9sj_6tSmd?i=92Y&T>5YS@E)dUpANA-=9y;+}9S# z4p@#qp6`2ms9e9Zy@~yceCjpc=v4gufo)kEQumy5SMNR1=6T88{kz=KBSU$18h^{l z``aBWpHH1VT&{8>_c?n879pP($M@{w-MUH1YfQ`>Zj1C6T6&8}!?OM+=PupSt3>K7 z+p>4$jJUK+JF}Z6+9{SE87y05Y%4$OWJh{+`aWsL?b)7z#ms|f{AfR>4j)_l<PX(; zKegXK(TjZY5Pg_2{1fO}>~9-yoe&CCv7=2|_ui2o$J@B8U2wY}8r)Beu*_MHN}ZS7 zZFF&BuF&@bBXhwe!nrExy<jEpfOn}I8on1l@cOunALp#7zv8df@6tG#l$sk82L`7t zk{NMoVeYQXi}kMHh+A?sPGo1Uf1mvc&0(VZUe110UwHqh+ggFng%Pc7gVJtq;`C+Q zo(5-2^xZJAJ9W;y_4B!*%dD%cTVK~zm+zAm^Ij}cb_&o|LnCXk5{B*X<OY#9VkJz= z7@Z@~P0r*RvGvi)S~JoS_Ya8A&I{CGpm<kg=lH-JR%)^?m-sE-A&WmOAn^o=HwQ&i za85*fZx0L~g=${k(k}No;>pJ%KALW9TjZFLeCp(3Vo9BbHn_8|nel0iN1Q$V-^(}E z<#%~AG4N=rYiO0+b*c6Adwn#y>#D?ygT~fMO3$FQ&++$_#eqrn_ibd>tdG~~(QJz5 zcllUd{ie1p-V|+Ul^VLJp{r1X*|~W_j}35lazLeCx{}Yqmrh|_6i|m>I!}MU`;u}0 zdqjj~M}{2ZfkTgdE%U<TUmLvB*_|@GYn?6qM2#oRVYQ{rdEQRb$9(D^GuF>X9>YEv zL_6rYd1riy^LL}Ik)>E58<5?lQ1z2q&VMV-J#(?9#5qHjGnttB*H;kF+Ik0fakKw9 zKZ&&z%zF|w+-l)xucWnBc)KBf1*?d=63h0V=!E0nz(=q&e{v@OSf0rAH$Jj_eqZwO zLyv7uk37D0IQdxrlY5>%^w?(349%s**RB#j!KJwzZ?@fQpGgn)+OJ`;&dA)({mUWd zNN8X4hL(G8!vi5U-<NaA$M<F5V?9&az1RLiE|t0#AIQD&G5g}^Ui(=}w&24q>H#_H z;Bw{1HW}RtiZ-LAf6iU-t?G0<OV8Vjb3Xi?hT4m_{CPZ5vQH)vhw^J~PIh!$Px|xt z|5yR>yD}sDSHxbR3#)T`*^dz}CPJ7s{|J$i2UFk3_$WP@^rFXp4qo1($9~Z<9{Y<5 z-d_*<OJBjC;zT{_O+5B3{BL3<nPLCmqj$x4e-*zD<*p9NcP@7`YpD!pRy`UgL+wiM zwZD`T4CL<Z3?5J-;-ev_9{m3!vkA&=!fRXI+`Q4`6s%a&ylV@%oxn}iz5FighT{IQ z>noCT8I2JS^;r3^^Frz^J<mMATlp7KuMXa!ck;N$x_ck-9($pN?D`m82UEfezd2xZ z9ZC(O0q;!@W=m+R1&X-4Jzt)n!PNx{+>8!hmI(p%zkpKcJ)unv-x61Hbsbt1`!vIu z)kQ$gV}~-s4wzsryf|*xq=hbD(q(r?)4-pU72F+4#}5ltO_e$<lr`C>9cSOw3;ZVv z7&Z3D4ry`!Np?qNCxsooI(Mu~=;4gq^Xz`eSc`W@wEMR+%d|al9b-OjUy~lUug+%d zR~VDs;P~-u3si53pH*MZdwAA6t2vcEZhsoAWPe{MDza<b{@kEoD0`o-{2I6GNlB4% z^F&INl)=L?Iz^asNI6W3>|?%0>t_s(+jFwAl5xPJCTnzw<uRQ%-;UcMQcfz!=p$Gk zQ`(JfolZBa_0L6G;}`BVwp{6)xaUM7(&f!Q5*Jq<&v4Sz2tCj0XC(FU%!O(?DR#~z zrG}J`Wln9)r%udNag(f+Xx1hES(gZse@f;yU1Fs!QA)}Q89%m%C%y(qGnOVI0sDFP z94rgLB9iFSX9!){F1IqcPsNzf|2xh<));&Y3^Ml98t1(l17<BLdp-i^lj^0HC+HG8 zG|u6A>1DYt@z60ipA4knJm<fNb2+;3gB@{nVeszC4r7~0hlX@uQFu}9qKg-u6qDEx zVnq0_iyGUEPCtI8YldnZ^Zr>`qpr%S#tNv%+dmI)&~#dU&VDgxMu|dY-Jlxt$vX6; zPpPPvF}NgM&FA@Pp=DM6^h7<LGH?8eJ}LDC+-gKqeM|G{w6R!HcF}{Q_5UvIL3=SO z&@RmmT0=C0{Vy_1c6;iNY4NwnCSQCeH24ZNWb9Lb>LU()Qnq=+?daEWBzF;m1Uo?z zUo7tcb91pUau4Fcc#b;@iaU>9J;SQ&n!z5g8ZzrS`{vxK%;&jji|79dq#J#36Og?1 zQF-fx=T1UOJ;(lEhZ8|I$Q$CTnYU95&!<9DfnCV_zYL$kf8a5C4i5;WqldE9JTIZ- z+|)wKgmjq;b!qXQe@U0Us;-ZjQnCHd%oENHZDGZmeW9;%(2T83;guF$iw<dNzpcHQ zvtW~R+|z|MJ<|8uu&lHWC0~S({rcp>`EbG5ju<!ORBVC|HV%*QPH=R5ht}{ht>5D> z<p)CPs}i5ia9Sr(F*L_Hebnc8N6(C>`pe>}J~_SO;e32DIh8waJW%y~?%mnv_@BJf z**mfZjg0*<I^guhuS(1(im`c=w^?;f<sPbX-hkNQ+(R9y0XYlcu2!X%k^W(BiouV= z{Q}p<o6($0BV+bwqQ%+;lgEant{`jKRAD7MHSzwwL^i+6lRnfxCv&Ku)#0uh-k0*; z3TvyhIBDoUX>Fj{;SMc1A2%R4ze{V|fI6KXt%&!=Z$ImScv;-!45+lY2mSvR<#SM6 zZc?#$qqxd9IHz>qs=TZumlU4w%@O<4{R8zL-=qCA2M?xZ3>xZG&i<73%bl-t;~t~I z38aGEjfu+V8=R6<IZx$8op?tBeO9-b@IUXz7A~CWop>tc7Sw3X(pgu`zLuK~md?9k z{<RBCZfBAEY-E@4-Wwu#;w$&D1EKthQwQ7itwM5!>b`iu%qOR0l6{iHdt*93ocBj8 zhyXhke*CHp#8gUcvWvDfFZJtRmGVp8q#`GS<xCK3d0M^ghCAX3JjfE6!aJsqdE0}< z&EK2jrF+X#vg;>skFu{-gy6m@-X~DTy*LF7Ej-8EvL^R2KWhJe;w+EQ*(478f#uOk zV~a$ON2}I5Z`j|)qdSs1A6@oU?ADQGHP)7->?0bL;vt%6$)3!~<lMh}UX_lh=N#Pw z%Xwoo(W^mrQl@5fD!XI(mGkIniQ36dq#MsF_e<=hN0bfyk&_a6i737jshD_ylO_BL zkKo~Zmfq-S<3O9!S1+-|K6Uy(ez8@~=<4*ad<G@=3k^Nb=v+0C8w{s(9mBegpyi%w z&?Q1eJlq(TcjXQ0+hl|vT0S?P;``y{yIFs2bIPZBrcR$~{=Ct7i8scGmuP?<Kfvh{ zc|MfM@8YxxbS)t@uTP(pA{pH?G6pwGc(^n6*=4h)xhMbThZ@<Py9ujkCVPy!9-?=D zgN-Zk9>3C5o@L$bY+>)~A<nC`_3Cd*h1A-d-0p0sAE)!X;+gSSIhtO^!95Fg5<AQ? za`Qd;{>ovAD4yk)`#G*0{YKoc-!duhw@nU|sw?BQ>@;bt^p5s_?!Bniy~}t6k5mVC z``@Ew<`mu-Xm)PtYtg&G?audAGoFato=p?Kf54kla=UeFmc-CE#$$}@B`Y3`$NB#F zH9O;x3;%qov1Lx;tU=K%?bzjQk!usP7~{t|gVK!Mc}2dZqb-t5U6H>HFYXoj)g5bi zYr;LwRQ3H_I})S~i{$V2y6_%#M_fM<iInW0lgJG7=0Bu>8Iv1oB(6uOI>PC)Anz-Q z?Ua}aZp>s?K#$Ieo)huFWX-KI3iol^=_D1$0{aqYPA;J*#c}ha?PO0!&gfLIyYuX_ z$})Up-;%XLi>9&}c$D{dzmjcR_$$0dMOtkcXla%E-@eEFZ<;2a+6(85;wO>58b@p& zd8X=&UKzl@*n4G|bLnmVfm(F<$FF%7`)~=k>T#jnbBQ1ujmQ{}+qFmp@oyd>YFm3a z!RDD|(Q<*crbyI6e%T^gd17V6CucR5idC@UqPW?~-hO0D-#xP$p{wlZw>#fcUC2>) ze_wvxlZ%W>Ju|8nLdo2+Plj6N-yhi&^{ekkB%-@4HOCyct9wGdb1F-zP13L;^>3+N zq5&^U?Xt)1nL3TzestRG)S^Izeh=y*PP3k=(-x%0c{{PxBz4RA`3r76TJCeCt?5~i z3OM7pRP<QAi-LIeHQbWa2fSn1E$LJLhq-qTjH<d8xX(P2oXK-03E>1^NuYFsXv5=j z2dec1sbY)IdV4F{7DTPsm)h&q+S*A-!~{i>Kxraa1Nd<hw6-eRV>)y)A(u{kRIM|T z5Xem66cMbC+E(#FzTets66oWf@Ba1uF|*Ivd+oKKXYaMwUXKMTt}0%XDN(3J!B!l9 zSH+CoDLAJEvdk&f>4Ds27NsAd->*S#bAfugdcV-}Ul>5&2%m1vyXLYg&!`rfqIlq4 z<<n4N7N{7pL+C)<LMio;!uTTJSomjHF<8X-iA-mGq*NOV7gFO=Khj+)hL-+B+8{CK z5hE52E(kj@NJtUm)Ypm0R{dBXxhWo|ADuWPvlOOWXrWE2G;M3<mOJ6vnvD*^!;v=X zplwAu3o0lpfxHl*X8s9%3$Z-6YS$tIsjKSm4UE+~o*L!-x@w_^mJSsCWIRslC+$LJ zAyZ?iUwveHJe8>nGG!{JD*jF;#%tb9@3cm4AHX{0j~q;*mwTOplRD=qTu7cNxNPa` z@LGDZ)X)~gVc7nxJss|4?Hy+Xk=q(RgE`!}bc*#CPCy@85A(KZ=>}!rugK_s*==rJ zie)FeJ}&igC7<3UoEleh#jY$?fmqDJ6O6tw<T4-qyvy7<@9n<4L9H9jy}0l#xI@93 zuh<m&cvyCv0zHfKm^_`&Qz`ZS!;%7BZl|)$bAv)dUKKCZ8Yadf%lrcES{HHVp))>6 zV$$0S5@YmZQKZz*xeGk$B?V|24lg+$2?)4YtkGV|;j03>=uSRPiBfYHDWxINXgWvF z=M2ZWko8OCSOoeEU`ByKcVn?;`uSdDE}sZLI^x<YT7yX7QTF7-Lm4@mDx@LMSI^XB ztgC>N@^d5OEkNGwR&CdI{DWzx#*9R6ta`2eF=qkE#amF|w~XAeaDj^NRq>^|z}GQe z#4CuF5%Hm-)*n_1G>5%1N~<enz5QFAYwOLyt$nVjz7Kl{J))m6*Pd;)M?KsV7YxoN zpU82P6Z#|21=~DOHlo4ZVz-V%_q4-zJ{9h*#JG&q5xB@Lkv}G9aguTJIW!XbOw5QW zi8{hnk+W3T7@4NRrbsm*C+f(#gvh@|=0G24kx<6YEWD`|g>Yp~M-EtWkHVpNAKugJ za4jUJF|wbSzpTh2CRfEYMfMW&*A@B1xQG$le<0?A6~c%3kQgcDC1O5YkxR@wa8k5L zocE7b<njK-1Z5`YL9x2v==qGszpiAsJdFFL&;TP#<|u9Ri<2vW_}!B4SQip*Sh`rP z@l%z~?Nruy(Q+3*uJeN2M-NwNt{v-vdwB_#uc7aI?5!`rG25lvVyi=-jOhFD*qM{S z7Y}p8zkLJWAQmx!-mWxp1R9O_7%*p_26O|G$>NXDIlGCJ({4_oJ2Q1e#t!X3f$4{? z)6LuoNI0k1+G?<K*li>Q?{*m+<0mPfYnEGNmaL<A`P8+}_UM_(4y$6XyQ{<yx&Vm- zZ2Z>SF5gX1M^m}moC;NPgqpjDJp$tsJ$UO#6L|vVu1@%o>Wt+gZECU0AMm%;xy-8S zz<{jl+o6wB@kis8#!*ffpQ!PwV7xMU^jO@5{$0QrR_6}U85c>q)2*>?7aj&Hp)#?V zf=v{$C#I|2)oac2yO|}TVJR{FXjs<zWxo&db{Tfnt}Je7WhK5u@BU5r`%oxeW#!Sa zwSr~hj)Dz~Jzvue+cf>$+jT80w9*5mi8eUK%~n$oUpFD)bn1*~{$UTdd-cRNhQy|a zaN!i3T}Pag;=mu-r*)z`vck)`{8zNkfjynsCSUH3r6H(8Ph#wwtXW$XZT_fwer#+9 zejb!fjQ?iOJZpHqovmh)ZXqYi48$kq$cCtU_!3*2A$DJ8MGJ;?Uw^y}DbEjvH%0%t z?>SqW>7=|rD4723j_gw~iQNUkv|%Z0@&5-*xwe*0_ZAFo=FTHM;73z&$I>$NLU$~k zUhY_&eca9m#z}v7pUBAnGmNx9WOv*7Z3P<(H)vbjK@VC8o@6QG7eGI)7=PC#Gb6|d zHma2XTVhZty6Fz;ra(IJjnF-(5ua^V0Y7yDzKQtBD*mcqw)vF|ysQl;6g`q{&IW!? z23}T(Pc!k?1HU2zFK4NbReX-Q@a!D(!VJ7fi++%a7j4&Z{P>uRypxH)9{3d*_zL1v znRwBH{Xqu5NqkhrXM;a`0zY0OBV#`i+NwBMGTzoj#QjL(a_F0!lYN8l^szf7zAd;O zSj`+xYFGGoEvRh^E~s^44yr!XmWd4H*f#|>+q|82N<HAB^9{?6)`kpfb|;!qXQRzU z&Edearbvp|5Qz<>d*9o)&4)Ft$W~puwJw5p9`Lf7(u$8WwB{WPh5LhqfAWrnRqClO zIm0)domXIW1^Yn;Hdo=wJ_Q%@rr>%flRm{)bn7FLGQH?lY%5Wlb}%4~21F_Y;WGal z%HVF*iaJucIUqHfNp+jkgKlU@JeiSJr_zL$llHsKd9-o?t&}vitJ34+X%~_2OPPG? zd>R?M$4Tq)Jxg2QW=O6@Qkqa&4#u0ncncV>#ABysnv9C1l<ul$PZc}N@DtBQM-B*1 zH|(P2XQM5r-j=}my>w*j+1u1xh2jk7m~KYdqhdZsOwGuG+7jP_+G5IQZYLJh_MN?; zcDG9RlU~M|XEpfOsF)uT6CPRMyTBZS-k%3eBJ`l-{5mNsMsD%l1fItdcl-XE@PD9! z{+l*SPj2CP&vdu>{ES<on-W__p7-qmqA9TszP{K_lJE9o$9wE%AFIdaTg4KA+brV- zTSoqNq=xrlFMSR7*$2aIsj<gIi+Jv7fri|wHuR+`v0Bw)iTxTMXUI$OD0azrR#JA| zF7*@=iP@SeH~dtwYf}-*4Q4~F8Ar-O*tN}^ClySv4lG!{ncu*QtL)xjKNh<;)o!!+ zNSnfT^ZYuvp6IV|x)L8+cPtE5H`*VB&qK3l_UEVC!qr}S$D&|EdmT4!ZtUgWv9OX^ zo1Mrn+0CAG@pmqn{p%40Gp%8R19M+0zvLOxPM|6ED)O^pl|VoG&vg_pyB|SKti&sw zqfyjKEoo~V{(v}X|Nf>R_LwA`YN(Qk=exmjlk`lz)3#uRDN?vMGA6%RTH;F&oC`I5 z{tBVAzsXm7{)*+(7St{|TnjyY{)$Rszpi3$Q&vqXl~oh5LV}DU`?d4*ES%Mb4UKK0 zaqq!uXdO~Q^ErvXwxooUh=bdaWM8iIoTQJ12kzi^Qf@m%14`Ab%)xy#cwSvH70!s1 zS<l-amf%T5aO-Z`;esE6cMe8Tcmmjb<9t7kc^iCcr<L3zF<#r?KmGoul1v|!7+S5X zdlX8*J2C%+Zgn)Zpc-kP*grWr_x>2ZJLR8xa?VNb|M)JMbBmdC8}6DPM5CQq!jo!U zZO~A2uJNwGKg~J0$(DN7s&T<)()_7*CHNk=t7^W#x}N>%BUQehJjaw7_BV7m#=6ci zYeIs5HnY3@NV6(yc1Y}%dChC@@G_&M4?d3{F~L+FTm=MS$l`sB+4Txm3jfvYlG->F zi`?UDkB-kTZrQ2RhP!H-;V>qrV1-2Hm{=hZs|A9)f|P$}hW+?1ZM-EFewkstRrEgA z<jjp~1jVApFP2u7=zL39*+5#i3`vU<$P_u_<*HGmRwHyi)GAUcrRGa1q|r09jikDu zN#9S{BW0={;867_HtHzv*obg$wJl-+zUr$FDOy*goMW*Ca))CEqJKk%RXDJMY4$9~ zH{p1m>0j00nJ>Jq)yhT!#V|E)$o$dVL7|vO<9|~c84ELc94zBGFT2i5PR)GyHf-oC zXekrBKmSzbRhj(alThqv@=aDCRom+ws<Ri=J^)WmEXR+hGOtu>HmL>{f$Od5Uq#bp z0z&L`T`~cI9U&ktyRK0|h>sJGx$uY&iU}KTsw`buwM!59hS0B1*F_7HqH&n{5~=I? zD`qi!FZ_-c5)1H7Z;MRJDNs=Hj6ultFQJ#ud4~~@a^0tti$yS~!+$KZ@h)z`6qZ`b zWac<NL=^r&=udbw`TP1Sn`Hm8{*K0^gX>E6?a&HyqW-dWIrYy#Dg2e0lK&C<HtO$i z-;Tq56CU9vtVjt}o?ha$R<}6k;d|TN=DY9^zDxYUCD&U>`a;hfT(Wk$*SzI$)+67y z3e204v13It=az45Mhdz-WM@;8(}$-)*G#iYp}6<-y3CqrV6ZOO*DF-)`Pf4hEzGrG z#fF#M`s~gQhN5o`k>9ty$+4I)tz3J&3`~{7(}4?GC3Y#ZwAAu&f8eDzYof)2B0n^a zQ7iB76^s#X5TV$2$6hS^+{@8p3g@4QKfL5EJU3^xEUQ=*S9yv)j5I!?o9F5$%hSy- z=;?Uv@Dq0SrZO{PWp6B|eN%0*x;D+4Hd4YZFdmStT%Wg{IbD8#6MgWx-^SZ}wDMAG zEvGu9GF6LQ-471XCw#N~3s?8Wz8CtR7yJ)I1H)4L!oh64e@{A|OpIe)Yv-!`nlZ%6 zef1o%hI2LZ>5So0?ik9foDtV-FvXCtK)1hm_|x!m*5cy5uC1%EGC|*A|M2aEtL7xk z+k-jm6pkLzI7B`?b{8g68rDm1eH*Fh<#24SuKvS_tL87v3Gp!_dawDdG8;B<!pS!^ z=nfxWNo(}<!DhHmSa%FGLo?{6KDV8^L5*y2_8O4|_sv?xJrKD<VhdMJb*?RcWkuF* zDC&9%`;T(#EwRr0d+XUFc3hPdhr2HGaHpj`ny~ZX6bcVbWZ53Kzeh^P(wnXGY`Mv~ zwo?32<k_09zt;n8H3KgV_4LXrZUCHcN)mzo-LXCW&kLT#QF};a2Xpu3BQN`)%I7jK z;U@P|Zth%NrI}u01mf!$UAz*#gq#lR?;v_jzrX2Ro!T#RXpM6XDgQ-!%CXQV+>Q-P zLzd!GpJJ&mNT1}J9@=0GUj$6&64S~iRJQuq;eL+=RJ_(;{Zn)X+;Asiy#jBDuO9el zo>05JTJkMjWBE^!pp`zA-CuYu?{W98zEtMTyGwK(`9;3YD!x-)eW&+V!J|H0%~wio zI{mh3yO~eL!$G7c+nVa)vioE~hl~A>Siiek>L9bLF8c1E)>&g016?{?iZ<`tG5_G! zi5v~~YRR#?_>>%P4@&8Wm&~N3Wt>xH`_cn};eDez7W*6yXEs**kma2f+asw`R*RI= zeZO7EnQ7}%gB!N(OZ9TG+9>jtKJI5H?+coL7+ueO<R(i}TddP4W$V&XYn9Bu8Llb) zF>Yav{()Gp7kh_Vr-wYH<Po^-OZ}F}gi7A6a9*7}zA60!deCL`Qv(lqrrCHqLN=jz z->ai-3c6l!PnA67C3;ZsI6g+Qk$|3VrTc=z#rE5M0qnt^#GR+=<;6Q>f3K=f?Csd` ze}I$v3*7dlNGAUsToGfM&k4twRXQ~9V&H@~rfq|3Rh8~58Wt+0eW^i<#CynU?px(c zm;J4QdGE{$SGAlZI<af`5;v=I<5;7wjut7ab`{F=g6NNKxfy%PovzB&y}GYumtJ0i zk0>c+w(UvJik1$$)EcYloSC3R(bzKe>KyZ~`MHEXLbPSzmAo^!3e7O`DJzSP@2L5z z)<M<`cW|r|Yx0bUkD9Z7Q0E5xs*3-U<AY;xwq)mZgIlX`p1=9zCCZZN2EKD=R_B}9 z6^*u7xOHt?S-pLCYPV=k;=u~)*r)ZweQ$^~!pDfkD)G?Ls5q|<AN4%GjzPPiJvY7< zT-Y+TbeDu@XtV5^p7id^hPB6Ck3NT<(C7<i4|mz;Q14AkgO+gYA6Z&1Hdy=n`*udp zKyN-4YqCDvdxM?3Cs%Xh@wB}sJy0>cKKk~))yS$6M@~bpu|weX5BJ+n&O?JQv1`n_ zBflD|XTUYoOzlLbAw>E8_Mb-TdK#iH{R<4K!M8_h>{&g(%<RvfC_8bJHmM%*h@C5L z$Gp$u$yC<o*Ous(Xkh&*Sq3d~y0y>#h*+UGo1lZX?A->fwbfeB9Nrk(CNnt%-y=9Z z<od;@_8NF>TS5=<|72)~@Y_N?{I_yPR?^hK4y(`PTz2lf^Msqrnb{s?RS}t6xQb?d z)Mef|*lu4mA6^fXh@V_jgIDlBC%BCN3xl`v{}oa+!XE^^W;P{z2+IgBB))=B(rX9> zgGu-ULcvi2XWk!@mKN(`=UJYrc<K$M`(0)%Sqj{;P(S~5p#=XeA%|-sx79Z^aY`~f z6JuRhz~dKQ%E{RKiCt!3MTeE$g&vXCjWs9r{9y7{?!7!s`{UT^4y{6Ot1Kn|KTvn< zv-JY%D;BV3>v^<DdZbDh-NLc1JX$6_?q-i@<Q7M?W(9&6?(c;I@8j#!p!~!#<#>wR zGG%At#d4y=r<O=LH9V!4xG6_^0Be1WB-Zk<61kr;<#zs4b@p|0$1{(;2-|AZL^B6D z;r;;(0x`^4Lx&Qfw+#nJfq4<w4lF75AxFzPdjMQsv&J}t9`k52{es-?%P5b;CI7Jl zGP8>H95b8z@^sh`Yjf_Pl(Yt`I9Gs8;N|@;dR^+79inf7(jU^^T-7f-=rL#)us9>Q zhqN>`&QTr?un4DTo0@7xl@AN<aHL7~VL7}!jb@M5RY1?AUpSu<oH;#fugv8ZHJ3Xx zb@<1bshN*5GtK!m=Q%SEdRxsre@N`voo+n>Ewd)LUCsUN%>9RX-@&`g|Lx5GhE1!{ z0ft+K{Shswr$xp~XsAG!cpGtbJ;U9(v{%N=X`kQd7*Q7cs_7YJm#->V9B<ww{Uq_T ztC4G0Z{mqYEc=NbiHuRXI^oNxjfFo0tsyoFMNaH2PJ~5fV@hPs8#XmlpDR-*u)TTe z92}n|C(uwseuVqzdEBs9VSQ8PsMy_;e=N)!GM7XuUd;f;eLCae%mB&Z8~HDN{Hr*D z&IlHP@J@Myej@yhkwDj2_?nST#E6W=+~A)0)`1h@m2k?Ip#@UMuVwBPrOQfhEfxJk zInDX(td3XoSB;wBtdJS34P6nuGPEqXJalXDwh*fUUn^%SY|e8=C9ELijDk&kmpO~j zB&;R8g78YhWrWKK>j>)!TL@c2SLjz7%k<^Ot@>>S+*4K+JQaY`3r_JKfE{wePQopO zzao5+u$M3vO6#Krw*Jw2eUChK<f$iYA#4rd34r*~(8$2(fPR24MaSkjC5TMWEY=N; z+3F(n69x>K9R-x^%z9Tyto&!0uk!BaD+q+dvVMUIYY1nN?$@)(mrK4}@-aJzzmgfE z@jbZs!u*5*Lr%R8ZTzm{erb<7r!o1TllL0ydwNNNbC6hb$hVqX@E33DRci*?m6XOx zcy)1R?{=|wUwRI+iQY~A#Xbc5CrfNgzQht}0yr*1tL@G9O1zQiP@0?Vo6Rxw-+k>Z zcA;5>Jq32|wx_CADSg?8h$~6?I-XnL>ik9cnbbMlWx363S2ecXyK!|(kXx-s;KZa; zxgE{+?Qz+AUf=t@feyky>}{arwo99=K_tta5`QpJ;vRUOx$W)T+ddLm)4_S9Y7|Mg z|K)D+tI8u*L%T?sOhpq?z765FNm<C!v^2HOR5JgPUgFzievry*JI(x4(>kb~nM$jv z0m;QepT{g_4S(sT*U(8&VMzP}7VlH}G<J$6W><4_&teM-82L~Y?-$>D?+rO+uIf>t zA<|PKO|t${k543+cvEq3=4jv4Ok9bP?pro2Ii_l2CsSluFS|b9YJgw(ZRxMgssw#? zdjnrJ{C8G>2M#-}Xm?6yeSUnYr>v-b6no3`a#K29os2y%B_9fQaih2fErkZ_JM`;@ z%dP5_hY2sWf;U@E`?Ckt=yz(2y`GG{-2eOWF&_(OBk$<XtY_2*%zsRN$2!F6%<1pP zu}CwfER|3L{ZgZ6M7-IA;CMa2&Bxrt=!;pyd@Z}ybf7ast_|ubh-UgWd<<o<7$N~s z!tJ99(M1<Y)3cuZE51vy5u-TCn%P3j_Ai-B9XW+0+^(_9h1ahwliQM3JG|nNh_<L@ zm)6OBRZX#8q`2?JhW3-OZ$1*iN3)y(kTG~|)Dvp7yygXW=-g@*qr2Y*-=WP?(wQ~B z8j;R?JN6;>@7tGpb&nZ3Iu4x+bQ@<^fn^3*1zYfh8kZcRLv@@R$14A9zbANmyvkVU zzsm1{O1VA0&~W>-g)O@d@_vwdsr#5+<@VTZQhRrRTQ@&9Y5otxA9AxH_D)~8X)bpM z>mp;f^@dxJcyY7GNu2Z!p|Q%&Q>WpH9=Jk!K)m~K3wwjswI}@Vj0h_(ex7Ak8M@Ya zC|;l_`f5#N;qZC|runQLb==wdxJz&ePwVgC{S)v<?$8eV)I6K7PgXfJ^Oa?C10lK2 zf~%;v`ZnaQ&ue#s-2+Fp9vP$)N<yX%AD-?+Iu=NN8g7WVjnRI0QhX2yrSm<$`r}BV zZlHw{m)@NXR1uPW`MccyqwGD}uHzY+_Rr65ZhyF=vg1tFkOvOWhjL!qaYjq^g_`z2 z%NY-w<}212Kkr)jwsl7Pk%bRh_qU5DgXW`Wv;;4FciNfljTX9PNAdJ?<jfYlkulrv zhFW)<=UK6r*I}dQ%oedSek->3w>4FCG)Ld#sbNO0eMOo*;i$`8U-guITKd~|_MW_U zG)aS;1k6KFxm%93+vT{lFOS|hIBVY-l2+|QFQ|g=Z06zo_8@n?=mt%n#O}AXDHb=P zM$(|9rlIWK0;}#HU>~3+g^BFwn+X^A9rz;&EF+43(R``V8l=~%Rm>S3+>Os|Bu6&q zm9g%o`2v^MqFc0~xo$o==Kf;~TZXU^bfnQbqa%3X@sK<hX1?o88PM`;t;9${M?=R| z>Bcrk5;4_#MOwIfy+`hAIlcXij=8CV4(zJ24xEKO45^3P95~W6Us^QQRTpw_34Bvc zfsB^5mjC7>u>l#8ST8B`Xv2&SEH6<@Ri@AxT}MPFaBC)i)BO7wc{!7bOm1L9acfCi z>H0|<WA=00IR45SLQY`B>b8$8e8Tz^30|4$FJm{?SwZ}U%WRyD3=|$3HsCX1=PaL+ z{G5g@6s+llZqUQ54r?MeAnV{YN{vQiLwP=<o!#rV&#>yL)BRS{JiIv)O5fJc>!e>F zZCazwt>?+jM3+cNh{q70o!4&oP`UGHaMfD4+iZ>c_P0dcucvqWpvk_5*V`hvFL)0{ zUhRVsUr(Lg6F!l0Z+%Z;I4%;m+onQiem0duKRC9^&rYQKs@3hxcaf3R%-^C}^$MC* z;$`4&VvZ$+hN-$%sF$XwV<~eCFLgSWGShwgk*Rf|Nf<y*_lyL7nlf0EO4jz5_(m2x z!^-;oLWf6HX}Gru#T?-5ptJwxs5;B-(Av~9>Q*SAn<jU!>P7)O>Dx|)S&am#i!W|S z)%Au%1dC!3=w2n2YXofz4F~7hwe>0V4vwRv^udU~3+q!|@1uG7-UzE=*V{;+y3J+a zay&S00?(>cgd31_{HLns7pERkFqfqadc)7YF1Lt|gtpe49+<7}?4%9oO}s8G46t_6 z&T=%dI^IJLX$-3wQp!0BgXH~lcwI_kHgiME>0ysbJu~I$>IwIxeuM3iF|1}pu#T(x z5Zd<}$ficHiKDQy7kLv}oqEQ1g7j!QzMXq!<4yHubTY=`pPDgt<V-UCAp3QoSZY!% zeaD!}U7A>kawK188PY--Z>*ru{#mq4B%GV9BYOq@CF;|?bXKvHB-EV?8sgmK!M>SE zyKhGFa9=Qaq;GoiDEbI*^;IR`?yFFE@jqa^fj@0m*PDGVbOGfAS!uYs98cQgGb%`} znxel`)>nNim=DaUUNxGM-=>FL%nBKCq2Gjm`y1>o|5C-*tDZZ9p1UTsoji_Li!IFS z)Do9Z<f?B(f=x=MHBi;~ynyTX6?K*jASr*DlK*m*uT|KVQp&sGdnkjObxQdWqwyn^ za%oDwhm$klUC{|wqxfxF`kU}gK;EPvLkiNFB@d<kG%+jXv@?2BfD!#qX6Ij-mG3hv zoqCC6fPdooVrFS(_R^m7uNP_P^O?0Wd&k>BY`IwX{|#1ioS7oMREXr!SojL&z*(6& zAfp!Y$cX7)`97EhhI=I4cP8JuX5L9lv4t@4t-~K6=G}>Jy<LsW5j8R;E09G}U;9Ck zknGFh3(?GH=`kp1IOaKuMv%7`B#yDl1=snB9;}f3Ze)G*2z~ywHyfjNB27Obp%2tM z${v6P%pSgaiT%Ytd};55E!EH4>E#}*0&P`L4^4bc@1m3Z4*G-7g-=WMV14D8%p9mR zel^mAPU;%|AI|j9|IjZUR#3i;P766g&K(I?=X2P6le4DCp{09?fqU&yynlf$x4m5! z+LEK_RCst=nsW31W7dDHut&7cEM;T;z6d(v$T~VXy<Nvfrs1s(?Wg&vI4dSOzL2u8 zq$bjG<JdoaR`w8l4D$u<Ns>w0z>JS{GdrNp+r{<6I&!vgYAI1={k!65S`y;zdkG zX&BzRSc;YupDzF9hWuCawMnYa5PD1aaX@CcK6wgSJog@0QelW>yrgR7LS>!ADRl!+ z2Iom^4kqCesVC|oG!WQ%;%ul|_sUHz*wa#)zFkjqCiBt;nVTO&XLGB)Ri|ezU?qAk z{2NB2B2j@Al%nWgl7=lQvsKCyq?9E5nG`gAhS4Nn-w3}ppOl>BbIM}m5aZ@zrOe9Q z+lba*5FMt%^|EUjbrw1`;;ZQ8n`V36W=`~?<R4>V=d)<gChUP5wH~VcPn6gKH}|uQ zs_<0Iow`|yKOi}k&DJ&O-nz)q46H~;rsGGTT2pwckblQ_09+S=Q~Q?N5Ntz9i?4Kb z&&|kQZKM=u*Loz;!d<#kiqz%t<mH2-gnRLqX=O?jnYE`>dDuo$<^9UxtTBR;mbE1t zZMECT6+qMObgSMjjIV-ne&r^e8oh%5YFGDabvG|JII=^yjc3_ir8OeQ)|kQFpm47O zcS5x#G0_&FGWi~2&n$<Qe1wzl9m6{Q=g_g8=ow_B!e0j)_bUn)Ha5UEsIU!AVAHM` z$A%4&Og%)-4s8)tlW`e~vG951eoc7|c?}N@s^%h@o2iRvj<~vh9sUwCfZEW%OZg&Y z)t<`pPqC#S&u7rXva&ku^{R66GA+){)KXXF$oRcBQA;2v$~kM~Fy2ew&9t)u9Qb+2 z;P@DR*Bcq^oX<$vuTthJ+}JDyx9~nm%it3}m{S{5!S^e8^f@y*V&q7wK1)v22FQur zgCh+aWu|(}UUD=ldQQBw$eqUHaQIo#Ses?fm~G%OsaHIZeBpY{(z~7w-wz+d!rp-N zjd*`>sKk0ZKo72q_(Sz*?TNlbMJP+nr<z%=E)9F>PI=4d-|;*i){(4s?%k4NKhkY3 zZo)cG!Vhoi&1S#Z63xOYA8DM!++7v$_i92)O2T}z(vQ@~u|!4i5E2}cruazn-=-bo zdb%sQ*S)~J+zR%~oy3e`ZO5b0>H97)zaI?_PPgaTFYo5YCnEfjqJ1v*3+xA|)}4+n z?61-P=PnaFJHi=hSbx9z-aik2<r?C>@FyOP?t`Nw-<)W~LSI4$53y>D$H?8*C&;~3 zJD58!u`9Zsf#1+>qcH;oFEW75b`{Se8`+!Djj0@Hw%<hyu1M+F)S}7akCgAy0+RQY z|5IMS%KOy+DQ|_!yW#(ow<hpPAH1QVXT$H)W7j3T+Ya@8Zdls!o&OU)u|y|h1mzHT zHawta`7G?pT@ana&EWpNLw&Cfru)j!fh~+b6J9_W2m2N$=M0YaU5Ir1sd*n$^R^Vb z|LNU%!@0W~)~{BhJC9xP7V@R>J|VJ6&Uz~H9?lbE+||&26837^bw;wr-rpA+In?)3 zVsUz5{K~Y9>d6tT8d#ng!(AhW{hN`+>8f}wFbfCXA8EJ$z-)E=$I4BBW<7(|xVq4@ ztUzKT=rq2+o%kCTp2Whq<{SI|BXCsMQ;B_E#a<+_Vc`*phf}yrl1hEYbw`Vsfgxx9 zZAD_*_LK7$XvY8BlDg=e{qnXwRioZ!?w4E6gR!@<NVpS=gkq8IYiX@hAiY>#@jB-~ z($<pp2ht?v{lN-i8dJ9$64s?w88w~4hm^f>j?ZQ8P94Oy*m!P77W9*69e!>8V{=TM z{=6Uh?k4lgsb{d-kOzga6Z;Qe4(VtNi=8WZzdCg-vK2eSSERnJEL!{oP4b=C14b4u zwAfyh{$2lB=HiINA!A^EITW%lO#g28S!O7*%<iQ1|8t`c>R@NM23Zxcp<K_-(~L#U zN!WYHwX=JjFTc^=89s~rb)g2Hrf?hbD<o@>;lZBUd;4O0#Ba_P>)@V!XoBxVmt+nl zElyvW(6(=<jM$AH%6MAN#+fp{_Ag3!n(u!KH*O8~)13Q1OIiP_gyG@2rba(Lp!)GV z`tdAiahZdstJC|_;TKXr3Q1|dqrQ3SsgI}A)YC4W&JJP4f>XiM;b*DmwIOZ$bX)Ws zdhuW6-m()4S@gyo&R=ZL?!JS2-W}eQ87Zd}p>9QkLiJ6j25+P#<Okn_%ufl|q<E)} z^{S4ud>W@ZsiQ;fip=FF=*Wx2CAQqyOS}oGzeplVy}!-Zt1x%z{uJ8CuP&JZKhJ1# zZBNJNV7tck=)CAOJk$TrjoQ|nk<s3>lLvce@s-bumhVgVevqgD$0gVamhg+IVine= zs#JJ>YPQke&s~f43UX2N&?noe?1>8}Z!(nscs)GZU*MedG}JKCDBOOJ#9ro1^fdNB zocH~)-;H?L_ZnK(s5UO}iDmxHXnjAF`D%Ukq27E}w5PFWw7>UI??;1<o#Us%AE#2i zY2J52Pik1TY~OXyfUB#y$N4T@PZq}UJ&Vl&q2Yx>cJ$=Y6>l%>)qAupQ<HCEG1=Ai zRQPo;y$Pl|`zh82u{&C{brn)9A_>umuf2~GKEC(*p1P=SU$reccBN9JNsP$)jQb;Z zF&?64?t?$3dcOM!G^8BP6TWz%^Ik@~TUI*pHS65ReCSx>(`0-?xpBr)>}ktQKqD3# z#oi2SPWATqz3nYcS@6<Q@$1b0NFA{|C*Cf@ue@97*lFgGr1s1E9`Pv4zG4R(UeGi& z$m~*V*~m=H9e#)s(12;eGMI%u-Q6WfPMm4`d)U39BKn6L(W@6*TPf_OeK<?<dd%GE zWvArN{-^xet^S@g@Kc62B1?|sp30vk`M0D877ly4b+~{T_p~k8NA2w2r{iZ2OE_Zh zv$EmM-a@UGS)ap3*-Wd*&hE{(Uio}ZhqmyQ`Kz1z_K4SCZP9FFEgVv9@oeKcEA~R{ z<-Xp2r2M3Xg0&%fcu;D36nqah<#e=Lv4Q(KVzJev)kl9j_`n4~Hf@IH$!&T(l-2R# zd~KWLP4_RSW|A|#=d;O~qT8eFC^Q_-#b&y;IHViVve(<}x+R+}EF$=k3c{q7<osv2 zckr#5J3Y2r%51=^iML&NAD)hCo!w<uwc!&QewWX9Jh-{K`7rt<(L5w-8{1EXfMNy0 z+b&w#azpIxcwqj1d~)zxbl#cS?b_n=jLq{OpMPo#9+7%4nrUsO_HM1e&mYZu9XSEf zMJhp?GuA)gkAB2$|J~DKyPdu|HhAyI1@!sd(>5?-_!k{sY4`B{D=TH6Ym4m8Do#Gv zniZ@eYt_?fDZMAvdw)&e3$yHVtr2T^^errT(O$S}C-4>``LoIYnw{NtGQXC|ztsHr zl>FK7y$8W?Y*4KF<EyCSMEIb(>CI}%#Rh}6WWJu;>$2*^Gnyqdr^pJ+moXFi_%gVd z*#qTvvGr<2SB<vt)e5U7d!WtI7R}e1YP7}keeLr_N?H7|YTe3v@qFdsc0Rm%q?mq# zmkl|akMkDfjQzVM`N-$gvrA%IAXUQMaXS7X@=wl6D?DcLtf<ymUr529$2=?Nc9eV4 zX>Meg<Ro2;jp9-K(+F)poAvnYr1ofuIj2(O-|C~YhM<4bbx=tSeBa#iBNOQ1lx)tc zXMO{Rbs4Fl-|_-i4-a^M3V#~VTFCU7H?uDO6@5%O<H{L9WJO*b7MlVmOL&>pJm-dd zcq<pvhB=kLn>cScH6L&3M9tAiJ+<aWrskvA>>V#dWW-Xj`ABimD-|_ZM;R|;65MEQ z%gL1Yhuo_E$ZgZg9=LM#(Ja=~9`>__XqMPb>CU1R@6ih3cRQ5Ir|e(@%CErhkn@w< zsGv7sE>fELTW(%tm6)@Yw9~c2+IF|cwPkdmfE8U%N*dl(-1|cIa%QXaYzwyRvNJs_ zb`6EwlFNC%&BAJ)8u=pglCw9#yLdHKW`lS7JUg|!5I<wNoWc1x%LTT`ye0@7G=t#u zAUU}ji8P=?3ZGAC$Qj6oRwUCePD-4PPMugUK?B=<u~&opdiq``C#!Gt&+INTVnR{) z&C=5p2G)RSP+;$mXv;KcU4@VLV<TE7T{ndXbcowI883ErUq?{<BIyU@bc$_`%$eM8 zbgOvZc>IJssh@lQ@}S7>J2}`vGG|ghk_JBv9*ukV=V0OWXnZ`c`|lv;2UGYTk(r!r zt_;c<)1S;XFRA`G{7|MASRl#N0zOoi?5<K0u@jyS-{6!szUM06<Xc=m*Va1ISFCj& ztM%2me8+0b)&ENV-y$Z<{5RyIoW0c1Y7**5Xqb;V32WvzuskQ+e9ipN8<|PwcUW6S zW8MSf6p;%LMHA0Y`tHof(|X1$y7pGB@P2hTA=<K*T`Em+&9ucWk&lyS+$FFgS*0zj zi+sq50Qk^bd_5lJy?G~ck67E|_f=JgdLX}vEJ3#UCF(Gc`gz!N(z<<ol?FH4-$qhG ztmWN!qnGtv;FsO#r3aA9Na>s+%HY3__Ld~G)C!|@Z3*uKgXHSM!nJ08M<gvw;mNk7 z2AQD_-1v&6TGgrfvhMVDYWim8i~CNEr`tHY)kluiR);d}rjM&DMth5B_bp&-$0C_- zcZ3f>y=u|P!g)~TJGrkUcLTYxtCfK+R?vGC^qaH_9NlhJW^KIM(DbjR@nCP~pr101 zN!HvW@yW@Y!GrN~tk)Gl3o1USSr_Fbu&6Hj0i3!MoL2vWZE|cMsFhfrE}3}pqz;qT zoH~RSL)M-7TQnI-k8`^G@eS;0ZZ!kC^b!f_f$ppkm#!gu+us`-Xp0`_c1merJgMdk zW0HSoey3)X>jlzFMzyctPI|XI(~J7CTD;^jgEOVc$U^mGb&umr4WtK-@5{N<yCu`B z?qjv?x-1h<AJ)Uz5T5i8kfb)RDCa*Ii}OD|7UU|fme}@a&VH?HBBk3$dzRCVRrbT! zUnt6We$C=p%9WO=olNEuZOOe;@Aerovj}<1&%6=pd3S2+?Iyktc>^BEn^eBMOum~` zzPwDnn{JeR`I&s*Qu*>T`M#wf={tqxTMCjMRBtycob+SnP3lsRfxKBk7G@x4C@jZn z?_xcg$~^p*%9)?Zxl+M;REayVOjeL7d!>RZoPZMig$lpSCS=)F3iGx*%~zW9q*x_F zQ=I!gugp)@a;>wmMP#Y(?SP}&abL@0@E*1A%Utp4E@Zp=k<@lGSM-doc@a2B-zL&# za!>nJIrU%oNaReU?Bu(B1dALVHOJ5a=<}FUqklq=U~p8*L29deyd0-|6B=1B-+}Kf zJ+s$I9pO@aU-YY_7Mj$ems+S9JB}&0@7^}2z7C$c44yvl<fuK<quM$SKVGUH*dZ&( z_cg5h2+iVpQd<n|^8=k#p&6f{-XHJ{m3w}`{Fi@vQ{9Fv=KPX$&PH;UTnvp<*h;T< z>2AJrpn_I$bnbr9PjN@5A8^~Qo|+6tuc1|V<4<ABfzj*Ii}$3^Anozla}p}Q%Wqv6 zEji$|Jw5ZRhE~z|d<y?7;=#?~^Kd7i@(-r`=s-Gg4yG+Bm+kI(85tohA|ve69Zk@u z@Ic_y%ILw%?cb$5LkhK4r4AnGXHNV>dpu6gkmYliL@(X1N(xAOJPJ>p)fl~Cuk&0V zoq8bi)YAyvEUov@dJoVQ_RH9lsfaYR3Vr-k_=oIRbv?R0Z=%%;qhHv6vOQ9J!F}NM zljZzn@9QJut-t1!)?<S*^;`Uid;Y2I(szp{+Rk0+MB63h-zVC>Fxp3tyL+aq9&aP9 z`jj4*??m>~ayzfXeW$+Ftq0V8p(h(U<o1)>0q%QbmO1Yyu&F(6i9vW=!nMwCc@i7& zhMn$%XWVBb9gY>}Yowi!)44H!tJ_y$K4Og_m(<YuB>Wesc>Brl4loJLCnLGu?g7J- z;m*`wm7Nr^73i{ETWirfTxG9{BL$T7m5MG$|G+!Fe?vBGdI_@Lfw3-;Jr+wSXFa)C z&S|FZ!KT<S-xIrT4zd$%_UZw&s+jRP@RUWL;Ln3&T_QQ86{F`BsJG===qj=HMt*cC zy~DW!=o(>fPQC*tEjN>vt<rqD*yC~1bDl(2f*T<n3wF7~?Meed<gs073yBuO2k0-z z*~9asoIG?*copTg_&bjc_@W;V%2@`U|4?W8=Co59a=7p)91ew)uHN^Jzx$9%Xpf41 zBT(o`Ip1m#REdm6QH#G7J6me>zKWi7la=+laR0MZUl+6&c8sU~2Y0+ktq)6_lPV+b zJULt_nHNn~-rjU<(y+@)^-B8Hoc|ndlV<vEa4U+&cSBCswcXd^RV^JmHi#q^=MABB zB>p<$v5Y&B+m*>J_Yc|@xn+Y-gHJo(KzsDl{po=`Zls$nc%S?A9^o1oR#wb6@K<iS zoim@*N!u!19(_nSuB+npk?e%LAIGPeI^!{8ltyYdvOy!Ufvota&=;~}I(7lSVn$PS zhsQa!pFS)6llK&*A#%m8&ZCQTzt*+f80)^W{LMu!<H#cHo-7LRn`NBn4wN4w?ila& z#%;t^8fPQ3`{geNjGY%(`bBs9z@i5%f4A-*_h(;kA6!)TcQHj~ZOweM5`WWQF&nMN zYiAix*H-!;t99`U_;=LK@;}3KKhL{(hK^!}IJYau;3}8fl}Kv4y93IjCl;%cXPa{r zrCR@6q4k90v(27qc3Qc%j8Ef3GHyB8D$^Vrei1#{QLE`YFP>v`)cW;jF80udId0Bk z<etoJmdxIgq)QhcsR!eQ*a7(8+IFk<!l|sfYvBDfr`}vNN9FO4oZcnRU9}#ct805a zxU0tW@a4JL)vI=awRomECwn7#9<j;?rsCgas<)B1byj(Nj^V>I+J$~7+AaQQ*6T5> zVPR<|`tjcN&|y`y<2FjZ(A;2s&Ya2#X;<p-q7tLPoB@9BC8fn!-#A0=?ibcY$|by_ zE;30%EN}!Q<aWP+5UQD*I`O3L*sbtj$*3hVpWBJczF5a;G8b=eh2{cZV@DCs_jY8P zQ+%s=p5nW&;~_YI?N(FAQC~C9lc~*`jv2oDI~MpJ=s@eux3(id&Idb+$+?dIDZUo| zXZTu)pW$okxWXJ7UEfhc{CVc@vF1~VF1_RbW=^*B#zlvHW_H&GdyaV&E<8P^OYcuf zoNWkCeiA1|x#bdnVt8#-V}cDUWgoc!zsmnxt6R=ki+sJ)Tl5m+<n-AWQfC`;8Id7& zKe?Uz2%6{;yLgjp$9&qUZM&IyvJA~r`U<TQM-HNip1(Qi+6rBOTtGqc%|)}+>}rf$ zD}9Q0`Ts<7yCrgUq5_K<2KSz_^23Kz^QM~b_iA4ut!d|5n8_Z%4BSv}7ntV~BX^BI zsx8y`mVC|81qTi<3h1Npc}efK*Z^_mmws^;6#VQ+Udcn$N$d|u>wRE$MP6eyZ)g(< znFq0KD83P9+w#qIfG-_CnA~~sEV-q%TJ2{pZnti^ytb~PrP$mizOy@baC#su^3&vc zI66hhuIqfKl}0+g2fak`a$S?kV#Qh&ITIPWvlGs<MO!w|LLDjfE0H+z3@t}ia5>{b zxkfH>``B9HwpL@Mpw_!O!M%YwB3=UJ9_i<-TBVHtWVo}zU9XL3s{UC>LY|XqqXiEp zUE9D^9A|WXoEe?@_N2D5hZoaxrgdOZuu$u~^oyaqW%gtA!Pdyxw9?S4;DGJCIAHjc zKiUfuv-Kz7gg<k!i+)%_nXYcbETM&>ljOu|=1&vkfbNid4eVCPy<iJdH@Sy3Z%TC3 zif7yN62HLKvrexD(4FSLJpH^Ek66=4TaLB)%UL%BE|h3^xE|S!b4>0*u+HmvF>j-X zTcG8N%qLP+%s}=h<n51T>a{cZ3vR&TcBLs&ytVOW8KG+RAKE^`bMwZY;sF^$;h&9< zV#CIO*_Ya>(j_fmzQHLO=+Jl#R-aM>R$>1W$P_fRf2K?84w`4Coch+%u8P#!5z_T` zYA9cQ;Xp&jxqR`(zVppM%FT?dgli$|`28adn;ToSu6x_-?I5e{cT>HVYrAOD2<B;E z{w!839L(Ot<D6T?7fHkBY)<vr@QLr`Ze|+!u1xKDF}CM%Y|M{^znn=IF0kPJ4C%Eg zNllPyGX5f`Bzs#GJA%*mG15r^{n9U1u(HD4VO`Em&eFSUHKUS$Bvmt~ba~SZNjVwk zSl*B?-Dd|Ls%G9)M#MkE<KaIcJ;SWm)6eH5WNsLWH|g5%+9n*7#>fI}qs~GCO1|++ zc=jaIXi2Q(YuBKjxZ{<zK)$g^fG=Y@Tv2CjkQguaOj>@+d$}{?uEzgYfVtwvBC0$2 zcsQ6DC%K7A_r0VrNttmlO=Y!ka(yXra<%yld&mZb(W%j|f&2^_BjXTFk;w@s*Dt~U zgH$8B6%893+nF6r(#MtEesf*w@$giBx6<;>NV>NxeD(-9=+&l3TQWKFc=$iaduq-q za^6m^Y<^!!Z31Eu_B2j~r~qPl>M^|RJ&pzJo9#y#!B5oPo7j;leMtL7`gs@riF}+o zopsS={#vb`jYwK)nRPTDA9iKv{FI>kGo5fM;XJ}Q+y_aYddzcx6d573OL&s6)(h9I z485QdU_|Oh=Y2ZwQ{nGrbC>5KUZjE~ejf32h%X~v;JHU2J_q<51wW5a$})*}o7YIK z*ij9>`00895Ug$H3AFI$7)9hS1UK3_{H7Ye;Rd;oco%*nq(s?)Cy{R|)U6BYrvPOK zNH3;N#XuDEUd(#{%mMO~gT1;yaxh0+=CesOA%Q3Xayp?vID568fpI5GfGAPzko~<# z#fyF=_gkHCci@e16D(90(hnc+!)}1u^-m|?bn;C#u;E8I$0(&vrPQeue5K$kCB2mN zQqoIFpG5j3r&YB=HyFuDKu!X35|ERCoCM?~Aj^O(1G0?tGSbUPFH?0F%Hw1WSE(BM z|EY!<y5y7=W>Z7y&k9v{Z}P{rW%`e6W$d(tiiTkY&el6>Jy33Cge68(Z5e%T@bw{u zfNjVUyS~<MHPw39SKatQYN{>qYi44XtBW{R{-)YGZYgGwZ#p}gk@Ub57tC<?$*E1` ztRm-BcD3=GO|>=Tt0`Hl&gGx*6|c2NpFf@`_m-44vSNr&?YEE`M_>4t`6JKwJ!r3q zH!@p4uYcLM!1z-6O#6)&NB6I?%i`jR=U42KJ1qmt{9AZ>)atWiFFt5LMUI2XJU!Pq zTc2TEt1mSsn}#(Rep<sLj#TrzsX;iUrR)&iiMYeW37>BqW`y?=?{Co+a?#^r->BWv zxiNQPXK@heJr~*q61&-wxE`QIbF7XyxdoNDUuEJNRon&@w>=Xl7}1Ycaho%7f)5Kv zmfXvuH>hGg3Zo~3@jl|v=2ENdiLk~fp+|_F2DA#1d}?5|5}ED)0!ny5Gwj2B71c?% zUDoTTkFx253bbe{k?+=Y!}R+M^!N-jP(B%5zRBqFO-6TcGNWn`8ieJ*l`EJE-Ybn* z-(h`KbnkwT@6&J$iDmiH=I}oit*I~ZF5jxWdyHKE<vX3~KM|fu9~P+IDwt?p6?H6P zzB?;IHhzL-RVX8rm0>#JR6_9|EUQK~a2`WS#r}+0f~@w5@DH&>;%8j5`N#I-Rt*aU z@V#R4-5%d}BK(61$Pyrn6lBrAge;(bI{W2D{x?|qmWEc5VwUmL)yV5IPQ=AkoKKC2 zPez2e-)7<@w~yR1c5=@*xXVW?e6+$xD}1y94P!l5dWKf!(#l-Yb4kx7J(u(bJ5OQG zQ)3OytT5-PdgXyx@XGiLoXnm)HG9x+&cw;=$y2kD?@-0%D}4DGd@D0?Qqz3F*Sd_D zd}@(TE%K>FKDCfOK8yayQsb2cKAH1hR(Z1(KDncBXjw>%2S1KTAp$Env!w5U{Wk?G zJZ6cL89p-uy9-zk@g8CYvV!kuGQBdHUMcaO2zyCysuf&KwHqui5JlwtH2l9RzKJ#E zX3LAu7S4ex{&i(lD!WD3eLfAJobIH%TsVGmYL{Exf1Pp`Rwyswi_!JmcspOxJvZPr zK-0`KS71fMcL?dM_YG}pb#&V6CDg9e>W5ocqd2M(2DqDOv?`6bioFtAuic(y)RsF? z%i+5U)NOnz*x0oW>A`4fuW*K(8_B=G2ko}Y+ox<gh{rJQ5HcK&f*Z2CzHjDre+5oU ze&$xs$BOMWd~k!1xlWXOyd@24eZ&e;LY`JdE=Vqg`nV5GqNVy(@vq1K%Rp8`S&YZd z1ab4?-;Hk|?v`LdT<%{URnL=nu8-_g&*kd5pJ%ZJULW}hCCYP_ivLM%sd^JxP)QTp z(zgWfi6@M)uJ+ow%vhnkJV<%TQ&S`a9m1*$^gVKyl6|)>wSzlmc&L|yGt2ZEF7u-x zyfou(?Hj!-d-3YyPw&Y#tCN-XF?|z#zS#;!J$nOaiO<#gVn`_AQ(foG;iLQ(3%+*W zG5Yo0y<To^guW5$F>AOrDa9t~Lrqy=Rx7cJ-$DFb;(MC1DcL!(c#=DyXi9k#%Ey=N zQT4<k5%@o<L!aE=plBao^7%~4Tw3r@6J9CFQ=#(gQz<#*@t8g2nM)p%6y#@<M@egl zAT18flpAz<?;d&&|G`10_Y0_tygB_}0OV0@&}wE0^wT%+E9fy_Ngia}zm_}{`&Q!i z_&sr*k_4OZRnaiON|U_Z6Za`hVxhf0!Z{8~$_J#6^xRB}!->sRwV9GBKUZO!k|{q| zVVeTBJo0$VeF|Hi$}uDOz4)!fPosusswXLVL1r|urlQ`QHeyX%y~%8=k6=+-y*cG$ zL*H<BmGRG9fjShw@?LlyiZ_5AF1Pt3baQeucng4&HwSMarO2Cuw~$igP4KRZ6jF+= zEYvqdib(M?PK7G>6qS1&v66edt@qTb8bD`G5vgQzrt<#`Cn*vjmw2(gD!wvaOdfe& zpq`!h#qj`TQF}#kO5T4@exyszV#@s}lTRQViZe&yKO6da2Gp3$9HBS!k%va(m%Ga% zuoY1zUdZ{Wbf`TiUG#|LF5gdjfb@V$cPP=%C9y!SOAnU-kvq|6CBVv?(`TjRk~gQ% zO39BjCl<<csps-|DLLhNwt5yj`?-2C&y&a{<0F*Zbjq2+DQ#V361nAhDeK83RpwGk zaZ)7j6!3gEUPfMdK2trHQo5`o0#!yH`BDX|A8wgLDdvHHhTc>wxEJ`EYNugC!)*r9 z3~Q>DT0qkPFXxn8pk&le(z(J(aFa5Ho)uV!&Mkog{*szO>mo<u9`kR>qx^rEd<(o& zlW+5X1(Yzh@1cQf)Cpz^w6DzI8HB`lGw;CcOEBXIvl7e}LYH|w>FWM*?ObmDnp>J$ z=E9Yj$^Beo`+j8S_QzNAyRRM0`ZR9ya#DHij7$4mqrTSb*GEQUC49v$bB6k&s~OoJ z*G@CWSNVauY5t+6xyGmANh9UirDdyG1%w9vSwegKJUe&ydVFuZIB>dM7Au8%E43na z>;+fX6Y<rNvywhV338{g)tl6|${FT^q^r2uz9oKJJOHgPGr5wmnD;9Q=f%GR*QsjY zI|H|smu5fzBGQK7IXyX<)=KU@j18WJv^skU6pY*g$SEv3q;-Aaiq4C)ZsGXL9l&Mq zon+5@!G7a~Ukv|jq`*Ae2Y09Z1iqdAzpPa`e3h~*+{el#YsJYoS!2fE{{Od*v5Eyg z4R69XNNye8{NSw9gGM7W_VaLDUQT&EpM?KgQNwc;HO!X?H7sB9wDM1}Yoc|@_g6{` z-j?XSx#i3^ex>}Tm9vVKJLlrL>RjwKn1$qfRMFd|VEi=v!U!u0aY-ax<+SD6q6NzJ z`iLKTq{65%F5$bckC=o3!Yc?T5iTPvC%l#Lo_L*cO|U-F!haTVokq3(E91?kUgLPv zE5;>y+PH=_=Dx_g?1>IGzDMF@_2A6GldK(Hvw|mCIm9}T%N$_$)d+_OMGyK-!V1FU zgf(DlW*627I|%*sm~)D(F*<aiFJzs)gq5W}66UMq8IL%vJeQU~uZQ_&_VGX0*rC^v z+QWaTF_$%<B5(pv=^_WYE@D%bPwfocKrkjJ!q<(Y2k0mC0qSd8EIGY;>7#O^+L&)# zVq9aaG=69_8y!aXL~Z69UeBlD=m<MD-~NfPC&@``gmReQm1t|q3i4_A0J4Sb$>ll7 z(#&PQ^#<5|%iVvs`?BW-*lGFA4Y0G8v!fDDBb-~#&KY38<Ts7q+yHZ`{FCr)%nb+s zFL)CF=3kZ=b-OkG^<9Eyr+k|y!gEG~{AZ7ptKFcPmR*ur{hFzxjJd2O&Gej%yYoC3 zS(VFJ7uEoMje@u@vIgkqf|9-l*p&*0JkRCX#|pYGazD^N49Z%5Kd?W{V7?#dA7(J$ z544QIeUS%%l~ItLN8U<_|3>_d_ya&=5j*q6KLEVEIrPk0@>H|i-Vt95JU;l;E_PpJ zEqUfEtZNm#%tXQZAn@}Q)&~{5%wZ>9%D5(j^+EE?S6J7nI!S8;Y8`nl(bs|d8vbde z-a`5h`7bq^`JcvoY$3i|ZzcXY{!5Jk{-+s3)TKVsN*Xe2nZ9lVW{A4n7H<PCo6@B& z>mqHy%bPO_ZRB~A-1kM+11}PCPD|F4=S|g;^}vg4ozs%_z{{J{KO4yNrfSIs;BzMW zX9IbTE36w7{CNNT6!_x`>rWN@c>nxVl`-BwKPAs`g>|E<(|G@EB#+nh=^KF-Z`d1w z^P1KA&w%op^9g0o_7MsdQBEjSK(*dZdKT%@NA1AmP4rPake`HCaUw6}?EZ1MCE+u_ z)Fc#+&s<sumE-rBw=@Z*<1_EBgWB<b9KLS?dL_`gO+qjE%qexyOhC^dw?Ho-w?Hq$ zPpy18pWvCrn|aC`krTyfoG4D`MB&|g91T4=Q@C_lshfMSSK)WgX>y+UGwH97h(!@@ z)z|wr99|?kbl&75{hoL(a&U{-ZM}Sn&?NF7{Q`P(NWyRqQ~%LRfs~e48dvL28aHqb zYP9Zx9&nYv#_oDC`#x5bpo#*9m-GHCW16CU^Gp{q01qMo#1nJZTkYJ@iI<*}F&ntG zyMH`JNgash*&XqN@y`v4oox?yN2B<7omDRWGo+@c*6iuTEP8!5zT;;nXAi6#s4d?? zKREN38v)AgP&Jpjwb#zk$Kp>wg-QGl*1K7(*VC#e4RFuH>1O?JSElb7XzmFZhZl+M zujjBSca?EH_gU9d?(UK62VNfe(!fjTMm+~FTeN#Q*WlA_rdeUt)y~$ZVgK62Z7h7Z z7I{C29kuN#dD1xfH?$wbV&Qe_y%O!wJ8FxK4ctFnK6KC%Qu)`z<ri5_Zv1@H%pm;q zWwl-_dy5Aj=;;{t8{q;qMvvp$(9hX=YxrHXDblgO>}x;{`bV`@hPDM8MRovdW;1FZ zkUPazDZ7;$f#y^!hAfB$lwKd5bRZr3Q?kXLUb_(~lT%?o1ApyQ$Yc9OeqdbJ*x}xH z+3Pz>+qEZ-M!)j<Ae{WMM_t>r#~U`kZ)fM7ZXbL>$BQy^<+s`vqsQ2F558Kpt(DQw z>?_k8K4Z?vSbshmm7$?nUnM>q#TsQ@Pdfg$;l}8n_bs+1_OC-@{hr}6eX*75Pw&nd zEYm|)YPV}-ftB9<>5#T{MznJ8Sig7J(~=)`?bCjleqnOrCT0D9KGK=%dJ2pfmX?-T z{VyGj{&KHKNeMR=x#z*r-TjG>-8WKj*4uDi9%8h%<AV@=j+S_DKHhUB=FOB?lnEf4 z0yS^Vh(7;1d=FPi^xcG(??4PHh<6gmQn$Y~QieQ?8=2+)k%H59Gc&y0a)|bQH+CUs zf<b!}c?rIg>yo#5Zm`q4|2@eFyVHG(66t<#qTZKAF8V(YATt4{#`Rl5KR2KKUrN?< zw|F@+EZAGa$7U}6SzO%*7KO@9JBp-tttD12;Ol4=@W!ScUTA&uLKEE--5=Y1TS;jd zG6b|+?vkKsveSE}aT=_^effn@xN;-w>RK!_je10QPCs8YbYKybudT5B0|xi@ql;Xn zw|TaWxVm?ac((5wk=mx8e^MlFCTgd3qm|ILAL%5+4$<-&OY4-CW;DJed8K=qNIzi% zybL-1$!0Jc`4HqBB=>67Hd@9vHyQr;A-=f6BwkygI=zQo-0|is8?EX1zb9gSNUH81 zV<phKM5gJ-wQ@W1$Ap(Y5!luAMI*MCzImZ$or+ykJ$H!PykN8lncQ0XIZ&EALYv8d zM$$#Q8L2MmgJ0=e499lqI94n}O<=v=cCiLeHLi3^3tqy;UjXPMNZkf)*S67k(SdT8 z#}1)Of-NvhY!q<g8_gLqY>}M&AR}d~ZF8h;zlltiZ=*;@$t;|TFVPcWIIVIzN%~xM zcB56_vnuL35R}|t@<iX;o8H5H`qo(ADrIGL{9g3n0QZZTJ5L?X+VO;;&QSH-vh=dU ztV3q&75F^sqB+PPl_Hna2|ZtLALicQIb){b+O<XwKzG)#W;R3)#rGz9RSwBn$iDD0 zIVa!XBj;1xF%Q6_thTdTb08^Xckm{C0j*d#lt`-wBy@Dgf;KjOyB`kUk}3{9jD~F$ z|10quUK~uv1H*1R-YfRVA4ZOKYg1!fFbVWmSc!_U!TcT`rK*4|1`@3i%YnTl_0%b_ z=L1`%V8?aJM3UqEXP>jR9fp0{7f%;C0k0#;;Wh&mS-l>!C^Fa6%G}h<r;-oj#U1}i zlv<Li#k<49NUpn}Q6CQbk>d75mvVQM75&fTmAX)j52In(Kw6GU`wVHLO)m4j=FMoq zVfRo`V$z1q;rCMYKA-*7-g|o4Vc1iJ%9PXSO@mpcNQ_L6i+#Q~_qJle1y2#lEvi1Z zCr5WLJg^9>kE^ZCtnx8kc)6{S(Sffe=ea!QSyp*01@CY(x{_D`Ll1Rx_=D8LVV&Ri z7?%RRdnFOmC3W~^>d}!RAbypSb@<KK^N{=N?@i&kc5`@3N><ws_6mmAQ=9Q0_Hg*p zf5Px!>Qy~R4Jsp}eU3*`%^c&-n!E4a=xbmvWOKMaHD2HLQ|jB5xI2DNd^0vFwv9}q zZFn9}BFmFI#@TS1u61(%mdrQHIF(CHm!gLt;a9ou|H+8R>gqLEeWV99Mhi=nN3S2a zjec5r)MwT<yUcFFD+!+?TuwMZcpKr+QTBJjHwgoT#|bN&#Yz^m31J6eEnzp|m4wd` zE+-ryyp3?^DAWnzn}h+v<AjyX$aE3TB1F)McWiYL&LZqMdIFu(lOu{po7bhzo=Ba& z32D%D@0r7-!ed&_*uU4jDg4J&p1FKto@_$1K;9j0qN{rodetZ2Z@|;@iSXMB!-5G6 z{R+b2fJu&sdUxn?dEa@;`-$+&eA5Bl@td<L{22Be_KfKE-ONkz1G5RsG3nkA(hOta zKqA|$t?)5lUDRIE){&+sU-eZDG~2huFJc5Xh3{qlODXkW`k3`YxM$}Me3z8Fh-n>J zL%tvI^s|vCb%FaX&u?+gbWPM@WopC7tG=rg&N7Ab+EkP^G=x0*&Cr(()?LhWmpU=j z^UZvQJ9(c^{G)j-IfKjD+|TJoRtpWv{Ul@+kZvI1s9ACvui*6K=j`J^ie5kt>$1yy zwW->;QZF}_s}ytxPr)&gSmD&cH_RHx3fBgQ;LYM*-FoI?9d85JEhyHyYszoAd~tPb zfd7o<+&7UjzgeWm+FHV0&=uO2Lgbx_xzF`jjp$1G%Y(j(a`bD;LwXH%=8NI<t9f1~ z^6<qIQta!)H>TEOD@L>#9gRDY)c4sfXou;3t<&%a{UN`~8E9<rPe{?PM;~N;_!06s z8hHCz1%*oW*`=GcCr;S9JN+V5{m?<i_wJ<j*i+FZ`)1kwyQ@ah@zWC5Bg_1~!wc=~ z{t{LyJjm>DVV$&gsL^V}R>e1vdU}8vaRF8)^ytE5>iPay`uVr_#a?i;(?1pc>^`|q zAI@M|LC*7s1ecRrtlv1f7m)jp(BPk3u9*(s?LqqyyA}zfBldAPfDX2yA&JeR{rjO{ zH1qTu9L=CJp?q)Yz6jYZm;N-=#)p50#WdemSe`_VrRs)UZjHJ7BFD1sFPa~vR_MPT z(VkG{{<0p3X*c9eK>P;~Z?f*(4*e!F@M0UIa6{3050V2@*@4o%zG27O`>LpSa56g1 zuIPt@@AOs;rg~jb-%v)Ijro-7-9O-pezY$auBNNl11;k*965c>{0w{Nc%9(=QRXjG z9_^Kp*dD)%pH3?`va`5ZgTIL7C`ab)<7baBr^HHM*`~>xj|_Z${~Nn6-`@Zw^&oTV zYXvK#=omo}JZfh@pMJh@@ESCqreI+Yi>+t`H)8Xk)!x8LzcspKxWQh9+<mIIv1fyQ zK2ms%hs$gjPCe;f_mDT5H-xSZ63OFrEHquz@$0P1nX>fO=&Omf&;bpZ5=6h~0jsgS z0lEIM@bZ+5*pJnSorA^9aXk5EA$aDe{vUe%b2k*65??_4IjNtG#CA7qL_Y8aPuF_( zwN<M9p;T<QX8s#}CUJKm_wMw^NZ3V>3~{b;uRp@sZTn#18QS*mM*aILww`JC$2_*k zK(^RlH2)p>F`?n*zVf?x5)`O&_MK@jgWK$}bC~sINeAM)(aL=q^Y?H2m+2zKbUM2a z-lEagc$jv59=YIj{Al9Vf01@hri|}KQwsmmeZRN6%zo<$N_o_J+U|cL&n+6l_z+<( z<qr$yjrJ7ub>-x<D(V@G?e?Hej?OC@qsWmD2}HJC-0QN$KfA#G+^S&B()9hkt9q12 zgMNYhU?2WUJhP&c70#16#LvQN#^*t+J(I70JYQ@UvsUX`-LrbvJ@I@)ymIuv_}%Ce zLzSkS7Mzj$>J3>FBgB1A_agH;zKlyVCmYds>9&hDc379}MVmmYgjOvbUPFJMZ!TfY ztF+6YOdG8rr`_|-3q^-jeJ$?~N{TC5#TnIW_4i6|2k32lYQV3^=I%KiFQkW^_cHa( z$mwOQ%Srn)r}2}qnz`Tx??f$2%`9r^OZ|cQ_4!lgR|)g(Li5wqW7PdD&SXA(sT8a) zY%{x$U{7PQU1!VFl$1MATyij$!|h})_ZdhHE9+XR{;JZ<Q+&4JJS{%l$SuKn=I4;q zb#=WFj-{?LQrMzBObL$kaF_j@UA(?zLuu=zmNH6uBYYI;xBDsS4fcKHdt;n_djpAv z^^F_uZDXgjpG=KQ@uqtx4`aEOk#HoM&pTzkFibaX`B~~@zMrD&m+r;hTuE{1!QFXK zjsE1J-RZ<a)|{)5rM@?{5dSq*ylte$KfwmYA4X>LcAj|`b|}Peik#?=s~xNS=Q?L2 zty8V1TN+v#TTLu`c-p+{Z@Q`Dn%vH#mv>y_%fx>+)zH?sp0A@r__%L`ufkS!BhSu? zet~%`_1BxX-C6*yy(_d#o&v?!jq}wW?7uo`U@i8u38OVz)3(a&nT)0D^H>MQXU}Ri zd(Jbbr9%HOdo**`@N{co{#6B+*;Cq&L}w3=`_-A;+R(Zh+2T*a4agQl`7=B4+S2_A z)(y2zRX0_a^UeLL{uf{YMtIHARvCr!%~w=A<QAyboPiwfknNQ5`$6pq)i1xC32$Y+ zJ=<KFYWR8MBj=;dQDau67Me|rYq;w$ry|3a6oES5>>{;<)E|;Mc3~0eTk$KFJ8)Wy z&(Z>?x8N5S>mE~DYoiYjHnOjNi+bh?KU~%G0`uZbJKPedZm6W5rqo~cx1$+SgES4& zxDQ`oUaQ)Z?VH^Gd8BF5@$RJ2nvQK}uNAJIgTd3{ZPmK6C*B>5Pp708oDp@f9u9wN zqBkx;E?s&`_RRB7*;UUlJ>3h<%UB!cF_%P3O8AS-XbBnkuG6}zqotgA4u`8!UhGha zyz&Bbz48WMVHtf5ZCY6C8Z(Q!4~M5uXiS~Qj1=oEL-Gx6F5NI`leT@T-QSmuwUavW zj-x+>*AFzUy29kkrN7<!{=QS=G<v(<{&mW0X{>Lfdk&%jf1zDw7sgJrW^zLJo`T_z zXj-8yuJ`vnJc0F(;S?C^Y_xMl;tD%Vhq18J-#@zNz_9G&=dmV<W==VB!a?6GWNpMc z-_b>WLQir&+(<Z<N*|@1=Z_LD9cj8<@INy;Dq`C<IL;sGa-$PdZ0P9Y6msXH`}53@ zKQ(~Yoq-ScA?>Oif(Ib|_7%pnAerjDUdNisUgTjZ?X!uid|KD_#vzw$<SM)Zw8Dkb z;8>Cmxy78}+eJ@nuhw;YCMIk6df`+NbG`A*#p0_%YI@7%3$eZ{T4rP2SC#K&B**2f zv6xS(9_$VXHHp5z`9DwsdFIdgZ$%>PHA3b9|00oX!%grTcct%%kK2F9L6<^w2!ihU za6#n0d*{V)ps=EYv~u^=jNQ(Q{dzr8^nU6i>%Tjhj-87XJ~Bygwpub;3TAyn>ql5v z5*g=v$mOSXSwmOpB0pb(hL+SRn355Q#rZet(TWg#JO^h<;?MMr`18n5?H>7Q_>)w9 zkMKrsx!gnsy3YP=_ebG^)c=z54l_On33XEH??v}=Dk)k@G-XAjUX8b=bu+*5d6|ys zcxR9?_lwlA>Y>rtM`#O3JN_oNSgi_bSZ`<HkHV{-U0r_PA<lypzQde!%59&o++FSQ zK^5dAyl{~!i;-|K<b)zx?jI+zB(8*eH~34AKC`3QZ`j8c8CD=Ae5Y*Ib&<+<86vUQ zePv<yPvEVHFKFikAS?WVu;<wi@nV$Gm&iSW#NZK2x0ifTvo^FC$ol)O^{v`tNZn*3 zDdKKzLq<ezX<xU=xhKqqb6BQMNnZ1lgx2{Wn!6%HkV7jk%AC-=<}o;TYuk|bnMiS@ zHN57�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%0AaFhG^9F^p!2G=!uw2l8ADHidomct&4`BY@i*CQa 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 LU*Byc@3#9tgjPB- literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/isp.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/isp.ko new file mode 100644 index 0000000000000000000000000000000000000000..384e6da3b1da563f2103949221d7264653b77e06 GIT binary patch literal 60760 zcmdqKe|%Ndl{b9ukAx5+ULb13SPu|2+NhT#XvC-&2og1xONbg3n}p;-q9M5?HyT@? z$4e3ro!AMG08*x0D{XnF%rq*UVfxUSsI>C7OrNyUmT8&k{gI;#Wh^tLeQ1X%&-c5} z-ZwjkXtn>m^La0y%|2`Iwbx#I?X}ll`^PzXZfVs$E|<$tKbKKxj6;U8@1)4dC>2qm z@hRhK!;9x!1P{Wp&pc?9EV<*Q7pETn%@uF%cxNR0(YAfJz4Xu}Be8^W{HA~P4p$|& zx?FL?jHNdCVu?RoxbRD3-(Q?${+VCc`MIMHB(ny-XnA8_w5AU9#-|!96Y~t?FYkLZ zmdK9w#LGseS=o5rHSfl_AJ3)!X;zj|owy7*r6X5a*@0NX6K)0GRo1fgv4lGqOYEL9 zCBFB6_r+aCZt5s`sgHSb-W+(}S09^|5nmlI|86Yd4Q@<+Ch>gy*^vwHWf>19yn(*t z^fx!Wf9Ar4Z+ZQ_Nk8b3mz>y(@g&j;NAFLb`NqY(FPT4_C<jjq3?qB-{8-{xbdPnc zevf6uVyQBudywY$*?gDzud)ndWvY~MxHo<c%J_p<S&-+cy}PzpIsP`Ze^nyKY>Dst z-j<D118wnrH*Oi)ziZ3J-P5N>_s`xk^zzue=+^1e2Zm>F*|;S&Z(vLDyy(0Iu|y_# z&Gg6SOfiB9uYcoM7HAv3otAfGU@UfOi!~i|tqT`k+_!LxwJpaJXPJM$aN$%rcyYyE zOnQt*6Q$-=mLKpG19J5D#{J;`hZio)R&A#mT)5OQ^#037|1Ciq*)GbV%rJgNIm8F{ zpig^~uHcd+<e&1)i6tlx$|7Jw9`(Sb98eB&_?bU?mE{e@Qv3aooiCO$;@hk#{)*(+ zfAEDQaiBwQxDDf59`sd)8GFrR#$L%Zd*a^kA<I2y;C&bR%wyCfcFdd;{}1pyy6{WZ zu^Yc+ZG--;m^qvP%_Y$7`=%Nz5>tJ#S6t|CFWT(&Z5~SipM6q}_S<x-6Vx;E7eJb) zeiLMIm8E1ds>y`%;Lj<Oqw~=Y=%Q;NmdH1@S#Id5VFXia&@ZECpBM}NV3IO!q8`*= zWi=r^6S8Ms1!U;Kn5jTM+aD!8bDL%OW2t@RJysAhyLU@05kS6c<ldym|3b1Uwkhcf zFG^C*UjIEw_J?6SlDZqX0r2mM$5L+pk|f(!8bDv8&Wz}1Acuz&==0aSM(h>Cs7bwS z81XDWbPDwwM(mA=@~3{<@;4xV%F8`x=>6%?Kd-rA?AMS@ZvCcYCS*$)zYq8@`n24K zzBbXX(QVdW-L*OSM%(5j$5|F|y~Z2p``0Xw@layWoE!f=%9P)+(+XU*({jbXkgP6= zCHl-gmK$}r{jpb`9e;jJ@aAuPeP0o9kq`Nlc>J&%=(m04o1ypBiMK(I?XN%@`Y=g4 zl-u88T>FiyEXrHyxDWDWpX|ce$TRj#$g_Le9s@2I3f1q*)&+|9Si|Nhc-UseZtS&Q z$Masq2N1hI9ZSqb*az5a4p{E%Y<NH5zhV9jHarYC%N(`bH^&l-5e@)8j{L=QV~K-! zo~q>?0{l-hZv@ZTTHay6Ka+V!@H|b+I|}#^>y$i=0-lciOHFt37@mC^?s34QbL{$0 z;CY6Y7YF=9nKy>#nOfdSz(10Cr|~>X%R2-3U72?l&$(LOIl#wc-g!J<rsWx*?zMg_ z^SpSzT+7P>{1cg%gXb%>JRjhn%Dh}W=V^I)fRD?(d^}&N<(Yv0N#+&cdA62U2>53* zuL#dqX?cFYKbLu>c+S`I$|O7&{aKFZzXzWCM)W;G05IoArB`Z>+zlIB`4x`;SZdh7 znD+0oet&5!<uiMQeiHW4HW<~ZYYk)eB^bBQJ@97g?!e&`ZBULeXysgnF^IB(`umgF zVb~Vf8DWRb`;%op*aO&PKSGfaO}bDI$G&Z&c3By~J<_))T?git**WGQ^mr?H+KO>E zGX;NOw!jYtlV|X3_;-R<Z&Ig|2Rqmg`igEI#))xXEYS}<rWN3sHp3X%WeNKS-kXE4 zj|lY$s}Q0Htq8qlZ~UO2vWTSy5I>91jj$Qva6Fb6&fjhIqdgIXK7=qrZG4(lu{xG8 zvrtbkn%tkW+geIHYsM0XQ0_baSfU1aL4+!VN(9<p^0u@%mZ06<mYEsP1Px`Ujc_n| zf^)6$Q0f5MO`LRIG?@Ga@(8DG{y;GKF7eT4k;XmN!J=)DUv=sqkT&FX#mloH6Ucvq zlD}`4bqV-mJD<Dht<<6N4b}nhbhrO4%$4wk!1L57+AsjyVobA!VdrRnVB=Ds13%Og zA@6$Ha_EVFK+Gp|khdT9Fc7#unS(y0Jv<5fRgN}u{wVd|FXjo_LZuU4#gn<qVw(<B zLnnOD0b@mK6X~Ju9MtV)zaqGdS*a(GZr2~gJU(>UFJX%f|Byvm)DMvd*<nu29vHbl zDdv9gxp!omb*TO->sh273|?jJ1nfdvn*l>Vp(pV3kX8dYhS=weT2nxCAMAO(@zP1s zg+D}Jf%84*H=)leEemN=Wm*QFGl7>SVFNPn8-f1_UEJs2BIK2W{y9{%#X6GMW9`e? zVtuK2Uc7&PZ+yuey~z`<Uh81_7PNOI=H@LK2h6K7Fb5gvr;H5Dr!2b{vf1f_k7K@J z?S)Le{?`CcvvxBr_!{DAR*cW}uOXgheIN6WqB);+gMPLVOS$}wN$LRGr}uRq<Tn-V zWjnJ5pbt^Iy{b*Bt(1=_i@t|EQ-;3>?Te+<{D=89aT5OPcGPbeJFMUT;le33hMl@y z2)-uGgO1PE@|J)W>25%L0B!7-^D1?kvZg+N7kTBgp*!e@4B)n=akj%h!n}%cvOj;D zw0GOB65t0V&JXZhA)i%0t9HMGyh2CbTS!xLdF`bx!+=0mAt4U|{;T-uYnWE}FRdf6 zzp!7>&qVIr0c#(|(QfF#%;~+!eFfVr6Mn_9c^j;LKKnK#58`<M&xa5XA|64!6Y*ih zyAdBj97B8*@m|F6V-lly7UM(C0pv~hD|0XpjL<(G!1^T`NOFvs;b?L=xW}SxEeO1j zJg)3(EJnXNX~1sL-{UxDKYM)#E%@UJ>PiND;VI}R`j!5X#mOAN{&)}kBja1s@$9PK z^dq+s9i^W}-<p0k?Hu(v8@?KB{?AnZXU4G3F{WYdP@5P7o*()}pBn25_?)pf$wMi0 zPw5$jeChSlZ~nQx7Cg2EYp3;SU;WEg#;Q%pEUeKo1F^)+FKkNQj5X4Ul0l5I&J>=r z;~qYTQ=caPzTS9`Z$<ok!6wUCu*vdfY_c9jy2q%G(~cT$do0u<{TOI?+|hV}vC%p? zk2E?`p91b_N&6~1pOLho50lbfG6`*y>k077Iu3)D7jj@dUL(Vr2K?i)u78AV3c}-c z#{rA7z&DUi8uX#_jO|vsF9R=I?8~#>P3Y&r@pKb%D(XpIQ*I=)jGpAY(pchLX`dV; zFT;-<NM7NKE_VB3E6zg4s-dfk<}Qv0ukE#Rl%DuswjTUcZ!-9uZB`ESwtpm+sQ(Uq zP?R-L)`+b*hq3{bb3uQ4;+P{*zRBvfR%O`!$C<DH#mNWn+LT;%*(R$Vp$UPwIX>II zGk-#V%e6n(j+a0WpIi5KDrdzWD+m2=L}Q7&>%R-Tv{TGsCE6TzGK_ra1LhGcSI%ST zyV*Iu?N+IIf0A=p*}yccHOBp!Qt8hGeD_Pg19Ojoxg)j*ekaFWbqbR={F&{rJ>&ii z_Brf%D-eVnpa-ZEWAjvNV2?#wrRlk=CiO0Cui@W8+mIT#ahsLv>qYyk6X@$~+FAzH z9@zD4VRs=P!@qfaJis5&>7LYV6z!9+19DFVGDt=0vAzyto&HEHm4UIb>$xc(xS@lt zoSIaIKl(oP$Va}>uD`y!FWKwsiT6U*uaEo?wsouZhJR}!!xxRa+$&N!Wxa_Hus2X( zV2uSD<d<|v1L>Hrw_Ao8ONFoRwa!S})Qk=lJjt;Oo02+*v73qh+g=q*VQ8P)_2*MQ z@S45vQ#OBAhc#hQMKWVXZ@d+@%8Pl`E$inV$!Fo55Z?{niSPRKhvQ=HI|0{Cx+@gj zp$T-cJQujIWyv6H7wL1a2kD~EGUuQi>}cfrt?)^Dg*@Pkyy$n?Yrp@Eeki~*%Tq3- z!ScTna@k?A?0SqJ%F&Oye78ZTAgf)spe+mE#=Zq`An$WGYz1BvK2UWE{=Nq|vseax zLgG4<Q)PU&Md3S5qzhkd0$tbb<8;qzbX_-0qzk>hh%W0ne*^jvW3meU%{KiN+8B_} zd+=N)pE*BsZlzuj?>L_GwY+}@oF!qb^TnJ>y%><X;aB>KeGeDLtvkrEYltzyF-X6Q z{E)VRappoE)BVt~EZ-jN^V#+OPSPHhbk%y>kGar=@*H=z&l^ka&hE9MSU2_|Y(^MB z7)0ow-D~Yc(AQUrPA=%cMyAS13;nr2zZd?-L|oMt?;?ylsT<_=yt&6Z4_?^@!e;@W z)!@^BPfPeDo{2Li;W*;BVV6B2<Kr?uCgV{VAC>VD86TGMh>Q=(_@Ing&#(!<N#kW7 z;C&h#102)foq%_0@BrWe4c-iRvxM14K6Kb|^vM`P7M}AFDiMMRVT5jk7{XqJ0|*BZ zMiDTP80Qdj;Aj*f1Q2Qvnh~N1!w5$Zjw75!@WRo^M<_xFBGe;vBWy<4hoJjvhJV!Z z+xvyHE{8t3{iE;0hlw}%mL&b=lH`?Gt4uYjd!aYmpnJVD4dX?`32>S+X7<K!M_HHu zKRACS9yS*B_>Dzd{Ub|~EN_=x)qD2Bg<aGm7uNON9M5LV^KY;RDd;KY%Y<`}d-*RO zNOB!c9l3z9z&Y%7xA8sh2cmiKsmA^9`|rL#DSTjz4G(D5&bQZ}F0&$8gf*Er&>QEt zbo)l%&qiCI`yRJ%WQsAr!rD7~kM+={a-L&7QOxD8Y1Vs~a~@ibwN-sA)d!r*r;p=! zjlGy>jcnRC_;jh?q8&9WurG+Z$!{(2y`&Y6&B1(ALf)sC^d0Sdw&9m9Bb#Y{;OglQ zyNuax(0s;i%nrVSy?R+D2YA^7um_}T#^ykNg09LZ&0nMJ$!FyFhCSq%R<w^@$$IRv z8M3U(W7(zP2mWdb{Lb-!XY#gJlo{u_3iQc?S{HRA-^q{4Bh8-!zgFXi_C?iMg|Z&< zBkP+?M$IU%=;i#8x{d?)boY4MX~$GuV|jnPt|eMsG2nkxyIuosRI96BtLs@+7y8IE ziJWI>^_2aQdcFbNJgpwuW!0uUl+BX;nKem09<83yD?YkCuK;)W>2cZ7_N#ghpzKsx z&(ulk`60%l>Z9gAQqMNjQ>oRnQ>!O9Nm<1Mb?H}HJ;o%siU;CuL_P7R#@llM^OB-< z`f@oApm!M`GB#n@(rp?9{zvJ;Q>ZJV)pby-t54MhU6^dlMKR{Qa?H_AaLm<+GUH<o z{>W_X@u#{_Pq5)Cv4=z(;|HD?KboFpN?So0tOEXtF7Phq=N+Q`yCH9T&c(P3z~)N( z#CpfD*QsR0@>5aoZj^`3PcfbTRWsHwA69;!Ufv%}!oQxq3gtyv_;bw*dPG^)E9{Kq zJEE6Ey_qOifO6#9Sue|80(o5$h?RK3bGf7Jm*@*2o#hIUM_z?K{NcjvD-GLc>cQR& z_m_Yt`s7gV#C8v%e%jwFDeo=Ve~M85Wq&{hCv(PisSjoUm<@a54;O@;U*)I=`%|Kx z3y4|IVesXae4*_n0SEpq693l{{|@0t+U?-@&vM{niWl_Xm-zn)`cox+j^h)vCbs(* zn8VoapG*9ypijNn@4(}^AMrTu$@lj`mv~VJ9({e{y(96yrsOWi9m~`^$|#<{CCgkb zc_`QMuy;Hkv^gf=+lnzkS`S}yKhDqWep2v>4twoe<+AthsKfiK;HPSRI5zW-&((9_ z3oHOH)F<lJWMg0&+V?4`V+!XI=reS74)wJb<(>0u1?pC~)YFKR+2`0U%>DB~Qy(ie zz}M&dF5q$f$aY1udo7OxzX14Y-39#?;2)9reZarUfq!<!MEu8rzf<D(1AnOl|F8pp z1@N0C{$}8R%7H)Vz+VddGKoI`{ACXOCI|lQz|WHSgTQ~#fnVytzX|xq!?t{O0>9CL z?{(nM0scOTe*ikN-hoe9j!Ivi{e}A!v%4k!LEuM$uiF;t<6aG)HnkG?9@w^*f&2SQ z<EaP!3+qAntx?0aSI;7@lxY!}M!Y3RtHcJ&Aq*0(8%7WxLEvu`@o|I`2yuilgp&wo z5qSB;i;#nmi;$1Nbq3cQTxS#lE<-p9ToZ8>!sX{LTnHo9*9dAq*gY$rS})H>+*id@ zl~U&o-*`HG`9WD;tpQ8@_E_{o9$YVu<j8$#$Pw$JyojXZo-vZ@yJkZ|!CW)3jeDK+ zf}}TO?OuqzNvuCeL)iP^kaaYt&#Ig^WF0FXvOL(cL0%T~Msqe=ik{eqk!$Tr2dy)p zRfhdc|IA}p)5x<otQ(j<+B#^@D>#oCMLna~V~3qfV4n0GE9%Vvj^J0P|18$OhJVoF z*`50;d*7pq`wV5{`yQSC3-7stz1W|&@p`d8!o5ZAcVL|CDsKiZ)-b#7p7Oy{^%ve# zc%<i*c-%|zYBUX;Hy&|q<s6m3nk_rezt!3Zx(Xlrgz3GGnyg-%N9^w%nNL1@(s<Y} z+{OKZUDsf5s;o!sXXRnvZ(}f)*!ZcQ<o1lrxT2Zq?~R)pehu&iuanTttnZCaA+Btf zx7ntx&M26U{lN4&1!Y?*$Al{wOTB?Swa;SI$5MX>SlvJ1Sx}C|{TDn_hq%YWy%zS3 z(o5>a?ttAt9MfFa70%rTnN_E7$LMF=cf)!sH6=fqmPg@SoTGzp?`;DX_pChrx3T{1 z#ky?JYK2^;<d4e^V}4wAxAh49E1HROKC>t3Lcft#(ac_vu6XyOoj%o0$UyCDl6SU2 z=RXYHbp@~v2ah}>B)_eTu@~*bnKX1KjAzz?^M_qo0m(1UxN%Nr<3lI2u;)x%_+Dv! z$O_mz<w`!Vzn+#S`2!mh<mr=RiRUf-kY^tDdoj1!`&87!@*iQGtW3eoV4b;AoQL>E z?@#(bt8Cs@j18W9R3~tz<Cy^*o(pnaO*&H~9h{|{(s7|X*?K<pjQ%Rdp`~cEe{r@V z`k!)B`&U`ull=KWpEv;%=d$2|XY;IsypUJ&0n?M6172y@h^wAiR`I6NC>JsI<$gWo zabTsiRZq}XaX&RS>qz<G%f3zi!E>{e{|MyYjQ(I>Qm^Kff#3Qe>wIw^<g-1E_gyC* z&M;hlPm=bqyaeY6^|+5S_n5F3XHhm2Z8=&FTZK^B*k_$6?;C<W*p-KV>Gweo(f8j3 z+>bq1+7}}`mM{@Au?Iw&w1aH-rT%F0Qs}w|XGF0}qwx{UZ$a3{6R?8@&T2SbDYx7b z@QaX-U?MESyjPC%9o{>-l`;ih1#!^!e%ba4)~~hQvoMyJhrqj1l)-86P8oE-eq~8} z7e$#uZSVNiJ8XRJ*^}=x<(qJ4(3V9(XCL&hTAYJ<5toCHR@6T=f7~8oeC_hyJ}&>~ z?s_}L_8KO}74%}NHm)B5ZrUc^-jhC)$cIc1xdw4IZOiou;0c+6pWQ|e`p1^Tx1rmV zfnU=h@~q3`Ti8>7R_>cpW{051dVUbJDKnm9=<<3sY`6bJ`5^8CHi|QhLewSBaC>=v zSDX3=?8i}0r~|HOCC<VgN(fzu#b&u<F%Na3l=P_+ps#d-^C9^>GO#IWfY#J4eR29P z)DPCTE!z{{&h1L<jTxw$bUipveHG^wUjGXg?u9Olp&i6m?LE?ZIIY`vq0O76&7nR4 zK1H91`05<AS<Byn{8|ZPT&1FbE4BRF0hdXb{@8thl`rGM_~$&K?CxuLR(6-XZ3E2l ztj`-~<k?Np5{&8apjFnm1LNbTkg0vv(F$K2b5r8-t8JUQ6*7!27}qJz^PDFRhc_mt z%;<?zue`<<>+-8@eKByZ^a9E#-HKw}OuNQ2lQ-m<Ngwk4cU(+!%6dg_2XM#fJ*(04 z-vN42(%WgR)O?JmfK%?|6YVQ4*$mtr)@5jq8h7o$t<-RZodV6w_0PvM8#c$iCC^)4 z56%~7@qVH0KY3?ux~R^E$?Ak`GL&3ATfk#a+7F^^YPGhMOW9=1>5Xs1S(bO!R_k=b zRx5W_kC4~V6+>2rHok?=C2gzsLEGP<T&HO`_mIBAd2Aeq=e^3u31~Pq8l9yY&O#lh zX`IdsO^zI2s;){6=T+IySo5dz{ZH8EPX{&KZiRmCmv9%JcWZf{13Vz%9z3h{1;^B8 zz+nyd&jHtK@LvF~k?>dXtj5#pcrKUe2l4Ee&wr0+<%b={vl>s|!?W_i)Oq$~W2uj0 zDTuMu%em&q(3#C*PHu%i^SOHXz_4dZwwWt7it|RVIb^*~`S@(Vw5Gt8u{xXNxwJ0p zztnIm6>fulj_JjDuafzz8lL|~o2FqroT8p6UAi9g8SNw1ySuy?2g3f+=3<;~-q0IA zI%g;DbW|r=;qxxXJd>f#8%N<=zogaSRpT4DqsV&@`mXeBlZIEL;gQBPjV9_y%fXBB zO<9w_BJy`F>;(E;%t4C38N4U3Lh!c){5`({duEbe2K;xHB`+;HU0MJ0>us4GowGyS zfl$11ET{Vd`-GH5M$pC`oij9HjLp+<c_)?p_Q`pU=c?WEnPUTY=}#%%6kpYPd52td z`7PG)bosGuy8OO@IVVfjNnUObKA%)|Zk%t+gZJ}rZzkPF)o)53qYimor{VJM2jxK< zMLnYK>Ne+pq5gkCJNx8#s-g_!a}Azb<?~~BR^xO%p4Axb#<LouLwHtWl;c>9QQWsk zk5S=ANSZvKR%3KOo}KfZS|{Z%w%15yE1^%ugDKdz*<8<#N&k&^5yk-Ts)H|r`H$^o zzVh#=AN|mArHktRF4sX{Hi7ROgkQP^>lfT{fZtFf*Dt-njqyh*OR2*(!KjcWX}=6R zspg~yfU{Hc-8{8650rPU<PkpKu3C+U4mlTl{2MVAwgS(dGjUfc-OshS>&Nwu3vEW6 zr?>ew;IYlhhO6~ojikf;^qAnCK`9gRO<krw4NM)EiMV4+|0+0Wou4@*e4bY5N-gdw zx!kx9fHq~LOf7g-@?aadMppKnzLnA)u}<^F5>2wNS%yBK(i`$k{0fyHjHT!Ul}UIn zo|Uh}vb=AoY`e?AIt#GU9o`xIFx?pr*t)~M2+F>o4G8M83k+JhH*$ScjXi!NJ6}Fu zisvl(%ynUod}d#8UE%>B^bN~q!IwrqG0i(kTE--4ZbzDG3)}iLtvzBrC)c-exmV=e zAL3d9{&b>7whwc}t{Sa<9_l#evm^QMg69<}whJ~mbq4Jiac#3QF&E*SDS`8z7b&NL zdD|^Ti)ZmjPx}Hj25ctUI*PlUEXR4q1v^y$pX(58o6<i6wtOnf`Q#i49b`G;b3L#6 zl6vq{tuKk=?8`H<{Sj#g$fNRc*Q1Wfd|ck)$;Ddw@~iE=2siw<C$x4%7uaK&w3Kff zLjGjFt)le??gMe`kQQx@8hidbKnvrBK7;Pp(qFvDudSzFyAinCC-}9T&oA<8LDP#h zwbwHQe|9MC&vIO@ybHdmpJN$&1hY0;OGRB6n~*2h@5<LF?_S7ZC3shRdgT8ujsJ2b z3-pcGLtkUu56JcOTAcG25MTDCnt#}r%+u#R-G1rwp3`rjj;86+Z$Q8ARJH(P;3eop zzk~<ztkz*1A1?z|J|u03nwOYIpE0P>;hgS)9a8fWadiK21o_H;{D1MR^b&W<()MLC zom6vE-y++-jLzZQRGq?J0@n7F;keIUiMG;LQ+-2QeN^s^wqjqDcUX0N-N*Oh&L(X) zW$pCQa3+zKp)PBukCCt8(MR(`)_Q%TbGG80fpJ=1=`&2$zqr>rX`Rmg#ajEtR@o1% zk9&i}$<X#PVTX26SG~|b;GYU;{q{}3MG~fuZ_4NI;92bp;@mKOpY2C@rrp3kN_wAC z-xuUPP|ER0`MdBx$M*th3)OyIm8@gJ{vpcb;cj$U$u{@~EAjpu?g65op+~d0r^G#5 zeIJnXfucu#_F)50-}^KD<OBPp*yp9bU|%mUT+HW{;`w{O$KHgrfuE$@dmmD+NY+;| zZ@j(_tNX_e8cN3pr0kC2yn#HUKl92YJ?!nyHt<ZDAU%uwT+=uPWc!G#+Q;Xur~~my z|J-*mSK732XY~}vOr@N^AhNV=tu$@@KLwl|*+1;Z_q6_|oD{D<IUaZ8UN3op&ysx< zb5$P359g^d=^t^f(sh0e^Aq{feXJY7httP8B*!h!GpIYt2Nh#X+TJnDk!sA2pdK|R z`t-3Q>r>@NFb26Vs%+wzY&XZCKCklLukx$Oud-bnKly3-#CXR!JvL5jvf>(8m)Akr zx5}sG{B||?7`Op_4O_{z+uTCzZNgW^9+&Wy&%5C#!(ZqOUbsAu@7n}pp1ABg42oTG z@T`}0b1xY-kG?L?ZsM{JpgZaI#-%*en8!Fv(Qje9luag0wngay+s`qkuj`c_bUXAQ z4}AsyPUtRm;V8}k*USAKL$0&Vqp$AMc*@6_3Hwpg`z-oB>=Wt|_hczAmV?Y*oR2%y zlq2sKtGTuq^zyZRV#?vXrbCcdwvI2>r&5pdr`UQ_K0dzkShoRtq3XstQCfxu_JS!B zot`ll=NlSMKJJ9GO-`C@gQAJC_M)0ENl)q9&mnu=C+Gg9vc(7RoF(;7ADc?wbX%Ou zzJVNeFWf3@@wK9FaE}wQvYq86d{1#@>i5{IrcHI)<jPswM8CMrEqpINTkjV&-Z*Y_ zKcfaZW}o#;Znr5H&e4_g@J=hvaoAqP#}x2JK8RC+xq!T3j0xTp&y(@Vxx-)lF5cZ* zg7<V*@|~Os^9606k{kVC>NDpsj#0JWYjBSW_0ne2rlC!^yH%Z9inv^^iLrMeY%=XI zpPhQRRq7$v$U+Ba@SJHy;`5+ETc+#GpA+}t@i8pq0(+i;^$}@P2X%cJ()5cu$bAg1 z)oIhYURUQFSSO3UtN#gno^_Cy=RS*bj^KAvMm^@)jy+ak$#&~Z&UWi`{&s7?W5g-b zR_u`(#ke1$`K5;66UQD;VlC^IcFOw*$LkJ@XR&3_51w(pSr<!Oi;&^l5cim_WJa($ z&N)ksX{=FZ^BkT2iCc_m+s9}77J;^q*X`qL1=SXgd-}xQmT@^f*Y@4irF<7AJZM#I z!2Oyz&&SW??63-;%ct{qXzjti{rrpDlUd)3cPzE`w6Hxpt&M08>*Jb!@-rgrUtn$M zJSWn1--~|X8n6Sj=yTF8uq~vE@i%Tm<hurgYA&gdrMQ>6S;5dl?%_lv%y<8u0Nk9; z-)TJpxJJV5cvgND`=%Ojnatz+h03;&xBCI>bJ!8UK8Z`6;@J2D2BL27)tRdDbE?pf z)R{2%S1?9B&~G!(zMCz^FYFoC?c&Zi>FGWe_c?&S3pGGia^I434Au{7jN;}B{j`(H zuBrMdM^RSVZo}9h-d*r2xuA?1*QyNfzLUpH@CdtuGv5_hr;l7_-)E1)9ax$A9c&DF zLAs!)^K0;(DiiasN&U3z)ARGC@0W+M%lGDT=Wfez`BuC0=Jsaf&g{+5{me6RjeRJL zGkviS1RY)cW6O)S+hcIZIxv68ilIGM+=;y}u08AVZYB1Lwlo#Quf`dY+K(M5EwJ|t zqzo&TLH7c<hw0mcyEpO<3+_9dfj`Kz;@p{opp7-o$e^`l^>y)bbC1RMbiZ;<f3oXt zTSvFvdR;sNeY5M*DIW~3?icGtr7L`wC9NmyFZ}o}ChzSinJZhGhcofL3t>+KJTDF= z$^&>$IT%a)3+}^Wyua9wJf@!p+=lw168<~De+D=rVcc=eo&p&V_bmD^3-+DQJ7G_} z=u5-@+E~>Ss0V%c`@3TvzSl*)<2OEX0^|2l4P!gr!M5M=UV?k~e0QAhjo)p)m2!ix z9N$(eGm7)e8~0dcVZ8f~@_etL6z|N5_x}MGA{3y{c>iFE>@U6p=0$x+UdDTRu-Ek4 zZwCDw>>cRu%@ra|j0?QaQ{m=&b34U*b31Rh<q$zTxmVCHVL15Njg*UoA3%P$e2zg5 zVfp+J<j{=gT#QHFZ7D^$^gH#ai+)cL^7$_7D%c{!?1K)&SB9>7@!SL-C&zEU8!6s7 zyz}kU-8c`=GWzfi{Wg5tU?}M^f8@v5D4~o^(7(hVN1x*U?I^ze1AB40%x(kjm1YOg zx0lL3S_PPA`|K~++u3^yaSzi^9~FB>Zum<x5!^k{%O2}9@agtRI)_jW{@jZmNeA;; zn$B#{S*6h#%kQ!7M%he>y9~JemI>>`x?#2-xO%$`?9;Ga8*bS$p<NG8k0!s5`@kD+ zk@s03OPq5Fo1nM#dRfocQBQ%a=QqGB#~DBMfPKvG<=E}~${1tp>zx|C&6ZKM))tJX z*#p;)%j9Gc`)32+i#@eh;<N3$<um-G*@CX`n`5<Fx%`=L37uE{K^}+)n|8{t;l&}V zvq)3pCKq|^Q}%~Z(qrMSptuXu>x<2B<NX=T>ofhuZ)G4{270d6%X%^p_&kH_1zoO` zscBA>X$1TZ-%2|dOPCllhHsm7<JB9)xgT})Yw*#Y1f3Dwb62tx?W?Dbd~=N7ToCfa zyYW2N=d+55_a@syeS$nHuN#+RVAfj}?p2&BU4!;ve9}i#>!uAZteXJuT8_Inl^E{` zP8{6BPp^yP0s8UVg^#7q7+R2D3mTY9v^_xJK#uBs;c?RNA^(~wAMkvE_U91bmoAle z4PmETfH~)!h5mm5{2s)8_K9-%=9mk2iOTDzS!gS4#zUz`AyXj-w43vK@WDNTF5kl) zr;R;K(57sP7NgHW|0&=WEZAe!UW+<>Xfy1E|E*CguXsRw_iC%hgZHOwePy309XZo9 z(YEpqD91xRY-=9q($10}*m=<0Zq-X03kQ2r8%x_7E3n^({V*Hb{UJ8CX>gBKFKsOE zusdz+kCA5c5={Op#*MPELQh|MJ5>-t`_Z1P;D+Sg(IcrW_<T60n_vgt!FvRJH??o1 z5Az_te^R~`?*?Lxgzrm0CaLYS=EeE_i~bqC@g-MnNIrdyt<QOQCzv|@w<yp1!5rJa z!u{XjdE<JSKlew_nOB5Om<bsVmyFx(Bj8uJ+h4&u1<vv1a_|ZpG&=)*$@xg>jS&nc zw}S@-tC;@dZ@`ZUeiU8WLfZPLVf#3KUv=0-FZ$s{)bXlj6Tbz%{wL^=#<A6Vtmou> z!M-PrZifxX&WR@f2WWJIN6|NsQ5$6(g#O<MzGn|v`Osav-|Vz}e1jls_MjCuqz?n! zT$B%EPRap(M8n@acMo9f^Dh{*3Q%Sr%53$x#d?P0b|1>*;VxzY_NiRP`qY6rxbx_K z*K+!3E+b&urNDOUaM7R@0j-%g_aqPEo|oVa<CSCepsUX+``%WoJR9GJnZ4C2d~~Z- zao<*}>eN>2(3?Hhh^xn{M1BzYhiCLyHNZKtqQ^SAsK;6b+$P{2OY~Tyz->mER^T2- znG?Vbqf8O-$AEtx@M)Ae1KhK~JqH{=@=K9#V9xYn>}`<!p!$IF_d4W13$iZ48i+QS z`YY~btM7%NFYZBqV!<u!=sLvZ*fS`=JN(MOp$%D!^a7-JJJK7FzTq0XU+EJ(4)|3K zegtqg>=5P0eBR}!KGHU+v>?(9d~1QeC1dV2yA8Y-1RTHnEerFFcxS*Dh^3C=emvtc z;BajE&>rPCQ}6LTmF%Aa=UKTHcm=f8`iXrv1h`)2y@2Oh`AmH-Xz>Qj7FXbUge*MM zx8-kUiz`~x;*A!z_@dXfn9=EonSN!9VcZ0~n-S*Xc?Qaj!Vgy8O`$)m)-LDdJ<%-m zgAs<E3}Bx$2wlY*@8BHV6U!g8u6&911A8-1Y)t0FHYYP4+lafvJ#jzmLauwz8XedJ zeZ+SZrWo<^=;q|helva_$1TPvWtltIrkCxDCALm+$6v-bSeD&ouOE!~7Rx)b1@98# zTZ&l6_^@8j;u<K9Z?28t9<hPD!zS+2!k@vJ;q2VvL90HBccL+twoUQG`7IOIr(>y| z9y7jpS~S@y=P=?Chc;;2lqqq6GsTQA(r^s)<vDyGG8b!-Tq*AiBQDY?N6HKP1jY%- zPVB{~GspmBRnNH@>lGh;+Z8GLvKY6h6X*TGJ=WGtPkdMYhGZr5U<ka4aSHrgH*hdd z3}hPdA=8XkaGeQV2QRZKxi&L<+?80HVO?|)UrbYcVXxWnW=z~8+Q+leAml;b!aR$_ z_bt$G*qh0&^4V*s9q`+$Fcy`6z&$KXM)<A*?g95;{{VUT7KYdp;2uz}jyr8uDneXy z&<YUOx5LUU#vBA&&9-g}&5N_W><iJ}0NN}2ertw1zO%S6Ug6sbo>rtPXAWk-hjUlX z?8|61c35ZL++(@TP4TrKM3ekRPgeNv#rp4yJS#H4WF1}4Z`$=*=g_a$e-U>S!1r~3 z7EL|~`^~-{UN3b5JPd$`9pIr->7UdEep8A(s(kgW7TzCSjCo|gVSh)XdB(&wD)x0} z)8-f>!cHZGZp8<!{o$<^>0OAtlk#-EliHG+7r!D7-imQ&2X!}tXMsB~jyoLPYF+<a zEU{%9+PMDt#Pput_#E{A^p4*5v#`JJ9ofut4J;*M+`~J`eq!Bj)@@*|&9+2I555uV zz9QZu#@UwMd2u)E1&wsQ(1CqX8*dKQep@={#ZgZjb-wQ%dEWkRk*X)Kb3$Le3_GUU z`4^ZcS(jnr`$?&y_@eLkCy&hOw|MRvz}N|BV~0GKO1K62h4R@T{h78M*aBUkf2eeM zFUA+vU_zgjT~d1yhsE7IIo6<yQ?Os9?%ZIVo%V&ZuutwXF5|g{&}HuB)nhznLVpB4 z<ih=#dc2DO`<LD?%(``aUoTUm{Z~5e>v}Q2ay*gVc>S+9Z~~|wV^qBBBlb({W2x5F z>U)27d7il{{`aAL)`Rf(+wt9zM>CRNd1$<yyzi;-uo<<hRy#X(FZ3i|U1Q_!#eONz z-n_mar3%q@?)}yx<{t6$h`9$!pF)gB1AE&g1CZ0o)Q!mV7mwmy1HfY4Se>{QY0-uD zJ_Po$vi);MtyS>Bd$4DXwR3ivXTYWdSrpOM$TJCaUv_y3?I7NR!dOwZZWZK@xgBe` zp7<)ro$0h;#3c_nyB7QDOwTkfOI$Bu%8qC6M_u;4Ykt>ktlZ|y1)P!#x4@srUNLwR z{y4rbwR^=LYxn$t442vH-aRLZ7<Y^2M>FzFL-<BmGm14D%Z2gY40**ph1utCx1Vtb zAp5otuvS1m?#A2q!@&pdHdRPI)@bSb@JxMBcC`R~<g}}|f>-W$@*W)9$h)bnScACa zJ6JgL-({3)wz!mc{n2*JA7OK=_2f0S&WinD_#9lX?VsNR-iNF&g4TQgMt+9`kKB`E z9gib@P(H7~bH5sY;N$avmH$DXgWtZO+-d(=mb`LrSot29<5D5Om6AqgFqU`-Fmbsr z%d&2*Y@^I0oq9a0Gdl9fJz$P^jJ>q)F}?>X-q!{j_*Ndi_u=->687^yX$PS%T+=ZY zbFjSs-t6CFHA7BD81q%}4$P@Ltf6_=#!c)Yvu}AWJEcCBFasNt-ssX~1=c_=w0VEY zSF!(b0N;IDiT8DRhH_BI4eKJ<*RNXtN3*^AagUrlseR}4x80;4P%h_NWgBwjyxGov zh5qqgLk|2G+9eZp5w8|wA_$+KcAE2GEyhJH_F<j2<uQ#$)`!@ikAt(^LB}U;6x(I@ z`Neh#`(3-TKE&RTPu(^x1MWq(NwZ^Wd`tzNK0bI3X770qS~c(?xEEJbj5P)N`D9vW zZQhhW0^4$tKZ3I}?1SN4OxZX*lSfsC_ttbD#+@^Z@6}~z7?&reOIt-boPd5RfBaQE zH%lIPH+_|S#y#Eiy&~eU+^-O;vkbx~0jKA@diy?Oo@!6fzIT)*VcIy33C?*O7y7<E zzmsIdq4y@j$TsVjclRgnoZgT9^*5;B_y+cuEsl@<CA)==8vZYcvjNi6=@git;|C4& zH}}#act^pDZ=H1`#(Q^G827>q_}3H80pu7v9Y$H`u?x0`W14plU4d94Jge7=;C!?j zf%{i(jI#`%eNWjPjU_$>nP>R7z0Yrh@q3i**KA6*-_n=dfNzKOn9(@L=e#5M7ODTu z#DS5w5*}a7#W{p~Qt9!JbpYEJ!F<K<n|W|{cO}0cfN|``yFHOvQE~Tze31uLe_T7a z7Ioi(y74VF*4yik#t%f_!k%0#bs+k7g6q1>s~eKtprw!VDkvuVM3<xR(J{Bba2j?} z+M=}mqW_M(uT7Fy#(os?gPq5G8OFPooTE9v%6V|yhO&=9TZ~Kjtol=ZSGW{s7dw}O zCgd#6OMTdvfM4^E9{Myq2eR!B?;>^=<J*I<huh#wsB@WjfLE&BQ|7o6_XK@|)}C87 zCWrlRC3v5MWt9K%BFdC$_k>;WZApJmJMeu!fo`p!j(EuT>&ACcekgse_(k$HS$&x2 zvL9!C-vR#kIpj9tYv-xgHFG_)Dg9oue)ifAT(8ELkp-E6FT>cB$X@s1ylq9>)ZL7S zL8D0HPu-b(rEZ)z%7QY+x2$&g_4-iPD<2_)emNh^MY(?HsOlU2T{-sQm(z7^Pv2L+ z(ou%*IHmh4j56(;lCS%}o8TI+Ue@D78L<cHhYs95<%1r4pZv=Rl*!khdp^neeAs+P z^w03>jaX~j?K*(x43zbONBW|#!d`gzJ|}oPSo|I6(DpR$1-Ff-+Cthf=o#<5Dx3Rz z;OI7&Ytg;Myzjb0+%cdmZ(@D=ofz<Tcop_uWB49$@$;53Ks%0aWlFn(eLCBwd}GQ7 zy|?3iK7@xcwn@9kd?D__`+(nq?y?S5rd2P4_y0thJue9R@k03dcn<cgzvX{N{9Os0 z8O&yTc_(+#HMU%`z@ry;090GWJFaN&Sn+p7dleo&xH<uk@)NkAXF+~C&F?#K=YcOp z_dN&Q!wy`&!>H)K@1Xl_2ktz)^C<cd{GN2s{gM+G-|AQW{jUzXJDj-C!%qLN-ebR? za?m~C#4U&JnS<6ZL38X;_-hL=*TD8;-W6v#*Lk>3S(*AOZ9nXtdcSfc+xBJYqi%(b z9@b#48~M#N^{wFD+VddJS_g49Yt+94AMYirALpe!%k9^2`jE!&sb!*%6b;@xP<ICS z%zZE&z7OYT7(3}S+N7s(w;%vo0nifl884-IqQ6^&yf0%fsu20FkBlaU{iC8jW8@`! z4P_2l**GsB_Wv-!wGe%w*L^=soWH?to8f!OI(wy*1910XEpQTfuNyxEtsf>vk!MV( z6ZeUc{|f3nfV@fT^kd%uIQx+w#M$b2`*9Bo>4QkGa-?rY`m;!{b)-j--h}iTM|wTd z`E9j&M|u^~OOd|HkzR)Me5CWNH_Z=prT}RLx8vL9o~@P%9L~S+-)9gf7kOfiM0@&c zfrELKXWN%RhDD%r4(F;z#P`YMnh$s^H-_{|<nKqGnq!sDok#kSi^>gIymNYR0<9ry zb2GlFh<alv6GIu-)LHm`Ys>|mn$bN0chKrXeiPD&OCEg2IIe0#6L10=PGAz83gF~x zIPUC==@bCx9KKDa>T+v*sk*$tIR>1)lAo+e>Ken@>#&A18PA7-)34!}lhD}<9Db8c z)iqhW`hZiR;ke+RD_JU@n}B0#IP~G2I2FJ-kF#1;mkWE9PMiYZ9M^E%li+xPa{xH| zK1x0~&mGWkCY29xS~Z+W<pZ2b4QEpM0H;91iB2NtCg2zv&SWyI0L}@V;i`5`Cc^^Y z@SIoSOeRAwa0Ydptc&G5hI8DohBKM29tKX8hU0SRGr#ASwg(u$yMh08+ykmdJBR)6 zYPK6=40)8}u<SFXH({jnJ9P)N^m+%~8sPjj=w<=$bqC#Y<b4Bqr%}dPXMxNcMV_-< z4)Uhqe$)X+xpVkNnrhP-ocEr=nemxYoWX`McVNCU241qp0FU7edMtMwm+vMXMcOwn z-H@Di=Z54k=94$@Eb7I4^13macpYcGUd#u>_*OLQ*oX4zxd!E@nz01Szjimuq5MtL zL5J-{`C+X*zctPB&5rU@Q2uXZdDhSJdi`%W>MzvFn|fQ&m$_)m-$1T|NO#KaJkEgs z7J1#sJLBk&F`372+5Lwj?<n$azN<IM@76iX9gukij&d=4*G=^Y{ggoubQ|a1V{iS) zs>ip>`ccj>R$=XH&pS%5x{)40{(Hsmit_YnVEbLLH!~DYEpYOI^ZrNRlmTY|Je-s` zs%!z$yOI8{j&vW=`OUghj&!!++}u6zv);7=$QN`pe=02ZFX?0b@I1~LC5-tr^)G;f z8vH)sfWkLpsb2wB-_@qi^gF<&%18M>0QPCH2WOmyqKEn-$Umd@KY;%=z;O+30RE^3 zHv=Bg;F|ysYj7!Gwbx1i@D9KOTK;0dQ3<nsO{g!d;Ck%G1Fl#2;I9L4P{F|W0}d#B zz-55_TK;{YZ))%;@_icoTfkhiH&3zm5Gpe8on(Za2>l4n2=xfv2zwC@AdDa!MTjGu zK``J9<{=a!lp_QYnh_!hn-O9N2M~@T#1V>6#*c6g&pD_!fDlB;M<_)&orOFE1DkMJ z2tI^7gaU*j1V2I<LI9x>p$4HIp&2295Jl)m*om+gVIRUU!a;-)gd+%}2xACm5xnr` za}kOVN)ZAGl?XKm{Ro2yeF#km%?PasyAci{97Z^X5JxzTa1Oyc4Rp}Ha)cZ_=OLH~ zg-k~XAXFkWp{)^woe298Mi7o6oJ2T};DZbb5Xum$5b6;k2%8ahBMc)PMmUbJ8Thrn zYsT#Z)&))GHI|7qW1;4&BE1{wWk@e`r1v8|i1cztdJO5!NcTF@4<J2?^ejjE5v1=# zdX6Lg1k#6*?sKG{LHZG-7dX<rbFRT%vumtEM|vL8&mq0YkzRy!-;8T4zazZ@>4iuy zb)?rKJ%IEIM|vyLYmwgMNRJ{tjPxo;`XJIbBfZ&?z7Od!q*pr94<Y>^(u0n4+QnnY ziy-|t@@W@o5A=P#QS(i#eYau_hI3?$W3dkkyGPrCk(N4xe36FX!*c4~qS3%xVo%i- z7{p%KSCVG{`<?rO5>{m@0=#d9Jq82!TIJa^*EJY2xI1a5Pr+HMx;Mc*R4dMAT;PTD z*#^Eljda0}IwuX{EP^!nH)T|L!n_Z_G&k-&=;>$S6LH<ib?qFn{(dk;8L%Gi!L#gF zamL8IEO|cQ)@O?SK-T}2+b)lH2;9q3m5ANbE=$d1jI#yo$7i!_6V5rx`Tm7G=V-z? z2k)H)=Dllitu_WcmoJv8z+SQ|$3BbT{TkB$xs1IA_AndJC-Te^=1s`Li~C$m^ZMTv zJhKebaPJ|NQy;Z5P5bX47I2>u{V4Lm6Vv(kt9<pn7VnKr$OFuL{*91a<m-9dH#>v9 z@G7(^fA!m<O;u=*I&)BR_sKqWXZrYed?1G%R=5#=XA12h&i;C=RY5-pI+ROLo{2I~ zq(LscN21oV*b|@4cQ(0S%)a416u+gX&Ruc-F1{5=T70jKd0)J6;b&|w&+k>N=$+vn zmv&}r%VoQG@0QOmqKvBV1>o`?t<p2K*A4x^*@N^kpeN;050#F)PCSsj0AAby>{UVc zOx%@TitpRI^6h?5_xr>>Za?pY4aN04-0Wk_6nuYlHp>YfQD-jhb5s9$pT~=SQh6LB zxHpV_B;%A9c`7}9<^p}@8I3xN^x}TcF9AP`3W5mwm@dQ_a-sBHyxa$Zyqf~C)U)^w z59EK!6{tz#?l<<Xq)z#UtY`7JSvih)Zg@ccJu&Exr+eXs41QNj@DIGB82hyf#{ST| z@}80x&p*+g|4BWge*O(owvT58c3)vUgQt9)*Mu+1v-u4pk9UwJmb3HrAus(N4%$F@ zDxUcsTlak%EVfs*^#>fIAJW!$q;Bkn42K<ZEXO&KVa8JiXi<)N80XY`ymMmZF7CAg zOWwBSg0}1Tj#XciFQ?wk;Wq}M2i$vXfxIt=eykt))qBP8&v9AiMR5j!zk%g)%}C`y zUb>zcGqBeOU7K?yXvDY1J@J3B-x=_4<C!pq+{%;>^wM_(P`?K{RtY`N!`;9N%nRf# z54yv-0Dnsrd+700A@YkR$;&}r4)Qpkuw0HTSA|9$g{%xP=tt0XuL}A>TdizKg*HDx z9$DhMwX!diE^sX51?+d7DsV<d{dc>f!rmzvj>&q$^30mwgUrEPk+XX8`GU5d=RT?q zeXb&Jyzj=d6Fpy_vlPx0+y_h33F6x%u*18>y{aMWEY1R0e&9{&33MbrWJQtRhkU+M zoMXghWa8_<hw;5!ZxHL^ks<s|SlDZ<Rawr!_uZGGuf4uOQI0e?w!FTV@SZi!zz~;% z7IDq_lxr}F_b|T2`J@o(g-Dw^!oS5COI5ucwSqYRtDP6MR+U7xafyBY`aRm%9JJ2* zanBKDnt<C3-1Jxt3|b@TZ~eU{*rV(N_#Po`1NSA}Xy4a9)t7vBA?^u7e&TN?V~p&R zI^xO>bFP1pJc~IO_AU%vQ{}o*j`DmKJaBAvPg2f{`@xu3PkFJHT?Kx4Zq4_6Nb?Pm zzRjvYI@YNPe#56+(%}5W@fO>P^#}AN_ynPge||KCzd{+~9U9}TLyvvXFP?dtLF}0a zaCgnv2KRg8$%yY)?|EHA@AG~-`QdlP`Cc1!SlMP}<Kv(U7kt9_C=5Vn(SM>(DFck> zs+q8JuEF=2=7oMR#!5uI|IG6Iag3?COP#wDhvQh)q4LG~sXq$80=k4a3vm`=rsv3X zpG?nXI%w$hVfPa`xFeTqAi&o0?uWurei~$w@C9ug!Ee3oWAQl`{pQ0M!@Cp-^!uAW zv+p~(!M^W!(6%!d)dgGR8xee}I@0Zs?bCVlf+r`Q*C*QmeWJf}Y=(im^YPT@XWFsh zi>0>kS>}IPrDF_yPdx+Y$LhI0mYOyT_`Z1Rdd9Ncr}+%JQO4*GpJt0(*TpzbB(i)1 z@LlcuWmy>47}M}u`z*B<FNfapTcNZsrO;c$gk2zv@lM&vdk&Z@=^t#h4wU!c?|b&7 zzr!1Wp7OU(#^gh{iAP`;=<k!(2%qbrHxfQTI4}<HBOF9MsEhcpRU%d}$1l^>H|1!5 zG7RG{yXRnE2W8dw<uZ(Tsv3Sp>wN4}$~oI-;N2$Ji&elQjoL-<8<1a{z*vSn455d3 zw-~mw3OG~H7hdQZ);cNM4&rb8;a<l%%(W-+{(4rt7k_WH7wgvhlLdzDPZi)h!@1yv zcW@xjjGQ@pGDh(2aNfc2YU%hpSu!2A5Avr!O`d2+`S-AjH24_cQVl)~xLbo&xf+>9 zcnNeTCT$RTZ^8ZiLBQU6dz`bc3*4Km0<2XyM?Y)sxeT(MQDF97M&G#5ge^xs&60+0 zH#zT>!%kJwR^8eLk;1OwxfyYdv|po9rW(ex0uG$)6LIjQ>xQXU^y3+E9_=CR!~o!7 zgaSMtLQMVfOFa(y@%~(Zb2skJ%YFn}+Gpb&N`EY!2Kll59CIGnKl%w?zx|%0vW05? zW}W=4X|8K&?+C4H2pdLAXE<E9HWaDrj5I`$2Y8JWUacnx3giE+X)c>zheDv(7-<#d zNveai#`D@*2>*ZaTi4Lq+TLic3$1JKc*b1Q(9#;>R*~`8qI(|iXn5LeYKSx}^mkv| zZFaVNE@WQY)O~F_KhoS0YG^XU?X4}1&n&zaPaTk3OXL}#kw(Lsy3Ve3cM71q<gUjc zhMSr?o_c&~b@lS<h33OR4VjCYnmR(AohIu*A>hgEYSMP(iu`Lk7n%}BvW=b!x3sO* z*f*B6uUps9*0d0Rh}F1>jI~9~Mx-&(YzlQYcC>^eE$wZ$baghY4MA5!t>|sTxVAHU z>Qwy4XH~AVeO<@|^AN$>wuV*|U){CVY-wB5j{iWry%GHiNH0V5b?r@Ets%1kEfm<y zC-5P7%?%w*Pd9XgOmNk{W{q70G>nE&Yx~-|$DV3v?Fv1P!enpi)YUDK$NY~kWJTeY zMzgUkLZ<EX`ABbzFu{h4A79uRYU^z8FxNJ;w2kAH*yUxSja&No!ZjTYXmN9>Wo>iB zT-VhaX$iN6RGkYRUl?k8s;X;U!#JH=A72Qao|tyq;|trvV%T)0`7L{VVM8Ouo=%tj zWUfXVpEf(2+q+tu0GOSj2%<F@hGyq8osrNwh@%A!y2&)3Zt8ffz3p)mtr3rF)<7tD zszWLTM-c(9t)ryLREPu~Q+Wh*<eSXa$htHto+T!pbTrU}u)}6!ONY6-3mv40BOy&2 z&yF%{AxedbXNid?2VSVHVRdWhmZp|Y#%5>NYO}Gqq0MY<SqJL?P(0{`>d;QMh3#!` zLs+xM))l~zhXMW#@MEB^ba~=-c7?<39g)%}@!YTmd%3IEGBTcwG>e$6Bwpm{c7tOa z!^3E7Z*A{b-Oy3uUlZ=s;Nk@~T!gfH+n}N?Far(HAG57%U6HvmL_KN^n{&*<Yddeq zcHm5c06MS-=zVZ;^UXI?#~yv8*m&&TmBGi&hk_59G{jw<W~ig1y`u;U(ik$IY-xPb zd@9@p<i?iHy2jQg>)N{_v?ZFY;6PznF&=4gT3~bp{fqF{m`}BIT#UH<o_mbtpTX=H z>1c0Ti!TL-8Yn^|8@!n-1zTj-$X-%YUA52@&kxPNx%g&3%2eEMKD4xY<-N;4V=e^F z)N5}l_IH{vHIz$0Se#;ivHvE2$xX$jhOxFG6uNay13qzN7!@5YPlY<nhe92l7&;5J zvf0K;dsyEST&blu-EwV{EpCIXRfjs;Te~>ybR64|SA-&=#)#R92ATG-r=3sZrR}}M z(@_kW*3uU4iiqg}4MTlFGkEWkx|KDHs%y+8?Okn=3GGEErE!*irb1!d8@y+-VuniB zP?5IyLvZc%3Ap5EIV68i)$)f`Wss@hVadJKOCDTQwfMn%?wP>jO(kLiaN?L1OM^9) znrzU+)X2pTu6#t1UbNIi%WF76sU#!&fu#?aiz+HG=LwytsD8+-Ub@WWZz0poJJWqC zr$L)PGUgx05&ST1z9TJozaXY)0T04-q}fS@#W!eWDaZSlO-K{WFJ82Asm9yG;7}%| z`K_vX0PPm+U6cm)(rKTmE~!w6ia(LIWckviXxxM}N885n=3k6gJV_lT<7vwtU<>S@ zsw4Y><rNQBEnUfOK%3a*#*(U_h^ro~5pm_ZmJU8}I4@g=fq-8{aEXYQEna9;t(4D; z?)?lC$s^<HwW}Kx9-moWrgt+AE?-$=F0%^>883Qxu^$=gdA@qCymuuzSyr`tv8_rA zjfYWhWtGiu^|Hl)3}cbx>5*lN9(Z8ULSu=Hvln$m+Rdfi;r7n1j*zWz6)kI9BJf+5 zVeV(y>d=}{N2m>klQTBTc69)ZNC@^z(0I6+?%Cpo)&^h-Le-MOGW7sji&dI>Kw9>a zB@dW2oW<<=t3yqOiFDY!vQB5fh*-X64GcbL!M_2Tu?$lVrZXEK1LCGzyD$D9<+2x7 zEnyAITH9Bnc{Uj|(0-tF)ib55o{P2T67ihPjsqP;<^%0bqSN{OFjRx_V#E)_j5ff8 zvcO{P8R-?&2&9P^a|tGzh2}HuT^;sB2m{-Ji3c7ie8x^Q(%vqt?VM~QTVOV}ho7li z)6u@JuB#K6VqO!|l7Z~Hj!<i;p%d-^*9>TLdd;9R*1#|7<jJnnH*RTbY)8MsxUXwi z3kMPNG5m6~P*kuGkC=@=yiDV|rb$aooGS&#o#6(kQbS{-oK)M|BW5_%0k0(zYMP`< z!}g1Bx+~oLOlKV(;yY>eOzAJ*bQdRIE!}S0t#@IrG;cBsn?g_BY_`EcMH`rKZ}kdu z9@ZFBr{25VTuoV#<U%ee!lH>njty`MC?on36WbsbK<HX@Poy~{$XzTZv6g9H6QM6v zXM6k;eT{HSH~kLQ<)9BHJ3?z)paImMHn~V4FTfRk7Gk<z;0-!G6+I2t7yc#HhI27Q zc>m&OA|Wv+H3?tf7FKg{J!H&WgC(5Vh?N;euf3ilZT@PO+3}fs#kROnc^~c$AgLd* ziMZ%~1jMz7%MkmkVEYiq5C;(tBd$g4g%3oh6V6^k=bho!h6voSbqmdVD$B|i+-hJo z2&W`;XRxCk>#h(K_ZdT5aovgO$+TS>qoFI(+}?5LvPH`uSqz$?aHy@R^Uiglrj`aF zWoVQE*GDMuoh3K>Z!V*f)OEGBwqtRKM`Y3`>NFQsKk(G8reVC58=GzGS6yoZ2H_`N zSAXES?YbxJMR8qYLt}G@&h97pz5dwGX4ch73ZI~yLj7IO-rue3Yz>8kW~kJUAOE)d z-!HAJYX~*0ZmDZ&YIzE>`1pl^*|hwf|E#N<Xp=q(0nfkx`~~{o_G;#nl(cbce*e~5 zS%0KmSj108;}?%zy8}b5RZJkCtf;__z4C=iIz#L0+M$YnLUH5zXTNy_TFvdF_NPL1 zPd7Xns$0|5CKkOPhhFghZy&_|6L*{%n_I#ypRD%`<J%vcdYtl?%gB#Y<pi8f1=0Vb z^r!1jP@uq@)32cX#Ey%wY7@x+QQ-ONFVB;*qcwvbMPNQY{;&0mzu1WW@BCB8PvFfr zZ?o+WcXTlQ(sGBymd(dvV#}Z3xQy~=2g2YBf97Kqlt?pH{xh~})}!KvPulf@!j+$2 z`8?L~EM8|%0(IDJX@ghu@wj;O+8-w&zs7ZcqWxK&`HxRQf8oz{!gzB3>*LFg9J;?y z_}jWV?)6~ov_#f-g}Op@%^zPF^Nvq>e}evgyk@7d?p@aXu-5<Zu0B~eT#?(7Sl80o z_{lZLX5q7YzYP10ea+8>I>d%znzN7h@buX7AFc~Ev_)Fhg^KO1nU7acV%-}{TrbA1 z@RmMNQGwjQe&lYwer)v7^ZnR_s!tyLNk<6X-WjR0)i~5t*V2JMJMr;;1&vp_RsYj` zeY{fRSf4L=D`NNmnvQiGz;dT@9OI*(PVIZM{z-J7?L5>8=klXVOw9f5Yd^eWU1zAV zvkueW6D@1jw0trT<nG?0pQw>nM<w`#F3|b0*p2A2wnjM8e~J<4A3b!rv^#&2{eI#H z|L|QgX?BIv9^ga?eKhpf-&&c3{Ryw@q7C9G{Ahe<?gQQb&mW}yc4mDn_{IO46JdE# z`JZ6_Zz!<-uFiHFy8aXsylv(8K9KDfQ_v@E|F?2J=Xr9Cz32O}8tg!7+_B~_p#F{F zPcmt1H2&@LuXKewLfAqMaRhJ<&~pFy<NE)2@FsiwviaB({)FTA$Y;N@6!Q<ZEyeNQ zAFt4X@%ZnzZMK)>pPYA+n){ot24KHB){P%QI%@c6@Ta##rggTg!+8xYZ=}8TqtP$Q z4Tl!IV*4Lr-{GSCKbCOiJ3qKj%zsVTV)}%>6KUuCeBU~4{_Se}gj9}y{gVHn`hJo* zLvPas06e?y))W65Jc|YYe*-@L+p(~03HI&^R~Hxi=ilzX)qm>^=7O6S@Wkc+CmD-w zgviBu-f)?C%(&Ia%*=94b<OnVx-N5F;mLDd>6-2SlzXnYcL9t^e;#9Ew#UG&Iql~$ zyc%Q}9wXBMt6N@nGF~Tl<mWix=??f(2Ry?8&vd}JDyscF#$_5r{_wRK?dLJ_G>G|E zI^fw8B;YmvogdQGer|);KaQuxgb!Q;j%zUUPp8FZ=bzPJQ9dn3JO8u>GoSAZ**`nK zLW7yVH!Vh+ABAlg(+%G^fZnqCKkUG-AQADi=~rnm9}CjmV&@lWF!OWMmDu_D8qEC4 zbhqI{=As_^KgCatmVZ662oEB5;~&e%wS3C=qy}?uop3&6s_@UH)xhS*%MDBMv+31n zFzKz*VAdDYVCL`DVCEmyVCIi%F!N8Q)y}RzjLXpW&#u2<?l{cygBr~8qZ-WoV;ao- z{CW6K{A~IK8qEAw4QBbU1~dPt1`GZ*nECbB;y>}T>9=Yy^UdpIHYCpSMH<ZfVGU;f zAq`$G;eCizf7P?o#m}bKq`~w>2=iW;!at(rlm1Z+X8k)qjsL{YrngsvnLl>3%$EG0 z(O~9pE}ob_sKLxXTskp-RD+p6xL{)bZVhJs06sit|7`wtYcTT*Zl9R%*I?!!q0)<= zUH+H`Gr#r@nJwE_uffb8)L_bQrv@|ss0K5CRD+rC<4YytXV;&r!OTCX!7M+b!OS1K zQxwL3cKI_J%=|<6V+Qum&Of5T%&!T^Y}GyuW`6&oiTQ&X%=~>76Y~#hF!Rr8F!?{P z!OSmRI<b721~b1|gIT^+gPDI`gPCvK!~giR?Zc=BGe7Qt1*-VZE9~Pqe5rtUuTUwr z{LX4H>-Vjkm~Uz@^Y>{m>p!T$%#S=Yv3$P<Gr#H4iTPm-X1@8@#QZ`HW`4K0jYS-r z|2_?7{t*o(e@8W#`QFdsKk>86XK66=vv>(g{OtT(4QBpM4JQ5F8qEBv^d_4uzg`f- ze|G;Vh$m*7Brpvzzg9einA0z(P{Ml==WFmAcrHSq=fix~N84xrrW<dmN5q^zf8c=0 z@9FgRsoVIOgn2fn?5EkO3fcS@Xz+W;B3vNx{~d89U{2{Q&v%h)0k4uU`5V^Cv;G4b zd|txM?(zEbo<gGd+4bjZ@HF^NgiYite#^9c(l6KGD}hh=kcNLo%P0Oh4ZaEZgews% z`lacGo6S!^gYN<!;TnzpfR<1CgBn}~e8O=JzbU=1Vbe#J{AC)C0iVCk2yXb#lxLb8 zVA79h<(Yp>gPDIqgPCtU%m4Uu)|X{GDeDV}{>T#b#bp|AQj^~JFWY!V=7o_+YNX$k zMzG=XG@N5R4}8MZ7wYdez*Trw`ut_Us{pee=D!A*`mM&p2w=9KY0UotVE*X2yNnse zKLh47T`s~O0Os_r@;zwRV!-5+`9dCewtusXS;*&)`t34i8FK*h*{*Mvz~_61_HVkQ z{1rxtEbj$^3$-o+oF%adKj45Lalj!5ydJRnDSx<J>p$|}ufdetpawI4RD+p+T!Wc^ z)&a+nX8&yaqWGs2dnV!MoL2sYN%Hsp4@J*u|7I9N4t(+xROslRJ;*0~IRg7@81NcA z-y~t;kN;*GBa&VK3ga?nI{N1_;~$Z~AM>k;LNlSUKLt$xtsF7o-^lW$Nge%z1J3op zu0pwLW%+9WbAG3b$MQD-RzH@%9WecG>NxY41CB!{a}fwX0+{n}k%ZR*roXutG4qEI z^H+fU8Cb8rDq*IP{x=-(w;k~J0oMn>pQQi3BmdWcIX{+z7VGm;apjNnrvv8vzZ1{Q z&v)d{2TcEdK<3{e^TPtpHtuuaKk9%R0CW8_D9b<L$PWYN`X(sz|EDAWCBR${*P@@u z-wr%;{Tt1&;V%I`s`bxnfYp!f`(F<DhyxyVz`u}iK-8CI;ANWhkM#Z%FxT(rq`b4i zhx#!;A27#f1)j<8rycpX0j58@Q<lHik^d;*6DaGI`5{OCQ-HZ1rH?@R&l84!)hFTY zfVo~9k?<bC>PP;D0n;BYfL^ft+m8I>fN2l%5N5z0{44R%KLNnR|21H)C+j6VH4_i= zNBWloroR-NW#i9r<lhR|1Rm=k{QzLvE2feDa=`S*mHg@fbA2=@`onE(0!)8WjmJL+ z%=N=@S^hP^^cO27{1)IU@+0A&03HSZyQO?j0_J{2nS_50SpC?ZDbO|bBRm~2{o!Mh zpQ{0Lza)-4@?Ye@za8)h>?68N<ny~P+%Jg9`aTP|5P3=-{4S09vAzxm90kn%o6X2$ zeSZd+{%gL3cR29B=77Hm*stNg&HQ`D`Tq%Eu4j)*dha>P^E)l-NB(lixcm{G1(@@f zvY+{m{1U+QSL&tw?sVke1DNZra?ld`;K*ME_?RZo^)la-_|F06e5B;@5@50Zmh%3F z#0R>tuWtip*+U4d?-*dNm&+uKKm2NN{g5Ne{|+$Ma{-y}hCi%+Z2t=2alMucAA<Cz zBA@GLrO!72=6Yw9Z2#TP@_@OX-Va(V&+q%FAL%~_nCof3<mW4Zx&9iH<N1&S{~rN! zf2$H@N$-Rs|0H1gm(4Q&w}8tazXA#8z@gy&LcfHs0L=ZC<FY;zF!xugBz!+$?hl@k z{M7(fKk~mC@JX%zo_6F90QSO}8<6t*vLpZN4)}Ek{3hU4ps(6{9IzMlGSJ@eWBPtP zqZ<YMOGo+NI^Zd3U(nW<D*)3U3ZOjY`DsUfF<|c3?3L|b<;Y*-fV%*5|3&E=FO4=f zwBFok6f_tGP2%pT4dXNickI@!Yi~m)0Uj6Qb)B1W?isoH)^yU^2E4FlC*Ef8Ef>B@ zxCYmG>iC`!&*<&UVl8uGPKi+`?w{4w-CSH;w%~RREGfoi&GFol;#-R+fVV9We2CLH z$!2RyTUR%pp8~_{d9sT4813h_P`7&QjI@Wv-Bw)V!PTjbu5d&U688bby}I-zW|8zX z-vhkpV)J;y#3J^4l$4pg=E=K4<H!@CP&e{y`SMC%r`A3QW1?(I_0|{PUVQ5~(KU8a zREP^5xbwQ8gmNS(@47B1DU%7>Mb`x-x5-5Nn(KlRjU>-V$19Mc>BMVRcwZ*e!M?hk zo%3Yq89d)!OiJpRRjFt4A)ib925t@4bw1q^X>6`*T(cJagu6F934W@jDb!wvT)P`@ z2IqJZEx-k>I(hHbPN-A&Z5IHpBP1@^+Pro?-4HgYtE+LvLEJIpMP>A}&__NS>BHB_ zPjPWKLA_hcezE)Bd0>p3FmC=esm7ED%D5JAPfIH=<B5Ep@AIy-;77dD7iw&3#Ml^T zrmi6(;HDPdgJ*|@(5Of=-VwtynvSx(YG)sHPdqlCcnB|Q6ax?>@m?GR(2mh4DC)=k z<5v&XH3{a%?-GE7_U7<7qIO3iJ;IGfu+)YtFp^E@jR<+e0w?@6?VssdXV^D3*fFRD zuOsu~iQ^UsZBcvMnwGWFDya??+Cuq4uHzR^CR|}r_hB6OYQ!Zy$)NMf4%@zH%|oG% zNDC~Uaq*2H)F^xRUfzP&uN(<kOM@t0128VS(6sD<hVcAbYue`*8y8)cl9wMv8CoDQ z{;4btxKjpov4tF7ZCrFsi#@bjnPR(UyPF(W!JMPYeqoWKXI-l=*4zmf(xmNdZhso( zCb{S)2J7OkHO1O+zL#$Z2&>74NOl~GPrJ{4q|)mOkN1RyRZ-(s+-sF1)}hJcN-1T9 z=F|y!;nmW*)z9!gjd;^m8X2iJ>Ya$XCymLj{>kfvpatosNA0pu<bn3iNU%NpP^j_# z2?Y%$0%9-1%N%$O;NGTg(UHPZikGz&(tO%2d0%qk%}Z2)SGZQP)7cQIQmBfr7YH$k z>z%51#C7L1rkHvOK~JTnu~mXCXzYTlVFFvg)#SHTF;-AaDQ*W9oY(27_F{_qkUP49 zPcf~gF99=2+y<7z(7slzT2B$(!`HQ!K+}aq##{S!d~1JPilRa`;v%c98%td-=}R|_ z&F$@-q2+C%C3qFNE!3*{8JZI!ghshYqt_H_#qIS5(Q4krPTMuk6lf2eAEm6qf`WDv z<{=^Mai8JhYv32tkxU4^7o;dQdG}nlSn0cJt3&6tx>wU&NQY&DQh>62X$hU$N-P-Y z@jLeHA-tX=Cm7p0Jj5w?u`qHC;d|Q*@uIRAOZZd(E;pmhM~q+b&b>azaEQT>(q#}s zNWL48)&jIOtpy+Y`T_ZbgV_mE>zd%o+0&nJub`fMWy101#UxExjyGzQ`<B))zYvFf z<>R8aN0cbl+XN1(LObOvFYK}ppUQQs2Dit4O9y6LT(Y$<+;(cZrW|3h|B?TnSm(fx zcjNOUXRuyl%zcymPq~Z$<J(=vFcud1Q(VST#>Fn<IAZtHF7Y=hiGPwX78?Pqn+dlf z&c|0Ak1)n2&pF0<F7fTt{QtsQ6u9~Kx{Oj8k1}2YI*gxk8D6Z<81wtEj4K&~&jH4u z%k>@U`ml~6-6F=I+s8QQGIlb?p~-&6zrnhf@hq3ogmp+h{*e4;#%K@MUyOIkIL7z_ z)`E=D?l@!Ae@4RRC7gr33Fa3thCC`|yh_HcGVYdflrierEaO3$zFWe35mRpbE|9y~ zWgK7(Ssaw{AsLUzn0Hx-A4N<#o?%=7ey}EG`XFM$XJlN3g9+j_$vDawo2mO`e46o{ zIEldGl`-$SkWLL@$a^Pa$omLm$onK?$UA2S;ycg}j6={D#z^N~7?!VMjP{H$9de4x z^fAV0-;tSi`f(ZW$9@{|4$AnjjE~7UF5@#Y<{cQ;bDlBiaRZ96iJ1N9XAHfmVhp;x z6XS+1)-ncOj4{gdt_$Na#Kb!*WA9})oGar38T(~iCgXsND`gy%ajlH&W!x;|u#CH9 z9F_5ajAJq$mhp&;M`awBG4J589j9e{M#g7ld``yaWy}Kz;(KMBCF2|!`(&Ie<2)JX z%h;50fs6}fTqI+^j7w!)CgXA$2V`6!<4PG<$v7zE8X4Ehc$JLnW!xm=W*N82I1hU& z`8fOwGS0yGU|i!e_R9E(%s<Kaau~flJI-f}a^(_UCE;!f@0RhfOg}2&(-O|PQqo}z zI%N{Bm2kI&H%oZ0gbzy?e^gBHb4J2Bvu(JDG3ZrFxK_du2@gtmSi&O`J|W@r63)BI zrdP-q^eQCWB;h^@4@!7g!lM#CEn#22<cl%+l5n$xH%oY*gpWvgOv1+1c6pOA%9l&H zM#fEy>(Or#jxo-}{KFXdqcZ)ZjPpK)bo67TjJstVlkpK5pO<mLH4>lk@399e;|OEW zAC&of8Q+HaL#7{L48BGse4a7tEi&zRm5lpkd`QNpWt>09#;cO?vohW<;}bIW&IKOq zPo9i<hmPa5P{u_v_W$2T?k_g7vJT_;X=$WL!9h!CLcvKWFhUuM7OYs!0EHc)K*a(B zDemkt3oSdaWtr8YRja8<FPb>UUi4z318%e?O>9gxjp;=%YSN2d^kOd>)5Mxo?M2n9 zjn<_8d7krr4-R*pWcr!+&-uOQeb1RQ=S<%j?8QE-^H)FV91dU}2XP38v4A63#1f8T z8OO1L6F7-eIE^z{#mmzDT(YUAXcaebOS<1jP7mmM;5K=U-j}TEdv2ino3^Sq;QSk# zqN2^{`h)VC(-*ZL$=@VDb-VJ_ej2;69|y63o-63~N>=TS;)KhanxfV_LcDhL+(Fmx zvfh7KqkI89htTzwDPO^Dm+O5veP=L-1>3BCO0PFb{sQ@{q&;`g<@Jo}dveEJAx@`N zzt^nt5ACCR|Gqoqr?CffID|zU$0?je&q;K<HLHHtaoy$G4?ErRCB1I4p}l_0V*yK8 z!D*bsIxgZ0uHzQ&pyxt*yY{WN>i|>thV5#(FKkZ=r?FN4Q}=kaV;Z}$4+n4vM{pD? zIE9{j>Ft@d+MX)5_o_XO&wy3CLs-OdoWd&Ba1mG0b2#13hE+S8*nhv`Ykv%32`6yI zs(sJ#^!oEw>#tHi@jxh_LC^Jcy*aCT^SJm))l+|F`$GL1F5n8T;}zV;V{G|USU-iG z=sBcrH)GXqH;z0Q>d#^g7jPNZ&~r^4XVWUq7Pfsl#ObhlJ?3%H>UHQjs9tZxYCX?6 zjpLx_kUG66J)WL3>h!8r{pHVu{59Of9rPSh*Wb6Qe}L7`hV?GvGI~y_>#teWU&oGI zsNaP>n8QIFmR`SLwf+d!U9L%7i&o<hJrr!Q8i$P4<d1&Rd8_)vR`n-v+G-qTrQ4}m zwNrao`8pq!9|?90gnAk5!#ozSgcY2^D%Np9y1gZ<_LgzW<@alRt=d0!zUpNj4efgl ztm_v^d(NxVp4;kr>Bm&>VpBA3^**&~)xQn&99P%dwpwooE2mUX_f=a~_f=6|>b|OM zZ`JwJeoXggpObIuzQn%L6pcPEPwD;U30YSA_Cvalwx@OfWv|z9YR6S?Q0hK4V^uG2 zRj)+;w$*m@J}I>wC9Cb&wu;~Nl+^YVt+r#_>etvOtnO!5$&a26<(>8~nzw+1SjM`| z>2*MQc1UTpvt<9J`$62c+U|Wk#<tIg{DRebWvlU?z!{vwMH%mRtNYLmtIsWVt@g(O z9%A7c#nXMmCLUtT7eYIpQ|x#h_G;x>#VNX6>(#8b$8(G0cCG3yTh$vH4)wP27+aqW z`R!K6QSP}AX9!2obCMl*(kkARRs3nvGdTFX)_+LnC3~CtYd@jmpddB=gZ4S?Z`-Qz zvwzZ*O8ZfLPGL(r?_2d}&t9kNgcsxsI_|9UGxi_qzkRAHS|@)CcklqC7gbMjQ&#Jz zvD+$6zr9PxslBB05aph0?S7A1^}CEGF4ybUbFE!|B;B9th*bP_8|igz74O8}qSwVs zp}ZZ_*p0nb+mRzZU_14GNxF#R=(*hSezD#!=sDcZ_grneCB0pqo9%SUy1w+d&RXpk z&&_uEKv8M+Zx{1tLb_U#ic`mB`=ZYKxQEBsa!%zs&$VO5-luW4T2KG)i=D?++{I%| zy%OqWFoy;7uQfT|3@+g|9%Aa%P_GMzu!8frio4h{O8Yp7<2Z*axP#Fc?O`6vSjA=B z#uH4x7S<oYQJlqjT*gh@!$WL4&-UX07SX@N<?)-xZR{wA`~sG63TwE6SMU%|u<P{@ zCy!;E#u_f;Chl4tZ-*GY5z;A4V-MzV2#Yw5Q&`11F5wz(;VvFxbb<CUjXjt{e}}=Z zqhZ^s&;4)&i&(-@EaNy<Z~`ZB3a4=fXR(TNIFB`~<7HgHMO?yVT)|ab!*$%iP29pO zxQ#owi+i|_2Y84_c#J0)jfZh<!B%X;6t-grc48X4FoWILgT2^?{g}f6%;O*q;V>3( z1dCY0Q7ohW{~jMV6`a6HoWg0G!C9>09L{46>v$O#a1obq8CP%>*Ki#-a1*!i3U1>L z?&2Qq;{hJx5gy|SMsKqJu@&1eg`LvpwO$;=5>DbAF5)`w;1RZ64Dq_KABVAw(^$i0 z+{8WfcZHg-*Bn9V|C3a)W=C{AXP?(~s&u_A%J(r-QTbo>K5litGh<&?9DAhin%SFl zy=+f(A7FJob&TzoLb}iXJ&N*H+c9C&x*oM>o1!cB8C~aC-FHP_lK1L*RC>F5oPJH8 zKRbQ3zQf|QuA}Gem_BE+x{lu@|BBUleGmPeBA+LZu<gsCyvOSQW(E6aeg1_Nd#HZn zEY|IR^mzep<AGIsofA^={GB9kcb`?e{W$J&ZTA#T+nY6>E?525x0QZY*L_y;`muoi zE|U8{Y8AJP{_Pc~=cLDX!Ro$f(LS#IV|Bf?X|+H79VEB6ZM9zX73FKalvR0}bPwqP z(go7vR@d_j_73eoZ2PLxPiq{o5A#;_C+%Z8j_ilE-$<{K-m&WUG5Whu@wixRXUhIa z{|>W1)W13GzqO9NN8@I*y1%okpRqmqT#j^)y;l3jY8?B>FU!s+wO{O8x?ZKcYBf#^ z&VNATXkXR!w>_ilUdpdny&vy8|8*V5<X66?^b?AU9_m|~!(3F`NjihQn8QIF#v+bl zTE_RKR^#S+R)<sEe{Dw8+@|B0^t4rfI;4*ew`=<_Z?D(=fYp6=0gLE%J0DbktlGJ3 zbsv3fbsyiSmu~07y8gxj>J~N5SIDSyMfYPkWxuHLwu)D`?HX6oyVCn{5BKrVs$WN> zkFECS329C3jqitBt@_($6{j83n89wVdOf6jvCpa<fB(qqce$T>{m0`ab585?f_U83 z*%7Dz7QSQWcpfjWSGJC0zaQ3XemBf3Z+<6=^3K1V{iea3clzg=hircq=94%7G|cmF zzM%7(^EKG}_D*%$Y8zYZRbhU#(`qtKrzmeH-9g&NpX;YdyMIn+NOzO&A>B*b{dfGh zKdPT2JwSQfAC(W1j<>6o?b3dV+fhH`_&QkP_>19t9?d@q-#=*nXPDRDe1py>-mh2b zPxh_1U$2}wEA>-Hv7^Z|{Rr{7?5l5F%AUP6RxaH$R*JHk=b5c|nsWT?m9Yu^z}9=2 zS^cK$*!gohg~nN)l+sYy^N1Ug7cayUtg=D3eqXjXUh(wla}%evDZ174EL+b#(xjUA zCeg;RSyx-*?bAG*^B43B+u6oxsoAso;oGcdi0k(+qio!nQ%^m6k0vm_d_KzR$8NJ{ zDw;=g_LAluX;lBe<z`jWa7Wq|@#6jGu}>E77cU>z!$;8voX}Fx<3#7IWJ&5}m2r(8 zISMv@rDOHhC~`Y)!}YYA<Kv<+-tgDMYd}TulEm|I)EKY07mfkPbDbpKDLrqDx2AYA z%1f3c-XqFrjJKqCZo~21w<O++dfpf>{|)si86@h7=s7(a<Lx`1R&+e~Gl@5*=Z*1Z zzNzmyDKA-E&x<~8cwfBq@55L+-Usza;!Wte<0YGPtat}XCrc8qqKwAvD=MD%o#VCX zk;I$QbI0?3_Okb_DEi%X;kp01p3A?7NxNIsus@U?FYdFK@95Fk?uy#2E6?qINROml zo$B7#kMws#8_JHCq#r+4s<FSzs^{;BCQDN97u3@!Cti+z5Wd?&GH%z;b;^9-_7(o{ zzvJK|DoeI+P0!tK5^t)m*M~D$l6F^>ZtQPW@lwije{a+yiT7(g_ZTJdF257nRaU$t z@qVL}oAG(ii|hS1JdOXl%#VGHGxg`&?<UWJuH)rc54HK;A?JE`$0gxUQqLy))+I}- wSG`H^S$h6QJ-mJHm;0LZK~JOHFZFu6*3ZI{#JfSs#(H&)OKVc7vgGN10bHW;N&o-= literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/jpeg.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/jpeg.ko new file mode 100644 index 0000000000000000000000000000000000000000..e432fc7decc709903156aafdc597d1189459ad3d GIT binary patch literal 68852 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process.ko new file mode 100644 index 0000000000000000000000000000000000000000..c69df249af0417b5ab9b12c9d45f97b82ddb7c93 GIT binary patch literal 83672 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process_no_sc.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/media_process_no_sc.ko new file mode 100644 index 0000000000000000000000000000000000000000..b24453ad8fe433590740fb9b54faad8ac8b9f466 GIT binary patch literal 82208 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/rtvbus.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/rtvbus.ko new file mode 100644 index 0000000000000000000000000000000000000000..8446772e4c63b1dcb7a038b827c0193096d4d275 GIT binary patch literal 45172 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%0AwxixHk015E@ad!8ik(NrxQBnm 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/vbus_ac.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/vbus_ac.ko new file mode 100644 index 0000000000000000000000000000000000000000..72a68a6ab3e475da73f769b755a1f34cb253104e GIT binary patch literal 8460 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 E0e6YwasU7T literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/vmm.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/vmm.ko new file mode 100644 index 0000000000000000000000000000000000000000..3f4d515dd2201c1436c5bf90cccb05017c663f74 GIT binary patch literal 15908 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/kmod/vpu.ko b/general/package/fullhan-osdrv-fh8852v100/files/kmod/vpu.ko new file mode 100644 index 0000000000000000000000000000000000000000..66c48ddfe5cb1833fb2c8746c2b762a79f732747 GIT binary patch literal 116416 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¬5eGK5WUo{fM$;(6S~Ydzt0&1;{Owie&o|>0c8W7X*87Y<boaEiP<~6M?z^C zY{0AS9o~*mn)dvIepoYihnEY*Hxj=u6klJp!{@t|o6)6G`Ql8g91q5K5Z9R2*iKP4 zJg$$~M~X=U@71~N`|+HypDCUsRNFoSUo?d3qYmZ~>@*JjP~b^0CtEr9y>oa^ZaH0F z*n)k3%jrppEvMDb;^mn2z)Q!O+k-Y;H>s-xFZ=t$^`xtwfL@ZZ1s*GESxb4EdFJsn z@pSR5<yp@&#IuWsGdC7z_^nesaWsNvo_3yYo*d6!o})ak@Vv@Xi-Oj|vzX^Tp7lK3 zfn)9B*~jDX)K{TN@hs-a@(l4j#`6l#t2{OePdiT!&mNxrJkn<ZePd~)+@^Ns(spRq zZsMsWyS)@?>Vu?7Ya`x9+&1wfarH;S#4Yx4#9Q%2Bc6>sna>!}9IZZi#jMNfiPsZ9 zY2tC>apFf!JPhMqz?h3JH)ikl#-RNpCXYkhA-==JwO@UL_(l^yM*JA@`%L@@@gv07 zn0SGBf%qyD-%nh3$t^YUeJ0#%Lg_er$g_t$%_i*#ytae19i$~p8f)m6PeI=^JPkFL zHIqj?(n6Tx>Ec<-ljYgLbCTyAPc1^Pg{O_Dizm->gy$sBS)Ow|O(<rqJlu<B_3#Yw z?BzMibBu@k*{riXHp<>!U>@P=rra=(`n$*M!PTP&)Z<&B@u&L$htrY+x0RM72h?{> zHhN6sh&L18ji}x0MC=<~D{-eA#a1et*2n3O#dG;?AyYl_V4INr(6aAx>+PsB3H^Hs zc{nfY#VH%NpD(c%o!(GTyp#Ar)(xvm=!DZGdz#7Djef{|Y@3>}jV`9{IC&#Ba82FV zJ)PgB%uGAy-B-wu%px!6OUNfbBK*kg{0Kv8XA@<K7bA9lR*P&c<cFFis}UX2KJJ}B zm*jk!ce1%(cNBPIgxtU4y+X*j9nT>Y+*5?w|2#v;-BjLLLe8go=Lm)GtNM<exCg#C z0$xW7`8nvt{`xaWe-0g4J}!Hb@QvY}J%&##Yr79ux=a=N>EcFoP1X=$daKQnee2+_ zb*7xww+=9GxglRl12fIHbO@$!4q&zcbLM4WwouLv!TbR*#iwkl`u7f|;h`>`VV<=- z-8^9)YL%@d?ekD+yCWI9&8sbN$0YnC|NW)#N9{e*Nte@y`DraxBj~RkUNh+_*2z^F zY>vr%N&AEIEcOd+%3!l<ci2BHuy=_4Z85f;7M^DE*r^U*?#Auyr?kg<&%8djr_kqS ztv<Ke8F2HgX|Q({<Eh8JT6F3DC4;BqseP;+BRr3Ku_c>NYkkRFtUj3@^pV=Eb_MGe z-TkQbg3mMT14&=Ao_OACDI9`#*t@sIN9FXB4O`ip?e`qQTEbI=+H*KV*hF}ia3<jx zVS?}#!Un=~gf`);=zq<2|0QdiKqj|A-xT!FT+?G@Ym@ykZw+#Cjftm-XNa#d@m2G8 zLr3h#q;;9JB=Jt-ttLK?xa4`WiMJ7NCEj4-t;Ac1$4$J2_)Oww;gzN(<$0o+v;=96 z;UAm0<abbJCh=FHqsj<>jjK5G!Yic3(Y>^ekd4hrUWB2sDBlCg=pYY#Q+k{{j~h4| zcaIU5{<e>Nf)U8)7QXE;-$wbSvcsm_5b+`NzA;5R($WJS^RgyQd*`wl*P3|XL#p|9 z2YkPmXFtzTo?|=?&nr9@3Sa|I3(sO6@lu+wn`a$QmS+dgFwY*I$9W1oM|n>2oZ@*E zFs~4b2Ls!=_UjLC^~Y8*!Z^`hdeq{+1;$l0UDjEx{6p~dfLHzXP28g~;5n^3eLn%| znty<u_f+>zuW4YXS8c5-#_jz4#AkOdnr2zo`(p%H>KD?GjUOp$t%2>JSjG1*U?<SG z8rcI(`XF+3Fe6(TuqZ1SjG=3ygb~W;D5vqy`oaAedl-|GeePszezD|T*sX4KAHIS8 zz3hN{D5-kxc9XOx*0TYd-Q7-`-jf>~)!)ikZ%-o|$QMbq`@RwKS&3LF#sa<s34afR zwf;u0rhx9))9<a&z7)1g!s+dNZ?)i8s~6k!4sT{*#C!H<&lc<H-*_SaEz8+R8uGqz zC-l6nG%0bX)5$n&s1hB9oYm|ZGG+Sk+BIL1&$4<Q!Cei^PISlB7BUSR{ei0v2<BIi zlA_7Ctl>Ky!4?d`thYYp)EDk_COLOHiz%<Qg!V?)^QayEnua|m(V|Up)_zgqqDL$7 zD*T=lUpw57eC%f*x8ECb`n`B|qZ@^Gl8?F*^Dp6B$*MpfRb7fllI^a>z&v<labmz* zOSqnJ7vaq0fVY~*vIoF(!0Y50;t61gcKetQQoyQazSr1jb7pwoP};E4ZZ9@$+gTM! z{HFC+q*)nY!H?oa@sxPt_uvoBRWF%&CCuNNJK~uy!2|Ry{j0WEsWN|8!(Y+id{KTR zUC4d$qSpN9<})71Uq!#S!wXi=AT)xX(j%UH;HvS-i5CXF+TlSjmdzKJQr_qBKh~P9 zykCc0pA+GpTJU4O%Ku2~-NnF)<=Nk%zvD{=9Ib^#!%^m`C~f~JdPY0)O!h0@e=PYZ z8b~kc1V72!WPYL_PZO`R*)yf?3BXi47;{{cv!Ym^81z2Coy1*9_%k)g+&1W~=UGL3 zo->G##h^FTGe|!VdZW^R;1~8_i`T1u@<@(rKZdiwb+Q514-a}1ditH2lu4zK@zzeS zmGpRG)O+fSPZa|{4nHlgbu)DpBqLbse!NiJwXnRO*lA$b0Gs~!mf&@!2fh02AZ_Y% zH9xD3HI74jutPHzjot8DtCNFX8*N<*4C#wCsb0sj?qm%WcWN#CyHZ2`o@JZxN?{|n z?xB2^e!9o0W$eWn8xicm+V6<;+~YiU{``-__WLkjSI*P26Z(D~k$$HcKRfkh#O{B~ z<!p)<@><G^oz@y2H*d-j+%GflqX*B$hh26{eCCjar6~KmqDeD$N!4d1s84yHChrrw z=%3Y+i<`nY1orpEz0A$CxUc!W=t{`(Cf2=HVXHT<$eq@)UMG$%#fq?BxE@&G82OU! zDjqtmJk@L2i~AV5OMaJE*Gc+M`rR69(`l<`t2gOrzk4droZ0iBFApYI8~k*|t9jRY zTE6&)drUo<?bIXL+w0ep#YS9Z4W72r=rU>UZm<SUTPfaCquwMdciM7zcfO3A*nIkj zzN}$Rxt=~;gdG_gG-%vF|1~yx3G-}&jf^7h-<J(7r3Wd#s(_xt_nGFqbXQyQjBm+8 zIczq0Tgan*g(UgQ<3C@v!!y5%4|Z8vFV!a7QcKe;ZCZG*t;YZojW^AEH)%(@FV*Sl zlVx7<eaw*G;r<EqtrYmh(v}-ZMBv|D-e;0Odr|zSy@$9n>P;&=TdFDy6(a|SiqQi{ zOMTA`70(|zT8bSZ?dVWR>yYv6;NiM!E9wq(&TyXkH;^ZBnLPfOK>i4C@w?hv4=uy( z4eDG6O&}%fI&Ab$_qxsKv`rp7sI^owAE`}lWt;8}=I}$n>M!DhQH(6+y_K+yu&uxN z`PM_FU+_*J)HP$n7GJA;E&Cr$bFmG=W0Ik9d*32_ED>dV580&yT(mxl*x(Z24NhtH zRa7^7&c!}cchuA!rS2&8_7O&|BhPz?6ZR2C-c9^^;)H#KkwwJcOPsKeFaple#l#8w z2qO!LzmGU!A7Nwx@%Ixa>?4fKCw@ae`)=qI<KVtjyyc8|dE|g(LOpYY=xP@>`}Bz0 zkNb2GUE<I*k~}mmmdsA!&izKpG)9oS$c(2iM;q;<L=qv|*dtyiwp`%QH@(HqWZxxt zoxxX1zfI7h`I7!0wzaljUP7O#YeN1=hnKvP?5IU9BsA_B<Mj#FCiYhEL952uZdE(m ztSaZr)+A?(6>+v&QD?MfgELw^=!{kkIHQv`JEM_aXEfU9G!5+X-u{_<@#?$t#knik z_bqYP$TaS5p2K+p{NH~EAMwwo<p;m2G^ut&G14?xjJ6CEwYR4|^H>`HhYURHXsrFY zr?~)~s<b+qYizoivBw-(=AABht8B}SJKuqKv*f#@l$pA@QG7cIeYKqLjuJXtop>>B zecRAJUFx2lZEUI%e=jrn*dxKm>uGcpg_0{4&yPNQSHjm-j6bM+zt~$VMN;`9wu()Y zk(Ubztpm`PHBavF5VE_|m0ZW4`DM%5!no^q>+0ECMQ%>8HzPwy<GnWYUK4t+=AAQS ztSC6Mf!vR-ru<O98|i>Pzt2ANEB)@Iwa9;XN&E3u26)Kvn2p@ldr%)~RZ2^fCRuJv zmh&!IZs$(>Wf^0E@0fhcgZJ@%&tY<s@yc2)E}6o6bK;`yOY^jR;U9x+qTT!A*c@$I zKr3W7IK!Gob_3Beush{6R^Z>@_ayj@hC0b1i+QyLUe)+vKB<!redGK4++9iA=}wh> z)#WR0Gxx4d)9(fPHu)WB`lw%Kat0bD(ZS(|n-=ssT?;lhQm#>ZXwv;<ch~rmtw#N= zFz9dL7tGNcHP+DCq*D$jU+`gvacm3Y_$lEy;BHS|?R57rr=nB(II_-Jn`htPqXRBF zZE37QbLw~fc`TmX@5z?0c22OePG_{gk+O|(^kvQ_`Z#L8SvV>j56AVQR|dT~3!cNm z^KX4T-vWK|=-}wOB|CNhR4bjIR{eYTPt`v4kj2@!Y2~vG@#JHE{%UM%RX$CbA6R#1 zt&NWGYPR|t1xNe6Rp`y^CytAkKSqo_F)o>(zHzE__=ttxi$31?@!y`Jas9{3^HZYf zd`$CrC%ET62;PYiZ_hi>+2{8<(U!hqb791*dRJdj{tPvY>l&+2vYL=1JlUpR{G&K) z)-dD+de@QWe&(i2_c(*Oq)GHqKSct)5FVyo=xY9+yJ#B5-NzXj6rEA_jkMCTCmP>+ zVC}cccH#Zf560j-C+F=$ciET0*6d)zDCYe7PDOHF-oeH_1%Kr<w(0};6jSERtem&M zJLlC#bKVeTWQRyh&3W~+bKX1OmM=B9)OR&@jINwlbsBreVf>!c_<$bGmkN}7wHf$x zIZwt@%Tr&K^AbD_9_irOMCeeq?Qp+$<SG1b8~VMYS7L)QJbpg@`RH@}JJ0xhF3MoF z&c|;cOj+5iQqISpi+=y!nU{=HwIiRTFS)zdN`2Xj6qdOC@4>h7Dd;o{e>NxO?&bYq z(wdn=HowGqiB-sP_H48k|0(luePN*Z)0YPDh2czzGw3xl$7p;a7V1vT-+Uo1S^dg^ zi*faJ?E>P=aq73k!T!d!c+NXA0lRQRj<%KC9gN}d_-#TaM-ofiNajXY{=st&!eiGA zxHZUun!?di@8`fTpD)TD7lTjhmxA-gvMnS&{3UPjH--O4OQ*^ABJUG+5U=G-F*rp? z*B)DKl65Qo!_8%Thu@z1Ph%4{akZ!6u8VQCC)IZ`zI1DucQw8%VKINzjoo`OFEXL- z%$*nG_+iu~L$Hv)b!}TOe#b|tZq<z!<M_PQrK5~*_#}`gqF2I<+dc4S-1(9hy@qz8 z^UfxmRK)joI{iw&M_WXXE_B;`q;PnYF_$jgc}-tY`>C1}(RHSaN6tTq9(;YiI2nC- z4x!3OFNWpn9*2LMjcx?<)fM1V;gf(rRd(K!^ug0ZewnpT=ZpN_P~HAe8O~i!=kaaR zmE-nd{E#BGS!WKux>00}WK2BqCGRWv3C$wyh82ZUb#1@D1{F>>#0r|b!M#g+4bwMD zM?w}=U(Z^I^}h6^cktatZ;d#>PSF;dF<*Gh)4EUcss6U1#-=CGtJz~H>l^GzP^O&k zdl&L0#>qETbpy9DZ$s5<Vfs3ZU-!2zz-)R=zOoD~Nam>>_`ftQDvuk{QSFFp9GkZI z?Lb#hJ6`Qlo#=h&pFum=Q}@r*#0#{;<g@&CT$+#lhjKg63Bq~fK7N<xec=L3+F@YU zz9!$LviywUPb>YUmzc-=ewasJUrV26>)@B3P=BX>!_nTA^ufHvSwt)DRA1BXe3f?l z^p>5EzRo4sbF{t$o$z(zOh~gOpSQHHD>lu}dRqUe|21A`F2E<q#O(!r7v>uIdyNN! z^Ko@&XI+G$v%=@*Uxb10K;5gv#rJ_+7B2^L)>nAf{+Vn_lCgd7AdVc9jQuL_y;mZu zj%Zw=A2MGSpBj>Xn?DBG?wh_Eywt83^Jz1DAipnPjvnm2FlQ!am*tMuF!RRAFMc_7 z;9`Dsrn*;VmB;FM>mJDn;qw*fJjLK5zs>c`Z&<v&=&UR>7B3naPlZ0LF#_CXE}$;f z8=`qYW7V^Gobtl$?39b;h1<FL7t5ogT%hlGxC#g1dkLON@I+6D&XS%WJXZL;&^%T0 zvm6%<TSD<<<3$?koNZ-!;c12P3(t5cE<EQozLute4We5x)2t;O+0yUOdCc-!GBw~@ zlc9Hl@n$273b!(b%j<N1O^Mw}>r~d2#pwJ))38&4y4IVlF`aFVT8GP)Nc~TX2a`rO z2+Py<Wz?P8h792>eZ%wKXluEzG-gLz`@D8&!C6nQsj*BOJCl#??H*~gGlQV%pQ*<N zkTW)b6{Wr1{f&}Es#`w2@#IAtKtpx;9GC7JIEJp#$T{<Pf%Pc3b>d&7wQXl|$Wxjh zr)_?meo1<=6>Y_*mXPo5%D=e3)UN#SlWY{SPqecx_H9RrZC(U98bvn53tKMakF=RG zjGK#PdcB6L4Q~E?4!s#qoyY>@f2q^%rH&D=0lrxZe19xM6YU?1u1m4C1mimqiTFBI zFvjPpZ^@(ePdp*KRc}AI3J<}(6!-D?xaBf1ep&foUuiLG*)t2l!-khwb1kJE;`=D$ zR=5TB|6_NT&+O^WKlul&W*^c&v$vqxpGzOZH|w$Z$BHMnvR}s;#1ow1v#ayPtrMco zcfF4lA6@sc;+Cm>PCARv^Y7KTU!9F^!2CHGKLC7Br$+Pn$ktdSfqpS%@>dT`L+_Xp zMaN*>5Q)}hixK-Kck)-CE@iN*_k9gnXn)XsC^o^7T%5f1sZ#gwL@zTu!~5ooeZ|Rr zwfM*1UySr@C}o%%e)>|rn9g#>5<hjjcNDw$4DZo(9mT@E_!zJbe*CtN6~F6s6uX@n z9&&fe<R~^j^nr(O%oq2Kehitmxww>X>r&@mjG;$N#t!tyD>oG<yOZ2WPJeOo&IxY3 zmAnf(in*JhBl`&6?eNy{{iR4^qf=kl;B;Ep#GQ%W_ipScb|pBg13uc*UfjdEz1upd zhi75O4<9X2UuwJeSnOlP?=9%~q1vPU2eskRQb#dgy{Ra@#F-#jyS(&RtfM%J46*H; zyE?;uK#F;g`B8lrwuv0;mQ7^j5}U}NWRsr{`C)7)$8)dEx1M~0TbcJn!)x=VQ!~6C z<#)(0*<_(NFy19^Pqxe6;?G4!zetzvA#W#T#>?-FlYc3BS6v4Fsd4gun7r+mfj>4* ze(js2E(8CSaq=&^Ox`o=Ufb4dE|d4{;n(K9ioC53bSVUM3~Yw!(z#Qw&7UmH@TO9x zO!G%C(EO3tz`i)9W!uu)SNFh#<$en?!OAek)Q8kR+4}RbRJy~Rl*$)VJstSD|M8g8 z%Hj9MENo0VhpaQn+V?BJ|HYVveamu&i0|RsU-0Z16AxJ#&O72KBe@vXdDh$I`wO&= z&>qK#WjT#+8*)*$HpOjxOj(a47i?|pTClaMZT8m2)w8!&)km_9)}a>rqLKw#e;&1v zqs&p#laOUa>FL$Tvy;eIoddv6o%tyrlRORXQjqU@SiT1OrfhvjdXSI!3kG)6Ynb=8 z82>2N2EKokW#iZF@6nb0b>`g+pW`3Z4!=u>li!Z~kg$ssbyhB#%Fp-L(wPin1KliB z?MN3%S`Um#Kd-it9|_@KwmVd&M@+i#l3m94(PICliuU?GwtNq0EZfn4v0jqz5of$! zvu?^}G|zA6{D00p(~4hH9KVdNQUBa`6*y?l48qR2%=iBNG0RI?>{YV!#}nJVH0i!w zAHRUuf_|qzik}w0v1)N%OZ_~?oFJQ!^r33I-|b(7PP?$*5e&=fcY-<6=R@P0uDh>v zUxw^4nv?#Hx`azD^Q-#xX?zTFBfGsCYjn&?KjdXO2U%nF`@gqan@}Eew@u+8e=mCo zy+Ck&0G#UUS^rZ`XL33{$)r0<mc!jCoX1Hbr~j0G9owV+`e-Sh&&Oi<{4~kk*2IvT zWsTD}mwOYeGHoQ=tcAN9zot1egS`#;+iGw3ve0FSxiV_s=|t^*_K^qOls)JrZ1k;% z`@L4q>{{4|m3{`F@U!s|@0E7!cTrq84c&uqV99`^dgDv-#k<z$+<b!bMu|aZANMn; z|20lEhYP2nOc^ib7as{frQa|75)ZLA-fPys>C*3$mRcacR`$a)+8-Kp?&9or*4ggm z(M$FfM!X@~5w+#J@G08S>(o<zFM7@6?9DyLT0BKt)rJIZYk~(wW7&ArZ>^NgRl&=5 z4zj<fzV34x64-vM!Llv}y=4DXd6m_^IPeCrYizo5;-Gsa_OQSQ-m)I@cCkLMf`09G z7JVy=4jTN1??aw`gQ$jYX})#wEgkx{mT%Caw3=@jzO4>@>*CuKzOCWgTE49beOt`8 z2xp}4BYhp;*M+_{vv+a@KKk=WlRuQNTY{tfSe4!u${Pi~_DJtyObpNN_eS}4Dq+gd zC-QsJ-2=m#D{ZHAoHdW&Me2G=@W>_~whgTkg40L7gWkTWtP7&%OoDY$uE&9whFAUZ zn9uj8p=Af-{wc;k`${j%UMyL=p8B;m6YRhzR(WK@UrQe4)p;cSK68fnQpzl)OyCb2 z_!z!Go_{2d=8~owupQ^Gjc+X&hf+NH<G16iqc)sbhrbgBz$Vgvm9#pZdfvnHg0JHi z;A3>tKnAyRw+!QTT8%Z*^t9u|YOJBAN$_}Bh6j4K<`dSTn^LsF-)k`U?NBv3?lN?= zd<^vJ>Ugh9<mX5amfY3eb9j!B{0zhI3Hi=y%xjISy5>?>H+yQbp$}(%#CTX)nnPXM zV~ewnOU*?NQAhQ3_HdGYoI%8<>fGga&1HVVJBV|h#reQ!e_|K=L)*OWMOzqu*x;B) zti)P>F3~)O&23Y5R?exW-EpUnb7ia%$**%<g4wqOyKFM%)F!#l&iJKjz6;*f9_&0X z`~GzF?c?-q;8$m9{lYp)ymrr9d);=%W@JjA<Kx5pDtRWqEgvWRQ8mA@-%`v1Bk-XM z{8F`_vl{raNvt;fRtZ04;B%*=*Y!H^Wv2-HsLJ13eD{~|jbr#pdrhn0A?-E&1?ioJ zpMo{d$IN{Q;`{TG-N>o9Wj!r92`gT*?y2RskZa$`^H!cK%3~#NLbVTj?8_ZGlW*gP zgv^f77rFUmKck4<?&=<ZcnVq-@Vm-)xJUWT-)Q34Y4IAmS}d9<)a;#!FYr9pPxbK3 zfp&j9?&W>el<WQXJ$$bNt}g?G?=UhxGSNHETv`Y2@LnlLp1aMRmug4c+QazA9>m;G zhrLVpHD&LVpH>;pD)Pq#3!i9kUnm*`-&8)sZ$ZRZ1I2stvtm8@g*7(kawrqdvzk0g zZwRMn({7R9=7>{g1HT`0*XKK2`C{oVxb>0pIqx98iZ<L=k=8}pI+K>>ePz(5RN9>j zyrBL)GoYivAKCgE{Qr&L6!7t<eKEe@NB*F!+V@X<=S*sew$EZ-Sh%|4`|r>O`2&^+ z*WZh;lU1f$+c@<G-vsyOfNrMVdh&<A@1YH%^~x`D=YfH#aMhBsFSA8Exp3}6JC99= z?@T+P;cMFY5!x}qv||F__mDr_&U-8HzmM;gbPMChZ_8gow@&hhzpn%T_D#TGKGWSw z(mU&K9`S<q49_a_{_w0BvfUKZOD1}qCQWU7EYvpZm$dEM<b^*=cX0>B1stGVm~LIb z_s0dW|0o3ekt<)HzwtGg9>DA-@9WXz*$Q4#xmL;q<MCb4q&Af=1vF5)a9kR~P5gAB zUuc8RdyK7WGqzrB3iX?vcJBqhlN&XMlxZyADxG`zE%a;g<@<mqx&&iNb&IdUv}q63 zzcN(+s9#rk>{pM&Q&-d8iH4^p@_kJhH+b<+fVF<v#rqqY`CduCD%u~=XL|+x^zH0h zF4FHGfj8cmNQTA)I9;IMNy^rlF;O=T{y#_V;lJ&VZFI$j`^bNR_LTc6-z6Jjsr*95 ze{nSYJ)L&{H~1=DW!4)!YY8>JBX&O4zF~J&ZH?bIRq%iG#N0zwtFFUu{pxa?CLr%R z`L6bVk-P9~fMtj4$fn&nw1+!JwH6syMoL~vP6quN$Vsc`(mrmZk6Z7(I0jAvFKFw& zU)k+VG;~rwipIe=wPmlb^OWf%I_Ah9{(fCWKQHF{>-F<1hOW@gm$~ZadddWRaF6Nd z`$F<`jI+U)z)aI_$^~U!@L}Foq91*j`nI1k!S^&U9~&^^<Qn#|<~~n9EiZM7=a5a= z_CsE8oV)k}m??aan6q`yjPR69T?@Pm-=WL*p`pfDH(^-z>s<6DxB@GTYo7cq0WKAC zQTPV((8nElr7<4VtMktjOkYhHr>{2uLihe%#QCt!4F_$a+!}-Pbp~hg&7Z-0QBwwa zy|AaE%)7}e9=wJyEW0dl`;g$wpW$i#)>w#9m-unm=r;H9P3cM-B`p=fXWHPinD;;q z36^jQa6N;aIA+=z8>gM9aF@)>I=dW{70(W%$DCcr*{3-?d|Ma0IOZJlF1>6szqfG7 z{9gfw-=6T>{uAH@?Nr;;F11JVj^Eypexfvup;4128}Y5k<7ZM%X$?3zvw1j&>qIZ& z)MaprLz~|Or?}}4Xtyw4fz#)Hao*><CxsJZWF`G4Ub)bI>V60q;WVF?q$3x6J#A-2 zyNAFh%%eH_LT$i?`f|j|m)@n2x$8>8u*}!l<qP#fciFi#CbID1m&qH}Ig%B5yTD(0 zo&P>xH$vVx@UNpSs;2;cs-O0k{+ai4z2&hxoYXpLh1O~4-^ke{y0I^xn5UBY`E~f| z$CqsM*E-xMS|0zv`HaE;w}Jm0{jiI8ouRR0+CJ9e;dTJi@Ao6LV=Z~Z^Tft*US#xV z=@0HMDcwbT#?xchv&IvTNLF)F_cgj~oU}lf4f1i$*y{=Ll*-nVwzeWILE0LV*1-FP zHqhq(MO%Y&Rr|Bh&)(r_?NK$Wk9}_LgOfdoy}DDZwX$={=lgBi!CK|QI5d1SE0)SH zya{;ELOX2bFF(dwt%<c-6YH!dvsMevC;ln<R<PDO7g}d^v$py*(sG2OJUi&Xy@U;{ zyL9$+AMcOx?B{u$=P=I^o})Y`c(isqMR<ni9FIl$TAl`;6wgu~on`$)I&MAheT2IR z2M7y<vSD`;uI9OuG@CGNJFpVi520~H>n$rkf-l%M*1-L}^ZSR{$J-W9^ljrl7M{Ls z<E`zl!cKD)HW}T0bXBrYx+-y?v>LuVQe-Ze#a@fG*(tyWOIiDiZx_Q~TVj?I&E%Xy zI$u2h@d39vgI^|na{l8_l<Ker#P~gItH8Mu3%<7UbB625U)b!lVBeM>2KH`NuGrAh zzAx-oWTUuwId=F$uRE}ews6Mi2H@#;wL1@T&qY-|_tXrzDqF>wrlSX__qicAhL6+v z=kUY9&uOSI<kVwpjoO=?Hue=YNBTB8*7;jv5ub0yID04?E%QR%4N2|UV3$thzqMo` z@NNJXZ0hH4(4O+4Qh$>B2!R*D&eel`SGHE2F+FkknBRuKW^H<s`#2scaQA<N8++16 zodWySN23`>G@Xn;pX~eRKc0097Vsx$UEtyS3!NqxN}^S)P$<PLXk`sKy2B_otKaEL z?e_ZU&l;-_{5XeU=f5?Nx)0J9S7GPBigU!$4Yx$2j%aH;)Q>%taaPJw&mQ1R4!4c{ zyzi4HKDuNt#Mq!au|X%^%^1t#BZZA$_vAK6C$HP!-i~cDbr1Kr+$@{_pab_~d%@-+ zd%tWtnO{dI?{>9b&sdz-%TzmY<w?bztL#Dds$|Y>ykmop^HtDP{G<EmxP#T(a{F9o zHaZNtfWHqAjQ@J-hBu0DiCEVUC;vw8rC%Xmgu5^j5$ov*+^?l`bk)DN!R0<zuWQkR z%(p9xZ;N1)^546PtQ|J#PPcf^Mt7CYeX(bgNewVhJUBK5|JA^TUZ2<jKa}rc5N<Og z10EIC#TV`N*0SHE{JN)eHG4wZH?FZZzz6tMVs}nc_w|eg-QCxn;H(sBh1LOoJ+n13 z!FjwHJz##H^R+yFWt6R>oMgPppCI27c(5vkT+QJ3h>cu*J&Uvxt^Dr0?8VSPcbP@- zu@;S{;xABRmGwrQtE+h{zkk6u=76GwEZ4Wc1)oIkHqSo5-TcLEUVUMWQ_r}YhhL_z zlaWulUt<0?|L%{O5%Nx9Un6<9gC7O`yR39{e$L~b;ptCh9sk~E={dn3`4~EYY?N9P zpJ>*6w!HK`#z6$$D>M&q7G{Qbk~_VRjBxJ&Z5)ZjoD-x!wD5jMcj<j?D?H3S9g~Nj zDveB-;JoLn`6A=!<x$}3{yp8b7x+Z~I(V)Rr3Ze<A4+vZmqI7q#iu(6-*M}JJMm8k z+>vOtb2ad<#wR~TIqfTmCbEZ$PMSA@@n3D{r$Ez)PZRq6o75#+W@5@VZ{{r77w?1~ zecaEA-zj~;9!ZfiebZy~@hR>Q00*~r5j;ix(uXv5r2hzBYhut{Hff;zn;yg3H@M%m z%$*}l{M_-*J(QF?mdKYLPL}VAoBe5p$eo?{yAQ@<&cob^v>`A2H<kA>*kh5d-yXl; zYiA!tbpI@{u<Mp;ditEYe4n#+9p^0fa2B(<-^(_zCg90rII{=N#}_=|(dJ?sxCVGi zr@7VO8H_#U(f204`Lv;58?P8}qtLQUtBW@HpdD93|DYXe!)*HC9iJNTeHXsA1zB$R zH|URm=IE8bgyt*dyEDBi#dxO;XIl68^v<Hgd<fqR!O@*2IvcL{&iS0h;yqrF-G)1~ zSSu~8?|1D(_@qti^K4|V^8F_KCL8ew3AGpS0m7#VZzj}Uz)gg+-<L1hv#`SgFSzq# zW~5w?#!MS|^!otXKhWO5y9wjOU$J@6D_*tAdH17hh)0CaJ#S@?7Wzh}^gEIjvH_nU zukJbs_CloB&jHpE%H@HT=li|@mI+mV6M3v`zW50Fu#x)jdEPmz=HExzP1$bBt}|tl zd<)~DbxnXrH+ZZiukh$J`GrRWSeh?1Z)pF#VG<IONBbNZ!df2v)g!cmJ&v>JCZDLa ztVKMsQJ*3%8}$L=Hu<*^ev9YbJg*o%CfJ8oo3+P$`yJ)})BP6mzp)DW;<g2IovYak zIKH5KK4Gqrlai%Vc(2MZ&K;hfd}-?Yk&Peb;XcCkNu9CW;OZWt8f)`Q^_;WOo~Y!% z<gCtr;<va-vKiH^t{?exUk1Hm{*W^jzOH#jbH(V`dPipu`(I)%Alx-3*$lif_IiC= zy7qR(Qwo1zLeWloTHxo_PM=sQaKw)*_`L{7Q#T6C7`Vo`Gg{vyTZ8+*#3$0HV-|3L zt>0qMK6d~+u=ne3lasTVyYt9bYpVQwnMb6rttidYdmr!AeN}R!yS28~(OjJB!FIqI zk{V>s;GOW&?u|~Q=L2pebBlZa^WQI>|LrGBPa&UT{GNS``|y*@cUC%>t5*8!m=m18 zmweQoJbtG;bsj{z`Oz(-8XI-<BBSN?1A0_>+^;PCGwDfWpvFSXy5Gqr%KQIeSnSVj zvaE};Camvv!6(v7#21q7{_jm(%bI|;ZkaPj`}LcG-|OMM?$6Qd(4o+?MB|~Cq88=U zU$#>U-jDLGeWHM_L7(Yv3HcarN&e8MWg2*$^Vu7st`ACn!LOsn=i(;fapF5n{08E+ z(x>2KbY^~IqTC-k%bYOp(nA}}`$FF1&KCB#ID24C^L@7EqrKkTQ6}H*d_n%YtNlA7 zZRvPUzH~Ijo^txzp6-{HPq6%d6ZU|YC{Um1L;dojW#6Z+q0r}91)Yx+F1lZ@B4 z$sY0=l*Tvw(~9~w(;jM6eL9;q313UvGEkylgku~W*B5^F;;r~7PD%Ec&f|MnuXBm` z_QjK%fnD~ulpGP?Y9CJF^CmoM!hqhv`90kM(Jq>UOYplZ7vw-1y9B;?(D}k|&a{Jj z_&3wk&nKG?d$BBQPGs(@$hBKPm2<n13%X}PdsS`dpSpiw9&z2XqPb7{OIxBmr<~*t z-x~1<eT>NBcN)+Ufh8HPeqpIr{+))N^6xaLoM4E*f8;on$rppW)WhErb4I-<Z{S{A z`bNB1Zx6Un5sz7YWBUEBCTGBH;G5*uGtcGR=H!68h<hg`XVlM<JCa+1e}doLIy2{q z3-vrxQSVXWCj<G7jMn%G(>M){MPKdZ`t5?Y!S55?9HQ?n(APgx8R>W044*>(*U-Fv z?xi$e_CKU~{i6R1n)f)+W_+3#4vu=u!G*P`cNl-oT4)?+JrKv2XQV#nyo2?W=8Wi# z+==hc3!9-a>mc$pQ09bvOYz*S5S=UPI!auA0nZZteL!#IzWyp{zW#M+j$FCG)61Z* z{55oztHsd#)^TY5zi8Ll5U)2+VIPfo?tjATXa8?_z2Gosj!*X!cR}l(0eAUNbMDo5 zF_tm|-bv_>%r4DYfQ|`$U%?OSYR!GzJuIHr+Dh=`S9@|c{>7A0-r2J+y;FIs^kde5 z>Z23(t(W#s1x`nazo7mh{Lwi56ZlU^kCN=$l01p*(s{u0IRl%1iQ`k%fN!4soOK7J z<f-ip9kdepL(DHfjwb{EPtLyDBaQgtO^e%{C$x7p%0GpD>F=T;G5=U~(Imd!^M`!- z=-Xm|CmmkC-IApVBTLJ2w2wQC$cx;R991Z}>6e4Y#9zTY)rx&a>z6I&+%uo22QoI# z{H1lBUFbiEd@SQ^;cF@02d{X7Goy(E)8dJ2BY8QSz1+w76f`-7&LSTk+1VuD922T8 z$;4V)GI46@?sQ<w<oAZsx4F>m`iNDY*DLcv57eI9N;<pQNqNl`5o{Wr(AU=y5~JJ^ zf-X<pnrn1-T?QQDg)e)zatDF#A1L2Fu-VVw72qU)4(KagsgrXjns0Po!3K^^`BsxJ zX~JMG(j4?nFq%0FY7olK*Ms2yOT82RHKF`>hI#kLwDE~Ko`&WbcpIOTz-Q-L+SF{; z#qXdG9{b#nXx~Rl=&t2CgS_1->@>a}DV`rh=i7$wUU2WK{89Sd;ZOHNS7@2)Vr~&H z8d_TVj(^nx(S3#Q^Kj8WY+J}5Y+K0xYg@?Qi}gOV&^;4neT;P#bowEDrBLf2g`!F2 zeG)#e__#1<$hXw$t%5J7i66Dbw9H)rqERreG{3|tqq5|Qk>^4g^*b<p{;n(|zn^yc zPUSQ|iPt)L=CtJ_54Y*g?3l0bMWJgL&ILRK8@!~GhsR6sJBwq$zWoo$ljg4JX9rxJ zdw#I+c1L4>zG>sHf&*tbz;W5MYe-`(GhZ&pl1Mx7%bH7CKBY4&T_x<9KgK`EwKD^5 z-$rbv=uq*(pYx5gbHn*ae0W#ml(wgU#aSlqbztc;Ju<w+y>j<&7iANfz?}`gK9)r1 zN^y3@*SWgn=lZnTw7+!&u;?p(%WXDr!ewiLcR%GhZ{@FRmFNGc9|`^bBvgO;yc_a6 zUHUNe?J;^*!oR<W^;WMtdR?=#8(*Q|{%zjt^gEZ*ZBzJZtxoeBOBsB+SSMJ?yIuM9 zR&$?C@(Fa)Wd33B{dW7n7S4>VEXE4lvtQ_6SnJPYtFf!H#*p1GyT*-WYn{w6_m@G7 zTJBbAZM;}M!kt_AH=`1-DE0DvM|I3`I6EA%v6)=ekB&d=Et{Gzp5lD*(FHm07-x%5 z+?B)ch~H1_%Xw#bKg*-J+~@P;POsZW53nELjBh_W82iNJz3`nqad@e&iu{4C%Yr7= z$#R}Y>@D7&1o&kiD9b3|<>5!+7az_az}Mo(4!(=W@Jl?y{1s0>;GK;UV(Zen`a(UF zTT7m*S^dm;`Qj_sscXp_&phDm5j@=yM}G_Fp(K8`3Gt|W&u&5wyx114u~fg-U7SmN zTI;gIoQDqbs2zU0ZTb~>FDy9h?QboA-<m$?w;__=Z~<nJU*QSnUd`3A*9eB}AQtp_ zAN|mTUQ%-}x*&H`iI=}ES*|rJ<*Gl??~XNW_hA>JIe&jNh#y&gnBTkNtT#L?n9{`x z)H5&P|BkGmraHb1JlRa<Ap10SgTBz3dI$Xd(EIsKHstv(WY{hv$1P}T4L{(^P4#Ol zek3~gm^0rscivCg`+)1;&%?J&xGeOQ%&n$ulCoWV5Bxt>mOH&(mMm(f-e$fnHf7sP zD4N|%9*r^CN=~vsXqg3dkb1I#$j%`f$QMbMJ>(fe%_onU`6OZHlU;@K*#MnMZoGBK z9d=H7BdIyaq&xhxwvweyzMiN##s3XC&ZbEpfd`Y^FVFWH`Un|`-{iDXq`+?vASa^* z$=yEmn_e%0OpI1fD<MM}U&v7MT=*`TY4V8n$}9PyP`ZS|N;#tS+E|)>q8@%rm-U2y zA6~Y+mMGXOyhw&M8^7Z$ok??J((Z6u%{ogqfbIfwHuy(|^D%z2avHy(SCtqhOzOAW z%In<PKKu>yyS*>)I}~dj#xP?-cVs?5T=%8b`g<MNY|#m0*csyX_q;grLG*a&t`_!4 zth%-Wzge?>wzHV9KASy_sRA1>dCeG3Su+|f?$HuHI?EGby^BxqCdu4@2StlZY%k`n zl(X=Ll|hbbK1ng3T$^J)Iqp4p_1kH8FrTa}z0>cz@_vSBp*x`TU4B}c-}8=WafiQt zhmBmD`x>*%C6*1`TItN+@$<(D%qIo)_sUYF30)|WjbH;~9)u6L?*TZC((UA9i>+nT zF@6U`<1_Z@4NhU!gV;37cVYzdiS!7~(c*Q@8BrhR#-i>TSDq7u;)n2jB7RW(0zViY zmQS^O?DHwz4N{&L?ew5)Inr^tzosXGJX}$VVSAUZtUihyJy@z~9*PJD@i=*+(W3`r zHRS0d-EWul>D2ZM^CCVCPy6_XdD8Sp{hi>Df*<dIZWh0vd@cG?@|d@+d9L3d_-as3 zm+UL7xyts$R?_l?vQ5NxvQy!)Y1NyuQ)OEeKZ$?Q-6QDf;M`T34ZX+Ku_rBi2l`#? zI?gmM?2mD;(lq7u&!85hSC@H7=T(kjZ;Y!S_`SBmtP%R5tn-bTbbl>0b=zrQZZ9h5 zeTUXZK^o@_^xLNq_+g|$V+y-I=Qh<3b>N}<aerAq1?z=T^;7!deJ@uT+H>#ArhGv< z&FYfv4ES_FOkJcw3L2!i&uQ^tXv><0`=@Ag3~>hk1?>*b-mcbfXlx38uXQ9{{;k&I zS92F6{T2lV{ORMYxW<>lN}f8`Q|?dsp6e`-`c=PaC|=oS&vh1nbKqMc-A(k<9^c`N z{6eH-=UxiV$!IUbr?1604|HJGGQRAv2b~tPZ;Z@fuV)aOM|qA%ADu3{yUI%5%l=q~ zllS#y-PO2|a}U8DgVsDg%n%Hnho@}09PQA!_Wie-4|(mJixE72`>5Q9h8|}OJv6U` zb!6G|MgOpF9E_ib<M{~Lqwt5Xo6m_O>yam6Jvh+Mb>2bqcd&ku4P1Wvt)w^8cKN*f z<4-)05G}-ieMQ!{zTU32mf))I0{H*g6Kf0O`ey2g@;laVq>f<jTqAlEkUI&@hs$)I z(vOGDT3$W?ohjCU4*mnFxFh{aV;cPuSp?4};O9hc3Vsr-e|I(d=eAYemMvg;>0hz& z2lJrXpD=w=*-l^fg>XPnT)+YT;r>d41LqZ3K(KCnEgn`PlK5qKh|a>}a`bK$E$F+T zPtgg`6UuxnnTvl&V>B5{Se*9>;EdOQXN*kWR{&m`en!^_V9pgxTQISO@UC;*3G4v; zE-vTJ`rU6~bFX)Fr;*0rz?jvu%d7sx2KPHRl=o$1(>%p*KQv*(Y2|k;M;SkXzUl81 zrn2r1(ljP&QitI=+6%pg<M=sP*tVm(pJu>oo5Q`Q@Sw)Y@nm^^ewr|R1~B0DnH6*a zCbBv|ZL58#k@m*|dWLxyT3td*Kfm?b{5^(N+J{LRJD*Q8=0ctOYJ7IkjdNaUw9w4& zD=#lCfleup--Uc)#J6?H=B4v5vE*jP8*5JIQ=EOf$@R~k6xMQvCW8M=y@SnU`U|s< z`*hcMe}r>sdzcp_lP>%o33Pe|-Fj^5sGsi3Dd?xQk@5v`y(`U+!%xAPnfNs6A<OjJ zadoxWrPaqp-d}K4?;U0THR=dpy-GcjWkKAcyxx^o2|K`1bqKc3VQH-zoUIb=13R^7 zIaBxbqgz_EGq^u(Decx=Fd6yx0Tel%-#ODDdq}!?6LUd4@gU!pm9VMqJc}=a#`A|s zk64M)Z$Q6@HKlYrq3%vE<CoT&f4Y_4j{MNvw@mu>kEKIIve@fsi}J<i4>)nV?8_mU z7@0D_IX~8fx?_v|`8aZOCUbgyBsj08-*;wRbWPTcN3xCuUak15&5M+O!$<YiQitlS z1xNN)o{r&fGK$@wy0K&Rk7+C{ZGXbo8+=?<4`~tl>%<2S`QyW{8yw;1(iZ#Bh2L@2 zn3leJ5*|K@JU^MZ_}ddIqu<HVSUqZSUl;UC(5F`70k1$l)g^rpJ<Io(d+nMFJWP4r z?R7R(eq*RSekA@`yvnmt`rUf1#o)hEuohE&oV9#e`+M{FrgKp9fL(6)gI<ftAK34d z{}B15FX;Cn+Ga5$!Wmj~X}xtE#bpucCkd}3JVp3!LZ8RXc-7hGbw*z->lf%)=oh*N zSHD#p=PulBiMjrmMSu78(|2GS3GA%bkoLlC>5$7yZ|6OaOw@kWZ1Ti=G+sWUHCvtT zf={4xjA{<G`yAO=k(K^$IW&;IL+MGSuPC;V&UrTX|9h_dJGJ_q+;~E;{(tt~KfcPN z+V`LR0|+6K4TP3b)CUM{+6LG_N>ik=fzSq_kdm~elA44hkemjxn}n7s9z&BBT4@ae zEmn?hJ$U3ODk?`&xiz+^oXSx=axGU;_ugqN7qO(4w$!5B_viVMJV~ji_`Ua!@9W+t zubuU*XU)trGi%M7HEZUXp`Asxq8AdQR3{qOpPT-}-tWw{{!-7+HT6A{J&3>6Zey&C zJSDqb`%1M_$L-Xof1E6t&^N`}lV0aP>pNKaBecJ*bZ?Ez3)MUN;M8)`h>=DNdd#IM zjV#j8-XJ@DX=qPdrD6HfI7%Agoz_k+_VF%4hb{hni|6CG_v>TZZnYR|VSlNQQ(b#& z1h!6}n6$^o6MkXyL-l^ny@%~%H4hxNI`LVzGXL3%Uf5=zksM5F+{pRJv?28Y-zS{f zlEUgt!wl9KYW!lKq3nkFkEAotr|_C<W1ULx+_Bf+Sk#Z*54-DrgXAYdyS3$+c>X@u zU&c#~=h^hTOY}bNWkWgHuVyNG3^{yC=P#hsY<UaEV(BpbX+*Z8DH|1t(Fev7q06YB zg3yELKje^jxG8>x{!WEitCAm(?@K;dx3AzG_V>(V+tQMEeeYi|aqADUlb)mAQu{`J zvO5v<&iLv-4=i2pxADEaOCIl<;_!6zOZdM#f6@KP<OKS{a=ZP=)|XFsE6?>z<Ffxg z!TAnC;}eznc#-fj)=OZ!qu0d4_HbMGX6$R#xyD|4x7viD<XBK`LQwn=^u`|^9|zhE zq|Fq2V$|mFTkQbPzuX|5!q~HxF~NRsoZ;e~9!^_XJWcgo+7)b_KQa_g1jc-#aYP`V z7`5lY#E2oSee2Ug%&+`;X(EKa85@b<iwQV-F>qzFE5p6V9yq1)t8YNwGj*1L%I(eF zMCkuC_j25AgMncY=>oo=ygjY8ZHmjku?OMBLE81fNZ+@z2fX%88ITLcEv;#lO=X$q z*6+abYFsM5#z{-(i^SbDyfsPcTcj_%vD*;dT~7FcI>lR)BpX3xv)d1P6?x-(5l1E& zXWH$rh-KE;2R(Npz~w%jQj8v%&$B#W4X|c_UV)#sJ?(FY5%S`Vud<Nyx7$-X?u8?a z*M1_MpX9qF^Q#=5X@7LdYmPnMzz%~?Ve6at$CpXpWM~{J+Xb6-Y#wQ;pUaEzbL%VD zg$DVQzVY%ZIemh%H2BKdGN4?Z{hE-j#P1$5mB~nUV=96Dth78?_u653j53!%qpy+A zM6#)|i~pQHjcu=ZA36s6d!K1@Y$*4cZ1cWn3Fe2j*1>6avdjDV&)m5Por|#HgK95{ zt|)7W^?kSILl?JF=W+eoy6>+%^ZP)@Wqjw$H&0_9OwTR)IpNDvhBH*<&l#NgAafCk zuDJz2=<Z<Mlg4%(1+CqItjoIyAH>k-dyUJw2sd&|0e%_2t>046Iy&Z_2aC?g9Q+*L zfoD1C1d#C<X&r?(M<yMSonrT`l0VNMc*U>>)BC)(97iX%VmGiRc|+SK$7W$}Xz-Wt z;e|IbSHNDgx$?z}2g_1Tyw8?n%BsFa?^d~vgdgqRT)><#`QKcyrF-rR<N?`M*t|XH z;|_cekF!=q^<;K%#sz1p`_53b^*_3=oi(EJ0k*Ri)O$}xG&4PzcW96IBZszj%Xb=$ z={ybbyCHcrys;Z`I;C$gcU|AH<MhmqhmJ63kboDhVeL1gyqDN}Sj%^-Jj!>dbzxC- z^XMfHrgzTIP5$?wY?Tu2!;l#^>U%ir9bf0f0_N@toVhzaJ6M395<VO(Xdm6mS-ga0 z$c!(NIVRRpWGWv=SR=4&5P2Eg@sMF{-mj>OqwL*sJg3ipBfTDA4Z%o@Zx}{ye=!f= zn#$bH9xlos4J=bKr93AhpX@$Je6=_7d@X*yu7m8as(N{jv<H^;Abg7AuO12Cy?V6e z&y|~1<g<c!#|wUCmvbU=7Gf`}&F&nq<Vw8IIY6=z?Kw>9ArKD*-+(6j<yGJn!`d0| zdULYQ-fhyc+G8UR9u`8A3`)lBe7Lf;hIb#JJgRTL{}`38ew#8KaLcp<dd^JfajhRJ zO-1AOx#5`>&+^!>CZBrL`iqiD?cHUg`EG~(HkJb;qqcR|@vNNt2H=JX+q%~S$FUY| z!}ac3a*KLLcJ3J7o~~eRdXLpfonF~}&YGKwl6C>SQ@<Twcc}Z`hYof35dSQ3^8@Co z<PPuqrXAhiCy&w*cDV?@f;y~&cRKsy=poXu<&3@DS+{kNJ#p(u<Jh70?jCHLZ?S&r zM`yH#YTL;v_}xcFS-XjEA!I&z@_N>usBGh~-}FqjTo&hT7k3Wp{&&__$)3|Xt0U95 zck8T^{2A@`nI1uSqOhVLg*Kb#I?E#?I@~@JBy0_54;bo#^5kr5?>+?oG-pO#bXgOr zJHktUc>L0Ov?bJ$%BT9V%ZUx;$?+$#57h@q_P<10qD!6?*6$}4zFg<gYMz5Jgy*ZI z8=#$y?c)1~v4zmJZr$@+(${3h$h*>hg?jCTC%V`3L+<@=xcAzJ+Cc{V(D~7YyiZ{z zbDhDB-5X|X?7ojQR-z*hMYQjzE3dRIjlma>mMwEzS03r*g+JL{0<LzJYulhYH{-Uh zZ$s<1r%Pl9--IT*s@WH2HokI|JzhW=Z9BAtePA|@#NHTX(<io#j@$lpw+#?ia_<il zCrmM6dhKlJijQ6#%~*G2F?79SC}lj!m^DnE&?#eo3GUU+D|{1Y?=eD|Hs}1pE|b=B z+B%Q)urV?vuWDyXOV1U4=R_-c{4)9;-hceE)^3QW(03`?I(qWXu0gy<zHpswy=`7@ z@+kFh&$W(p+F+PAYuE!=^8y*%cLK+NXK_Ccn2%n|10KO<%rEHQ2InGQ9~jUElcf6s zaw-0)9a=4ix)Y?en>5B39P0iKeCgQU*A9O}e#P5D_<R!n9`f;bBlXixeW|SSryQg# zUnacDf0Q(rL8m?#M>*~I^U&neQo9P_7m3g=+RzpMjO@Ob_N?{C7VV@!@n{RujcUi5 zk5fCg_2f?ai=FB(hNg??W7O9F{j*M6S3CFGwZE+oZ0Bm<+2)ax1KW6@V*<~8ZJd01 z?Og3!ZQb9-2b0g^n)^ncJ)5xKdXx@$+;L5sZ!S+&k9&|kkRD94hg5GH2_P%7Z&Y8B z6}6Yyq$zviP}t+8(?_Wd+IxH&?0~G+F7|px=A3;&16iHmoi_d+-epEJPe0m?KM0>1 zxO9mvm$ct&qO1{y9-?2=GwCI*)s$|!4Vm%!lQ8;L`O<uozLSyOJV_hoe803UqtB2w z>li|2E4uZulUc+M!fVcLIjMB{cS>spjw5qN=#RDq0?F|?jx5-8p7rG5@1v~#{9Q%< zP9i`4{4FJ4%AeLYW=Jn0ze+>v1+^|v^JK@#kMgMed3jPCtsnIABz-Ae`5o1hEn}=j zLcT7>H}OKYus6@**~6xUa>ld<gtb2}fA&di;ZtQl<V;$A34Vw8o#q$$5&kEB`P}Oq zLFKpoYQFi)3#P|_Uw~)$eNuzm_F<1Ry>QnhQs=PuFYvwKg#6ZiVUj%er*%}}E|S(V zcRs3}v~+*5w0gt1`Le@ZBrT2A?01q@&D-Q_u@}ZoYxdjZYn&I3v?6blR^A}|Jp6L` z*}ge<9@nsrUiGg&s1ThyhPCJx&$24Fc8_b_+MO3?t$fGNyS0aO4(oFQm4nl{$*tYm zOS<g_{I1&{N#)13c1J3=c0ZXhBq?9I_BGZ1(vP3Qmd1DcAp0k3y@cWp;X4Mcli&OZ z{KiKT;(7X-EvZfMjmfp_(LT8DkyP`0vHu@!ONEQK*!Id`%kind+pT}CKM{}D5l(f; z9JY<$=i;J;d3L`K&v5$@jhFrRc3rq*B%NVDF4obV)7rr|jUAM`J!v|T%}Vl~SePy^ zS(Fa7GR}&&rfVYX6N|pA!?x#3V*JJ0V`~@ZOz!HgjIpOl5?){v={&z|^VO5XsblB6 z=?|vrpwr$aV#~~6F9z(pwl>v2zBIn8F4MUN*Jki7+~8PEGNW~s)gIrJ9NM}n8fe`- zArwob%CVJeXm`u8Gh@8JxYgaa13l-Bn-o9LS~EQmt(m~N=+TVUHY*%km6Q)nZQV<w zoHD2mr8m8}cAfZrw@vPN6@RifH>LjB;3HI@g1;nldnIS~g71uJEPjX1wwsj`(LQE( zq-wNI6<bQr*(Y$8ML718NZrHz7&}Z^YHn|sveZ=W<?~Y7CYBf#re5%!k?$wFJzp5k zp{K&*+miCrpJ(hOo@<?#$|Ap+sVqs$?}G2bmXX2Gy?rdbXR>SL4^X;;8Eel*=S8iD z@Ix{-?$mq%-*#gEL|6yLJ_IR~)V|Q1<!d;Dkv-j5N1WEYrRvU0TmCKPbWUxdj=l4( zW3KOL4EoVR|LaUt*_I~um~A)Yxpeu;w2u1Y#P!at_P)>e!j2*SdD{3{*I%JH+Pmyw z;vBV{bE%Jdz6{p8iPz(ZbA&jZzBu0_&L(JYnR9UC<Pc{UaWwCsI@No=N}NZDQ^$Mc zuhyDjTXx)XsBHSiZMiSb=ZLeJIGXD&faa|a&Y>=pFZs3Yy72Pqi~C99(p#7f<N0!% zM$y5qhu<E43>-{?-w}REe#iJpZX>ST%5QG_h26E<^eLG(kJ&S{0lt}-b2e25J|vw_ z#op2Marla2t=-{dYj;K`{_999_H=76k0Y-CQc(Hw>kiGMnO68#IX4}kjcPtkYadx} zg)aI!?O<8g$hOS^jk7Xn>yo?Ok?q|Hd_eY|0!jRl$?b!NM-n406tZtLXT@DOV$yL7 zpG<OiaJ>QMw5D_h#^X5~Q~5gEqHv?VZa+(BlI6Fh@**04I`%+*iRQM<sSISdfpy^e zevEM|>!Gw>wp8C?Wm+AKPm|lbzrh~S`zNkQ<t7-bc5<Fm@{#1zBUiAG^orD1lZn*7 zcF^B<KAN=HhkL?Roa2$%n%YZUe+k-9&g>X}8Tx%D&&fw6`(&@YmhfXYroO?R()%Ya zN>!oPtI78u>O*H-DvwV;WA9UK>-TWvA=;huT=|tud3pX%yL~OU%N3-28dHhx=_>!d zpC1Rsk2rNy>DU&5l0<5+g?&gKj=SHr9#8U3kyVq_oKD!>k{;Kwi8<gzDruq96SjZ% z)L_=gX2ffv$@rC%EbDRl!^as*m9S2%EgfO~a0L4kzgK41+Gp!4?MrKQI{oI5R?hDt zzOm5t>>)Ckz5qRlu1BvW+D0=k%l>xdDb}OR(t8HS8>}qyBmHq49WR|`w=eXIS6;h} z?m29dxwz(TDVzMlo-a|~!EL7x+esf5jx0zIqD<(~F3F+ZEkCJ+ehu=@3UqB=C;mU~ zv(QN&2G{e|K&?Fpa()zc!K{2c%$;_atL!j$reZ+pTJ0w!UHE&-lZdKMDAoA_nR=&W zP<hjH?a7Mo>#1;nHG$Omd7ho7FYwA~>utXGlHLwdW|dvC;(h1!p?7hfIq}3twM(yV zJi2r*`uJ3M-b2aqY3va>o*%ll+|{op?&!mOi@n=<zSyUCwI)dMmd;_nPU7i1pWFfQ zbVjuHXZ6mrmQH-0cv;h!+eN?ipv!t({S{{Yne0u~VLtY7lIOObbMv6QE57!O2vUbj zc<)})*h`$fZW>w#E&Uyyu;ayjJonb(D&BX9r*Dzh6K6fN^=_OXbDAngh&XxjheEU8 z>!#(`&3oK3SCUSYbfSdy=6$_)>+I_yp8Mw%pCX?0-%SDZ^7ua8Y@uYOo5uj(4=oRP z9()$}Iz#hDU>GPF_U3);vkUM;bhzJs4nl4|#6F>FSK_nBWBJj&xjenwpGNOm9Cr?I z2x%~el<Ylf&npGCIqUsMLv=SWt>xtF|73czsayDn9?%*vXFg3nOXU&U=1~iJ067nh z_~a$!^Z!)3ny-(zIx>Qt>G(Yp-$eI**WpJ8zLvzOtfTA|NS*q1lGZ90&Q*Eo+mL(t zhKctpCm!ErNH5T~y*8^k5O42eh4I2o!{$>O@3Io9k4=7t`GvOh9KK)5!+##Eq<^6< zk0F;i^mF03`W3!4W!<xU_V#zD;CcMsHLQ(i%>5us-nXYpS2{;~7i?)|4v76~q!(G2 zIX27EnhS7#`sPY=wsxLaH;<h-n)SNadpkK-dy(xoR@$OpfzL^6@QTTkx30a&xc1S2 zGWyH!<<HBT^q1sY*RJtS+bW>V6b)!MlASE}AmaPQjsnxMgEZU33)xD3S@wr3`<vlz z>*AG<jydm)1$z1Fj*Y}u(*|EH#(*(oS^LMp2c6;U%`JY_mTAtCAf2$rmGFKq&yGxI z4T{z~#^s~udkA!RsKn{pGQg$NLkW0TLciOA-2`t`r&-Vxj=hxaXN3u8tWx5}Q8>k$ zO+1A!<GI4d2&d=j7rnH+G>Y6bw00sA!T#yQ=1K5fFgyxH`R0f3i)4H0`=N1!c`9pY zawGR4&Pk2pPYalNX^ZE9>1`?em4uy_p5vZfJBN7JY~%gV=iErxj)m#K4Q=ejGBmw+ z1U@;=jn&yp1-$F?ozC}2A>w?AJ%=XUL0LE_R^#Wa4?dI%a9(Wok4!p5ezHdb8B-S} zS-&==&9?orXOW+d?cL)!3$2HIOgyxOaq0GME4U?<{Vzk)(a!DNkH4rhMndWA^iR8H z6E^#~tn{`2f~~ga(NygRsW-w;Ihjc1@8%4WCx)hH6X(JmKkQPR;XKb?{==?8C6A{R zFUq^Gd4jk*A4wGwFQ0LLPjYy=kT}^hL+L5$N9{fQvOk}do*m!bEqm}<zE$su4@qZ# zDJ$L6nU%h}>5<g6oU?0oKAy^_{=}Oh>)TQpiS6B4F=vncp%!uw>Dym;2)NF$_xLyn zTxY0zcqX`Wmb@b~Veld!U2^Kl=U`;9D5}2Bi60!{^b4MCrT)dcSHEGOi|&SDp6!(S z4zGQxoq7F+w?9O_+K6la$d_XKR%ip)>%LPuro4-F)S2N#M|T$XS-1l~i``Dxe}eHx zM(d+VwW-CiMd{htrr4}qq39#YGRElP$Tt{o>TJOeYHYDB5Kpw(-*3e?&CvR%L9A;S z98ZiWiEIDFyHaIw+sCjC9|Pg;l#hXMrClY|4fbGQa5OQ(jA(z+Ondyr06HuSn-&{r ztj=uLne4&nC~Q~l32aV<Mr?mEH2yO$2F-}nAoQWeFz(rI_Sn~}Gx~(y`t$1`uTD^5 zcAaE&IyPbiU7|f2GR#(NYW)4|H%=Z?L5uysXb1F}wvR+}`yrFq8Zd3Pj?;TQ{p8sZ zUR~3<@D3+^@|vk{;*`G9MMq8~?hM5xJ$r86pO(i*`GF2#(_z2bXBk<Q%n8W;?R=QM z&+bUo;-6`NH#-TlWALD)#+gsw&Dj|n6R8IJ&Do4$GLoEuTGEzW9M%5J_$lH`bdGEa z{f1p~oA{A7C9Ql9(>h3X8SeNZ_Hip`&_0xA{m5ADsinAj-;j7)auQ|HepDJmggYKj zv##x_aLMJ}LrGIM@?a|=+xnDA$j|>l**=*W_}((WIbSkGz05KZ_PjvOG<TvpHIc{B z$D9YOv?3iZP{np!zN6rL2WM`(FRaeSYD?q8dQ^EDnq<rr-<19zgw=YnAyqf0!&Y&+ zfqpT_xekM?+LHF(?&_bTU#D!}u;(TQGscdTK4h=MsHCq{UugHQj3G2O6aVzxh-5F; z+kf`S)w+^1zrQf1vuhA%w`$FujYsg;M;_81GpEq`_BjJ;o4Pgw50RK{qqu!p8T<{$ zXnS$`GWv)ik@n<<$gu7}Vy?#U)C*(Ajzp>jUKV3FgyO7&u5`Xj7(!i!Ij7UOV><Q* zO?hLw2W7MHz0l+2eF)DrZc<qJ0n~0Yw8w?@=}Gd-t*1@PHy6Y&XZz>iq3QwORB9-4 zl#yT^Y<#tyFU1#a18p-ve#Tjk>iu2$z{UJTXRj2EGXnvub!4D(9&%F6cUX^dK7-RY zmPd4dWp_Dgw4eimc3)Q7^#StCm^-;#b{=WU2R}~h#nB_PSyz&8v9BAyTab|!c*{KE zTgIeAVl_$SA?(t0PG*L+)0R6u*ILZ=<U?gA57!6dtE~+NobcR7**j>0$~Ocbur14O zd3A4Ex2Bawpw(HAsX7=E8I?BH=HwvidFy>wC)bnr5PONq$H?xD;KRC~2nCY8^%!HH zvB-nTKqqr_^uJ-VDVZOAlyx1Cc8{Zu7RQ`A^y&)z+BKMT^j_u5tGlluU+eXL>PUOy zsg9OYt^>4*p|?GhTx{9%tf?Qrap4c&B&?pHL%O_r8yBNK`OW6Hm|r=+c+BCC>cZ2b zxwI$mJ4kO`lG?ZY{Nvm<p}y!dydy|M?-}1W2CG5I#$8*{n_r0~Ih(F?E8hVi@AxbN z_@#r<UvveMKkW*zrz5`9%t*=B?i|`gzJ>3Ca62YUNN%4oF=_F99M5+I2PL<M!i?L| zDe{e#v~~w$ttTV+%W|w%(r)cmTh^RQ4sjyH$s?_NUs~gMZu!#E+BAQ=+(o-A*Z0zu z;yXH=Z%)0w`=9JKwY=*NY|EXrOOH2U*0!l%TLwLMB71Xa-ahtVav%IDu{1CHRChb_ zuI~ozHLURN$>~=ozd-m_c&WILaKD|laeTV=I9!(M;2j;{CtQ3txa2@-m0(AO;Kd%& z?;!rucjGriPWFRu2H#1%P;_JR0Qh$7-o402jkU?{6C?{I=+FeuVB0CrcOspC6L|=a z-}d5A-j8n%ztHlO?BWFJsl3=7nY&3-`PgmeoBhXmwimj_F4QIdcxR56Zz?knL|97! z9x*$*wLga1;C@5c2z_8AF+=@pkUk%MvNd3BY*QMVqnBJU4{^$0_wOffhw1Awym2&R z4~F%O&z|bu9AGb9^4S__OMU_WjP&JfcT9xJ=xzYtiQf2RhLwC8dLOM%r|+RW9-n2S z$#>(uOMB?-qm0_Ku%u%fc0wYx)1psx+hz^Ed-1TLWRuPaA4R>6)wh&-E`JmL^r!6e z+~Jw>q581>Oos1~Nz3Ld<&n=xV-M+HJ=1%<_UN|@579OcG0r<gTRh~p#a8ln5d5I8 zZOX6nJA67j3A+>8PM3Ck0{M+%zgUlTcko<t=l8M8uhSZR>o?Txg!B8>w-Zi&n?lkr zB%MMx{S&_Q<+qU>=esoVR{nVPi|QXgLS>l=eY#_pt2_1p<;VFj^bYPn3fu?u+jJW1 z+IAMc^A79hwhRt~cdUP+4>6CnG2W9bv~eEp7x3qJ>rSL2WPd3yf~s3V<;m6suKzwr zykHEShYoS<xn=ZsTSqH>`uH|{RXak{Hg*)0Y}-+6I{s%#gguAgnQRX6PxsQ9WjuFy z?0iG$jgP%G#E0TOeG_4R%k@KDW0z%l*Cfg!TQ5O*cVrAoW{hVqFWUFhH?^fp@Da?$ z_Pgsdl!<(4Ux!akzeelh*?*FK1$f5t`b^n|g|u<C|3TPBVeGFkdGq8?VI`B2SAD<2 zSmV*n8#nXa^b_5isfT}|{#0*a_WsD=8Q)^t-=nGyHJ_<E6jUAdj!E44-QF|!N*Gt5 zM>IzejH6#;&K?4u{wzkf<f_c{S>x<^{L(H9JfHS5JGrB~xP){2&=-8O^XQ;f;&)Of z6ByGnE)I@=IH@&B8H`Wx%Z#=<s?syi!xnmA<c)2(n?Iy=@z)NwlC~bor5%o9&!H^J zHUo&Q)MZ5j-RS)`$&S8F3D3n}P>HTZ7wO#!BRc-|ry{Y3(@|{UFghS?{hK|X5T^bd zzTaW%Pt{lMQO*XWUew=(qkFoUOE~56|D0<JntS0tbz}E8KK^U`HpDFND&QNFhD!E3 zBTr9c3{GZjm0ZF9$q%N7qLXGD)?ne|z3Z#$U&N=9uBWD7o5V+s46tW{BLlyBdd<V> zLh>vb80?dQLCC4{t*`@R;5p77O<K{1(vpF%x^1Z6+@$5qO|tiX$|O1Gm3;*=%tm;? z9t6l3eTKcpDs1x;8RfZTNawXnb_69mf{0G9?09o%n<=xQY-)cU5&11|laGvgDb>D0 z&xL5?vX$GWJ(&C|?O`@^Yvmf(#C&sW)KA~s8t+e%$4>HSe0l67JhEf!258Eo=Gc_S zzcuHkahk?`flA2`dLag6?_w(#zZm0V_66=>Jp53BwQWaPeA|u^YuFBre^uY|L5c6u z6SmyQ*Tgf8wdIovwX(N8_qGqJBazZPd4%U<=*vTiL`rl2Ip8(GI{Nc4duSIM$EH<! z>Ys{yxX$v3`EdE8ym#kBHsPb}i#rC~@P5$?TAe<BOymjHM?TRl-&9TlcpE+<_Lc}I z(FeS{4Lo~hW;*+s%rx_b>50tK#dtoPu~z;`&a%BWGu@NO#IOED_k`TXQ`b)5+3y4C z1I*7&`8{hX*k>?o#&xL=%rZ}OM>~e$*D;)x%kNtJOP)UmUsLwy1L+C)ab{X8y01O? zc*+XmtNKzPE#1^Z{;quipAo*=Z1Oig{kU{;>L7E0-|bpNoJI6itX(v}?2eN6>5&!P z!x<~jA<uKz6CL{$|IZ5MhM(xpZ~bMrd~A9?J-LXox26h+GtI0ZZ}`PNA50HVZnopH z--YdSnnBz-tntxVyYfF-gwOs`kae@c^fa@mTWMtv9-fvTYEElLnl%;7p|+)Rsh8~O z!_%7MoY6{J8Lg@8hXd*CS;Nx@au=ntCj`<H!>y^jhw+QeqWqgTrzRF`wtZkKb3yBs z-BZ%7sqrJ*Qu|+EZZl^Qw!}DlO-(UnEg>IME>hMg&lY#|m2)=bRyn6o-pQ1+jCib# zrj8y-P9?0$ZPyiLRQXlT7-3W{@n{ad#y|&tHp*V4GEw%)lv`z19ayXI%Tf01!IXh= zXHO5Lr*<srwp`y{c5pal4y3=OGGB`v6+Du%>K^VbXSCzW?g=#yr>3MIPL0Qh_YKPW zH0KpBrmPd;D{|R2$V#Nt&OG^6TPwy6@$fQeTC?ck%fVwlyc}FUD34wVUg*O!NMCz_ zdvrnh4Ye<}+Me`?XS>aeQfG#JT5kJc2)i&-Yfz<E<U8>Cg1BpQlzaN51l{23lVD{c zCHq&tfaMl_FlEs@#^3{07|f!~!9RE?nHRw)$~vGZV~*L$UD&G|)hEiAFl{*fI`hio z<@X8Fzl~#^kT>5TTTr@1KGojz=!1*x^w?`m>2+em`_hxYD63z3j@|Fr<j%e=8gqK~ zh3dom?pWhwt@G6T0;ZBY^4$QsNA|Dww$L+$$>&)v;q>jW_7&B>SGIlTtsB$$jJi=D zNniKeF6=1VC+6Bo+N;5_m0I7%R%*3vCHfJ+t@Nw@wi5Hi@KyGbSC)RZ67RrPdQN=N z7(`=?Zw?q^sQ>ruB!3^*=Qr%Yekj$qT+iiovUUagD8M_lKhV}^$0xt}H*8m>=dY6h zeg9PW+o^st(3Z4f9o=~)%x{;pCpjM^Mf<pRPbKeYCBN}R3d0Cn{K@V%=EJ|*FW;IM zOr%EH{-h_ncZLU+t3+e=v9cGGE`Gmj^^I41pgrl0!@O};cv?F=cGBb9XJ_5J8;^ZK zW=S?wM_yaPzUtlI#Pgx4j9wejnggxp4#cpv)lMo|_d%Hhb2lafC4<sBSGIHswyf+~ zx2*^U#^bY_${FO8%WI>aOfF&WY~Z)ZVcLbhixvOXM#e<?&JhtmwT>-oLf_csfIDXK zk0FXm-~;&!P}f?Us`*ICJG|C+=XM<rA$`x6pfIXag_A9gj(E<lAK&=IlN<3`;~mD( zHVgv?f$NMt($BPPJQ1Q^M`?T$q@JB|jspWO9&(|bZ`UTxrH(sU100BvZ`CpW{rgGt z{pd3JbYq?D_lzzdf)9`H5K^R-dVh3L_r61m?7G!lPhnzv_r7OW*lTxgim&MYQiAa; zZC>k!a+BM;Z){!Bt+|=Z=eF2(gzSIW4GpZ-+4t<CR1bY)aVO{7vj#|OgVeW7xJu*W z+q$$i2s=Hkbw5K{=c9E*RbyGxGjb97ZWH@rkw5iAgn4|##?(;y*w&4kS)2L;>}lqD zMzVgXlW$MRN5I7JM`fiAYli~KC27sWS%lj{m{??E*KpPsDV-d`-$XwcX+7LEF0#E_ z>xoQov%S{nM*26cGx`So&_VJ(i*Q+#Rb^uQ_2}TXn&jxmHm8dc?P>Y;0v(*^5Rv~7 z-C{lUf^Dx6UVE5d5xO%)8~E<vxeq7pK1uStR<issZOxJ04DQuGdHCpC+wps_=anyv zWL|5XyfEQNyS>KA!vzCZI=*kOuaX=}9+jUV(7orLY%KUKZExS=bXffqa#4tWiN;w= zS(!-PGJH|G6WvSMY`@Wl0?wccQ~reOw{F$>uFF#!3h)74#COe@)n0o_ea#9HE)=h^ z2-l@Gqw907wEZqMyXiNISaaIq*raM3ULG?dthcvnl8UP{Q!?VKqM`UI>+_#uPAi6A z8F^J-qPFa%7ow~U<kQm!URp(ASFifkIklA1mg7!4w!gh*&w#1;tnS9iWUooB)SS;U zeb>ZyI(G;@8m4~qy{&v}+grC`LwM^`m#4l)IinG+PhFnk8;x1=9c$ea@n+2?oYtqV z=DxrVQ<mD)8>TF^mHQZJ4~gZZ@1fqb|M+pva*$8$HpawSH*hcS^wzM32$P4d_tvgX z(tHd3gJi^810{Z|9;AQlb@ZGeqCWXzI!k=Hn9kB%1Ul=x@?m-FE4(~pNau;4(B2Z4 zF`mk+xPyZaC+)EjFk^z#k5$n(<@fsZ`qpmfJ9B+&sxc(%8Bd+SS9gN7Qzu67bJtFJ zdVDav7Vi&3JM7Y=$K?aQjB_A%6K^-P-7YPP|E`d|FA_ZSuV32Yi>tl2+o!P(mAE>S zqRypxYh`B>U(c8O;{1#_%ZXD!9IeAGaA`5#SHv^MZC&1aUFA=EUlb62;CkE)d<EW_ z6$&T6T@K++&<0P?SDi5Z*Txo*mvcNn;yzcLy~NQTse6dC2ihK&RzO~q_oF<s%N}#q zfpz%e{u6Qc6Ssl5@(VV&G;iIO>P~*ga$lSd;%H1i&}Znyi4sR?<@w^Y5l42;uvXKm zc6t9Gz9G0szk7oI_d#eUfe!<-FmA^2`#AT-z&7AnXzf4){*S;z;2#4X1xm+xeh1kY zJISZ!RsC%p`_^gev^}+T>>k>Bnc$=0k?l#XOAfHdxb{=1!fwmQZuE3Z1YeMR2?J%e z@FMl$$!yq_*<9+xn}_jaR&}EK_!9XqxJZ4dJf5wvg?HF{X}G?W(Y@y=Oh{t?a^8k~ zE4EK1vm8H2rG-BPy<<8PUD}8H!kM=8KTqYHEY8_@hCE%E%A5o9xEH2A(`BEd#aKJ! z*aFF|gb%QmJ%jm}EJGeB^M7<EyS)3KaL@dL%~P*mQJ<pqJvq!*m=brdTIxQ)x?y|H zB*FfY*XJhd?Ythd^U8f@be+a5cXrjG-@JVm(Z`v``7TxddY$*d9zc&~bhM_Iy<dCm zf9hm;>-O%-O6&vn-BDi`i9ChR>M6GmDCx={)ZWb;4?d<(ot)jlnUVO#^gXTWX9(Yz zNtZv7LH{ysb25njY>QGxXfbOTHc=b%T8XcJZtBM5v-lsqZ{T!>;1i+2$!97PBZ?~J zXOZ2#tZNc!DShn!)YZt=@iJ@x&e0iEvMD*T^`W%-{|w|xa{-d0arlx4t>j!T!f5;& zfF_$kd#WnT4D|)iY=6<}#?HDOJEwDPGK;y@{M#OO%15~Igt7PztaCj64ZbC_Mm#}X z`Ok%VxSKVlWB<J*Y0rzxPVo9g)vNkkeS3PmpdCLMb;CEZ9$m8O-E031@BSy;GpBEl z<D_qOmJWMSoT@?}51eQ8)_E##za>m5VYK$emUrZQJ#BXbzb*VEKT+RzA_kjR<2kS2 zl^+~Cg>`CtKSw#lr!kC6>5Dj<LuD!L8pQpK3sa%lYXirQiR#<O+f$*E#Md)o3R9-B z=UCN44sBTTi?V(Eco<ycd4HP|zx;bJ_+?%8^$BEMd#TE2=lM8CzsEV>Wc#Sx<Q|`_ ze~CPPGU~L^FTlU3zT+eBpXa%KF2<T?yGlRQp5F4{XS?TchKts)=fs`9R{1#2H+9iT zT3@y@NxYP$@meI&RWSNccPybb9#3@FbbvFj6^meFwQBC2`DKf>jQmvA0DZT7hDxu1 za~vdZ%EQg%CyTM4zPXdW)Y%zxd8Tlt!#O)c@s!5Eyc|WIBuAR_jFBgQSvt4&l_f-3 z^2on6+To*}HvD2PU~Iu4w+#52YFgbgkazZ&wf9Z<TV;@)qB7iakuuEl%77ijSZ}Pq z46?PQPqI25M5k!)yGKq+UY&d~2aOK#WZxez5Wh41Dbn)u!(RtaGak0<;HGE0bjFsU z&I|aCQ@o`P@VRWW`)To4e5<K+d@Ti0_y(T};hoMu(OwM~<Jn-hyhH5rGC%3#S<ovl z-z^O+?@nZUU^!TWJ(ll-?XkL7R{3c<d8YPGS?o4zxFq{t-zwQxpJ(qQY*GK@A)o%u zJC|fSelFExDc^_cyU-kHUcGvKsM1W({tE+6+Fn1Wb=d0X0-YMWvtEkymG0K)#AFsS zSUS8dUGT$a(f6&`xZb)SZ(Qu8)#K`uB5X6>;;apd>D)at_AAV%MzPVN(4wy0mhZy% zq0^O5eE6I%=;V3KZJ+HPR4EzLK1>hcH)ecJT!riVuBs%R=dNqkb8r2=;hh%GB?F<c ziLUpB$Y<OcOUXXZFq^t{E`$0JHq^)rTW#I-?<EZ3_j$IMtJ8M7IOBj*_V-rQQ!Z;J zX46M&?Nm8-OF8wt#SORFh4@uY4T~kamb<vVqi}fPJlFm;ngbq3d{1v{Oi|*7m(J}$ zU!I3wl+nJT{13yoqcI0h)?%ya8NV?+&*i5ux}HZU^}L8@zvJGUTl93k_WRUYYPDhX zaz=)6_vC{I-gjQn-n={Q^Ly}6>)kE#?&W!$8^+e{yifU1o|q@FFXbW5v-{%fDw=8= zYO9)S?fb@f?OHcTKcH}H8f(@y)K=85t#7fzx_IsSKAe(sk*?C$#jT;3_H{qVy&(6% zv|0k(HJGz!arh|h>Z*q7isr^uEfp=b>s!_}DIq;?exSLcxwZv*ylQ2ALw(Bw#>}O% z=bn8ljIm*gp8s!yde1r1dxvn2-cR`d?NIMW;O6`n@cnu};odPMy?F}%4&Yoksc`QE z-lX&h|GyK8=Soj-UM{~QrVow_nE6M+T{zcr@V7wGkHJsTF9t<FPCWyQE(U2tMJK2) z(Jux?Px1|q=of>~7wCBo@C9RL3%?i?{iHGP6a8XP^wT&@L>C0Vc>r9{!?!_t{x)y{ z?W9n2K@O+A<!#{2$ny=NzYV+@`I#yD#b6fCk%Q}j#cu;|fu9AUzYV+vnHF7e2ET>; z78LXAK!+}N;C#XD#&~cZ^qY4g4=$W5xC?#Z!dMaMC6EIb&Jo-VU!mJDMt=6dC!X6- z_+I!0TqrmjxDWma_rY1h_rnk99{}Dcc%Tm!3O`7F7Y58C;0=PEeQ>7mL)2$Mz$^w{ zFL;=-Fwbo${D?6#fVT=pfk%y*4qW2GTaOttP0x=5^LY-83ZCeLQ-vdkQ}Y65DR7D) za_GUy!jZelxp?G(`GTkW!=*jOT&L%P7Vs>_F7P%NmYg%@nsI!g>%!a4(_ez$W&*wN z>M_v60pr1|gl7bd2Pft5rBhbGcraHuvbLZ>KVufu!B=3BU>yF}z`qvw4sOFr__iLt z^IR|{xPkV~^M$Q_@cqKu;WzLDg5|)?@Oe4>*aDxy1!oC%0C~O`c%$HU_*q7M@9cv& z2;T)COQ`1rd<3_l@ZInexD+@;a1U@Xa4&oWmH?*-?gJJB_ro{fZNRC52Y^MugYXNu z3^-Y^6Bq*?f=|Fw;B|tBfwO@};1942c#YsuU?K1rd=V~KfOq1!F;@$oFy<;j<m0L+ zI}QLR3BG_mBZyphaAH1RL!35dVji%E<!^##jTsMIE|?2EXN)Cyz7M|F;$&<SFz*oz z1IGa~0_NSq1;?<;J}Y3x2}T0uO2Hg>y@g*9{ND_pi{ZcEV)zd%2F?>Kf$#0`wG6(4 z3(f)mz;fDoD|{@6&)|Zy!53G;XTciyy8-^y^}!q0!?y<b+XA2Bv{!J!ncyWY@K<m> ze2v4G4e%3Oa60(1R`@8`4y=O@o8hP67WfD(15Od_fPXdA_jdRvxD&orQqQ~k;I-w{ zYXZIr?uK82d*Ih{>UD1)ysC`)+Xue{_rs?W>g@ph5j+S)zCPFqp9BxVpJGl80a}8G zIWxB?VD3KR!1ANUye9^J%$Roz9>)hcJ77L^!hv@ujk&TA`~?OR1p!lWvJYMnW#;=d zwx?i^F_-5DOx0NjR-QBFvOMtf#*EGln3X1A!>Vw=<XGStjJgH0fa8D>W&i|p;Qc;+ z7JT0i%!TjZx8%WhU@>s+Uih64-}k`pDEtOr1iVSG0Dkj)aUuNP4WDPjXW$axjS2V~ zgU^CR@E2H841a;Q0Sk7)$Hnkhumt|@gpXzLbvyi94qrRqTRD6M7n}lqM<smS0-tK& zBXD^g?NG1*K5m9TaroE{A6np_;Ck9yYrw470RJ|?k5>2xE;teV?soWw{C#LMd=uPa zjMYNDcL3wS?eMLE`rZlO>Zspc@J%oQziOzz-SA6r4}7W&nCiX8Tu~0(51*C?Ow9rK zBX|&45-_!$@Ja9xd|DhZs}38JBY4D^QN;nX`lvA@1&;w^0aJGzSM+RPlD&lr1E&53 zW3mNL0t<krjbTrC^AA0YO$E;~F3As=d(HuKfhJ&v35MDH&<dD_4B$9mR=^AujL5d) zXW;t@`hhU~2HpaU9f$uJv~%D>;7z~}WWn!a@I3;bfs1qCGw@bm;ZgWL20jCqj)Tuf z;4`q`F#NUPFR(Nh{vLwAdGNOrzUISM;2lx;3cM4Te-M5az*pd1h4A$Ne4Gtm_ru2+ zeBB5C$nYfK-No>8FML}JKli||68O0rewD$`1bkX<814eg;U92iCH&h3e`?_0PWVy> z|F*-A2Kd(jAL8(D3-#Xu|29+a>)~5Fuob=uw!^np>U}eO+dzG9fp6=n-wycILVa$B zUvc0r_|*_FYZCCOE@0N~hEFvC)3^sdRRZ_HpYni-?*}di9$@~W4A{v)y(D1nJ!H(# z#R1cFnDe!Zfk%xQQWP-F$AGf~rscRXgA0L4V+Iuj%(@qVQQ%3&iuu4EV?ucWbKhCU zi@Ct_KnrLBCNM5w?hgZVfLYl7SwS=Jg=`Z8&S%q-IT=Ch<ZN>j@aEIm=6%3o;H+@a zEM#+&Lf|6cOyJ_P+2;E5@cmr2nPGxvDR4S?2_Mx*&%t*Cf5A(Elh4BMFzpt2M+W@u zf!|s16?hl$>eKK!0$)$U-yHb*0{k5VUz6~69Q-^1UoB&-<M1;VeuA$Az8kzc4}Knn zkNNQN2z)GnkB8x7A$&Xp-)6(dPWTpse+S`L5&Sy<pNiq%e)zN){_TTLCGc-A{3(Nf zyWvMU{7b-(O8B=6KGeX!o$#R!er>1z<M6A4`fh<=Td3dlz*g$D6~1i<nDy=OYdvra z{Avl92Rh(WJYYV&9X{0s%tv;?C&2`;JYY8Lfltc==A(NV>z4ud8(c#H^N$CBMFI1% zPGc_22Oc)&uX6&X^$73=;4x$VG9zF%9%ny;slX)gYT!v@-kcaP51s~I2|R1epDzcV z2WIoNqG235J80g|<}|Z`G2krVJYXSk{&DyWTmZbjFlcT8&L}_*PGp;Dz(v5Rz*~Wn zflHFvCO;Z9CBSR**+CPz$^(`GugYV0CFE+7#Vj`RG%+`5?gEYnUx7SXV}j;x<mo-Y z3gEkQf~FFAx-t?pE0L$M$RX8l#vpgA!tfKg8aNuctIvR+=V^~w@bR4V8hq@5pE>Xm zxoR8(|B$PD$HBiOe9WcY9fyB;@bMV@%ZHCg;a?Q~Avfy_;2U!D;X?R!5dOsA+X47f z1mE_-k7D?>2R@X*FXW`P41VpRzLA%}PGBV&?Vz6P;Md0kro90^wFS&WE%51M0rT*B zAP$^|Tj5h<z-(@ZKdS@gkuAV#@a^ztML-`CnKw!U=Hm(ABH$il&cXjJ`+)BYn8)@T z^E&*0>>v=nKXwQR-yb_-%xmurn8%L+;rAzw1L5~4lE%C`40sY40`{Q48-nJ>BiZH# z;QN5r18)LOj|a^hU=(~Fa0;*pm=C-ecrCCPm<Rj-@TwZ*;ApnV1ug|ntmLa6;CNsu z@V(37KXUbM;Bw%VWkK^n<Y{b4(3AtmEQasE%Zh`h3V9kG3z}-=XcVv(I089bjT}Xg zvwGxcIC9nid>3-H_H;J=T+qaOvgzM~rV05Oiu|-7KSO}`0S9LV&3fc$P&jBl412=J z$%YL0c$RjS1s{=<k3}FLCmVC%TNmwP41D_?{6lX3`ZM^2-2CMy0kbI&zC8=S^5NI_ z;8Owo`X+oS1b&hFkHN2hrv8zab590L$6_FIu(b^SYzml9E{7k;!L~|ZbHHq`1Ktxb zI~w3ib-+B)0=zR|p4`Bk^wNOYiF};B1-Jz`CtyC+0fg_L+G)%y@cpR-5WYXP2S_{r z^giGy-~k}~{&Xks0{b-_2EGD32K)o?1oj;D`v2Ph|Gn-1y5m7}9qls@I0bkWFbbS_ zB4}pNuE&GV1ilw|<Kb*G4mcY)_89sBI0iWH5bgFT{RA-Q2zmiH@-Y1aFaliCNqaqn zJ^*HQ(jNdb53+L;FyjDv061hXClvw*?V<exL%Y%Uz~C<0J<#k7ntuRZ_yp}8_}5KA zb1(4x$7tug=gs?r=6>Lx8)@IbH>!i?qvY@0ilAu)zP>bQ+9=0sw*<|@z*pZFG>=fu zSEmNe$I(Y;uMVOwvuQs;vlTt`N_Nm}Ll6Ba6f{pHfv?m4UdT2t|AF>&5{O>-r_;b+ z1k7i9vQ5vA1Lkw+nI81PKci=Qz7{ZFFns&^*?{?C25?)z{A(7F_Wz|E;Qax!7roNc z7%*S4fE5ArwLD;H!0d|xY42Z0pY)*TzY#O$<?90Go5jHQ2F(5v;N?K{$jh|vf2%a+ zPqgoUs{_)$zZD0*2t<Fp@@pXa<CR|kr9YkpqBqWd517Ed$_l~jY-2@2W)kq-IU!_0 z{cgxy2OI-Fg?hORd>Sx^@YhpsBY=g#Y@qs$cV&dk`+>v4Av2Hq9%@2n0dUAU>;>Q; z;9~d^>cKt$22ay3z(4bXBL{zF0%ryIUw(}o9E7hwqu&Sq`N#D4z&E~+-Upszm!CDj z*S`q=fv^2D{67F6pG3a{&we~;KEm@?kc*E2|AbsTD7YHF17EIy@4z19;W6IVGe2lL z1aE-fz%$6fljQFVa_}kgeP&qD{FC4X_)PiEoC%oEQ|_0#;4k&@68zsoJ)MF7|9S%W zZTOl5ei42mFK0dtA5Q{54*!soGam_<Z=L0R@crB8fbji020kwhnC~GcFV7E{gUHFt zGXmym<m69R1Cf(I!S7D`pFhFxALPT&H;s9w0C>ijXJ^CDE+GBQ+2?`C$E!bP{Sxx= zDt!JS^6}c&z#D-74BkRN^dxvI_Ht3kj75$wFAkY^lh4uM7H}l^MDia2zY6#+@M|d7 zF!0Hgb7(ANqQJqx0?Hqr9WplngN4Wg^%BSrnK{4<Q;`Si>o3=ZY`fvji6Prw`16$^ zvxItmBb(WM;OoOe<__xpwF~G2;H$4Y`rzyzkOTPgN|z%Ce|jE00RLV_E*gP7$VKx3 z;MZvXz%$6hM+CRQf8a~VL)(7fM}lUP;61c=;2)8LPY5Ch+XRt=Cj_Sk%~Qnt<9mbV zGlHXn=5tEtP590GUV{I71b+>m$=6FigU`S--=m$9?=xSfJyIU={Q&aP1K+<(`FlPR zF#qis`MxJ$zJDCJB4D05fn3tg4^h8=dSAf&h<bnJx_~(hKVG4o|NB|wd04>w<UI8O zzmJ6BC;a{?a`M{mjQLpvNV`5d27c16k0Kwhf7_U!BOm9!3`9QOfY1LK1AYRC{`m99 zfMvk@f#ulA?IAOQ_Y4Q-0JB;{=5pXr@Uh725b$>c2W<$M@#HHA%mteD=n3-s*Za{E z!1K)^GnI0@xjJNK0N<!a9*~#UE071u`C2LR0DN^($R1a`a!bhEa*T4{5HgE_FC!-< zs;8@2C8~NG#V#?xGswl=)aOfYA_szJkOS)ZkI2J4)cYTQfgA`viyk<bZBBn1Js^mF z_$YikjT}5E*hc#oY<Bp6x_SWr=LF5peWU~bcL86b{U-!z|GNcWr+ov@(C)t?NW0&+ zpL~8FJuLV&_zip+zJHJR{0Y84EqFhCCO@yNhR@{l74-YR1JBaVe?mE4rJer=<$4u< z|D5v5PXABp<8}1;vExAa{XF${4t^h3z5dLY|3Uq~@qNxT>p?$$&6wYu1JbU4Yp_SR zF&B<}ytxUOgPjVWljx80_ZX8xKK@bx9tD<y7ZSlBR9t_(5Hca)o1w571bhRWWX$Vt zhRiVFtFMF%TsLRWgv`kEl<UQixeWO7??UDZ;F;%<6W~ifLr%!gAD^W^5&UMzTzgjh zpdSJL;nN{AUGU?`2l@ZQM?z*c<vG<DGBLpl`VHji6ms$b!S{ujPXQtqw<igo%}ynP z7Z@*`03r`H)YEC{1?ufIa?l9;<ClYG-BIADu?MKvm*BtbfHRFj^APoZ=1$}Q=;{BL z;rot*l;`rG`7}`de&PW9`a{6{%YOLvJpDHCRrtMcAMnexbKq;+;P+nm^fB5s@Z3EC z^Q_>V@Ock>niDWT1^)Ru_$qjLz&sCpGZZkt7JLQ15&k^<O#}b(6Jvfah~EC6r2iM% z@oC=sSK4upAbfp=d|iOAuaeITtKkvlxUd4A9R@Cfhm_mUC!9Y9L>K&(dNLMc8tTy? z6XuV=EO7W^uM1#JKr@R5YMUym8*5jsB1G?cfi<;joJ9)mv+BCFy=w@n?G*%0*mzY_ zb8SWSnwp0CwY}>NwAO&|q+zF5Q{P;*vcXv!VXs4gR=sL<ZyxTe=lyF})l;P2XVp!O zaW6l0_p`i$h#tOL>91?5sIOVy8@{1&b)!euJJwV+-{ax;SJk&vG&a{%G*_)s9_bFv zA%5cm#^9bYbwOh=Pt6z_LY&`WelMs|&_u@ZE96(kFV1fZKfCVYtfNq(1oP@rn0K%I z+&8_VcCB6VzA(;n2Uj`#cvVeJ1q(MSR<2uRYHFLSo9g2&^^I$9B281ZuBEQA=_b=q zUtPPlx%Q?K>Zhr`wxz1+0Rs=#D3BJH)Xws5Zdw6X?zT4Y-)gR{wc<^U)mB|?Lwvj) zq2+;iZC|A3mZti(s{fi=7O&Ja-?XN-roO5|acY~J&3&~^YpPb)SKl;aN_0x0#d|8& zt!-$ms?jaPX0q9A&0TiueKRd~8Y;Qn%)b8pD<(DHJ*nB6R5Ocb<jQi_$XLzms+DRc zuhVlgdq)4TlbUB)3zjWgx@?wJ)zHvbUDZO~td_c3YvHonNYBcvZE9+4n#JukO5`dM znf(4W>z2ls)vj*t!<RL;nAtb<Ph0uW`W!D4Q%HdK^LUo^K;yb5i^{B8Q`=J8WI1(W z)i+x$jg3}A<J#5ZGfk!)vbr(;K*g%2#x)h|nh9xVM=3dct!}u-++0=PKs*Z`Th)}| z9^%$C)l*kfNr7>vlTK4@Rg24-+O;iB5A-Gl+0r5*FQ4Oy-}`Kp5??W?=59STrfCga zu&8yAi`D(wMkN!EH#W6c)20?!D_5_v?ysW`9O<;QWa$2?rdq2y{(usk{Qu!nek|Wb zeyq~6xn;MPW}4O2HPdRVr?cFRd`_D(eG2_iY0)BuzGK0%(uGTxSn#wtZ&LF$u}O%> z^yu{H<mima(+hBeE?Y>Le&O^gb4PtmZKJhtZG2tJEa%-T?yRqAsk?jDq#745uB~5P z*Wx~~tQ9wl!PYV=UeBgZs?iG-)=7(&CFvy1RgHF%hB&2nm6k2I)h)^0JXWSHt7PH) ziUmuGDv-;H`Af=X*$*eJBQg8Vrc?T5W&RKY=(jGIyQE(tKKjDak_x*eRNTDmR__fy zy52u;@uG^-yOzxN$kqV5^Zv4hw=S49X`N-=Ub>*dMV$IkPL)o{vZeDEl$KV^z2g>N zfWC5g^jqgH??+#8D;2YF$<0euEyfMM=$76(;>p~iBHD6v{iO9)>B0{#aBjUiyld)w zOLgGYwUdH%*IOekC%!fRt<OnUMPX65-oIjg@!Tb-hP(NORQQsmW!C&<3+9$BDC*6h zm*oNPTruzVn-z2M?YGYLvfY<!-P!MPbJz>!7cW~%1Uq8`gZBpV(w=wAt$KFRz;=E` zEt$J)u2ZQhgr3-!m&W{(yM(`O8Y=R_B@1;Ht{qSRV6kPlj9Iqku$)%mApUT-R;{<Z zCQw@c;aWo6uLdP;d$+Zs&TdRL;;Rd%h4=B_d0)lNWTLdVS1@_%lT9#`L&e;AOP3Ta zUE&k)w}x4Ids)ftWdxaf>w=19aI$~9B_-!tvS4{x#e(G}3+9(ql$4dy9AQU80|hE8 ztyr@3PFwK6$+`4WaaB{zozi=B8_N3%LPrbN-)#ru#*TgwsDjULT(hQXZOyDqkjeC| z^=r}dJkvwV*LhD}*Icz4qeC4p(F}TR=ujy)uE|z)UDevv=-s-tmKJ9^OEV3(6)Qx# zyJE%t{Ob64rC(SK1Z(ZOHA;iq-mp9(q{24Tud%z1mG&Dfn}NnOuUlyoDpoYEo!Yo+ zl>$%h?HTmKwY3dV^;!kC?d0|u1^4(OOjf7Su(EclYt&iQ^-a|cwU%raZtd)Nsgt&P zzuo{=GxAh1DSsMjeR?!%stIjBTA}}UlNa@H>YWsiY^bwpYyuP-o)-AB;f8&ndQEMW z`f{gp>lej|Ic=sfPN<3%1yc*BPMfLsDE<5DuWoi~#uCpY*e!K>E2hvIyFA#Xj_ivE zPA5WK+Z45PT8I3o-&CD9VQV<)HdoixYK?DGUgO$^2dq^T0NZ%o`fJQREp-&IVnw_W zEA9ajMQj?IFs5z(dWBGLte!Z3Wi4@QEmrT^mVo$Y7qc0nzbbeyHVTG_-H|J*b(OWU zVO`T4^2K8%=#MfWt|Pn6jr55%wJX=H=4GoI`DYu9re@`8(s$*1T~iZQO0THOR+13L zn_5g}ZB=!h-2zmZ&2^3I8fvVSWT{pLRZA_%1J>2~S4;5cHZ)u`WD60zBDd78u}iJ+ z7qe;BRIR_Sp0Uu1g-h<3yLe$yg{?BNH&G4wYinz3W?>)wBPxpo?67s%8lIga{kdSR zMbd`0IBV#n0^3%Y??~!AS{GEyrcWY_@433K-Z*N;Qs*^QEmbmvYuz{x)Y?+%K5^1% z)_B1cH^j_N+j&N-#ni0AHse*Mw7+Ebf943G{cHu2bhjf&(tU28>|z*)=E@c{I{;}* z=glu(V#lZ4d6>^`=~2v16&Mi}PCen0+iz96zHpgF($zv;X4(~pKC7{eJBDniz0bC# z``P`=7Th|w#JYLz!o`_}UKcHlhF-GtcC9&c>~=K?)!-D3(AKP5@7T~S?)VMfRmAJ7 z;k3<1-Sc*1q-%YW)*y?m1r26Rzka4<W}w}#GA*mUuiEkyH-@Id;TDm;HTUu1V4n^% zrjZr=sK{QONieVd*~-z=U3xCvB<ScF*5=#oyf?hstFImQKJRO;GSD4c+_vWluPQe6 zP50_2>1bKk?AR(R>swY#nvQW}O`2JgZ#7gkw^;F(X4|+@d2EgA)r~XG8gID<E-nGH zaP56`Gd0dIN1aH%Rm$K{-IL`7>>uVL0Z7N=iN_CnylAbl$7{|YhI&O$(X~y|7@0ci zy|;%iC|Wl(Zh}TeK2nsuBN6ul2D>^m?s4K)+`F!Jo#RKa)2(Q!UsKy;G`_bLa&t># ze99DiAVwVOtud|?R$xNk?G4EEP=WIm*J@nX;=IGje={S%>RMF%>iT940qudEsulUD zuw@Wv%ijRKV~-jw@sZkHy>>E6$W}#mT=_C4Gpa_kjd%Y5_ixFPRjSO{9n5&>%jER1 zluxn=8~ns&3rZK1S&o54P}PxzPXt+LvKX4zVstd<<rmYP@;OW<GXu(SQQc{WrQ|kr z%V6JA02@*p9!+JE-$iNLka#w9<JtEFvLW$2n&J&?uS-jdtX{q@mXxn-xW}stScbBg zjK$I<rVJ>D&5N6&eGE|8RgG&~6xO>J6Ll}12r3UM$9>Z$%dO<yi|pMix_57v$PKTk z-g8?v+~<UOz<VxVLX8ZCi{<t0<YquvH`#dodYm*E<h>o;v<=fY6wuMxydL07xmdfD zkI8G7#mYQaYXBb?@R^*%SUN6!qtsA^L&SEv*&*K9zi+Jg)yRs9dz_~I&Z6`S^~Qs{ z-&oV!P+MzT%l%022zhP&%h?qbRkeKRgnzL9KFacr;(38;mj3w73fz%?|Bgp{CouH# zuOGqx)93hmCy{(%%KrS!YWMvujkb5mM|=mj&+T~qcuj4Cs~O)xgaJW*w_?(h2y4T| zzhD~>_#)_2pZ?7%`8Da2DrEOvB*@=<l=$4^?`p2Sx8m)-q5GSWAzr=V-wxv|#c*EJ zcwcSB{Z;qWR;*gLwpxzV|0=HNp)sFGx%q!5!QT?*>()=MY+2LX>pOo-fdAsb!?~@m zd-A*P?-1bF4~Ac^`m-%|+oS(qyl?<{)3VP`bn8yeU*s6C<bW`L3+-$;jJFooxZO2Z z+*5lgkxBSn*L{2Cnss#lwu8Ca9*6#|_YI^qeEN3}A-@be22$P`{)-!S?zVMiMdQkU zsI6{c=E1QA-dS|>VAb_Ex$-m9HVWTiJTF-62S2#MdB28Xm-=?*hCY}-yZP^BKA9L% z`kPsj9~{${ra0XKT=9|8P1wJRUQum(w<{XgR;*=k<dyJm!@6fieDojcSFNhA#gYGa zTq_6v$9=2nG*#6*4!@*S#>^bH(KaB^KzudpO^dwaG+LH@?X`aLvu^DrNl@_dyw@sh z?Sby9Z?O&Din@2sjETpGyx32FyyKiZ0T<q~{!X9#t*T#pX=1P>^TRJl{;TWi;}m06 z<0ZcT@|^nAn)>GIOP74-MIYMzdHR2b6d$f_y3}_og%2)a8m)E>@^gt9cZ1*m!qT5> z^e^={eO3IDh4_ZY9yme%Z4GFDBz}q6SeQs%Z8!f*)|}3Zw%pq}$DjX8Z30`bne&|b zKgj@N_e;z@YaCwr&1gsd{yr1(eUIFea%xYLZkPOe^V%0aHc|PvJu;Ub-Aw-RnQzuK z-v5qljf*A!!|^Mh!e;%u?YCto5B##J7PZk#7i_EH+L{VE65ipJJ@xvlJpNVPry1c( zyK<|q2zvTQ=F6qUX7B&pXIdQouWDK&15%v8`|(cG8L{X5whCMNRyEbuR>T<xzvH-i z$DFqOUwS=<&4f!F0-b*$aV@>Z+G;j~s9tmFM#z?<2QPE`&A-e3`iGx>|3|jbyDr{4 zd;d=BPT{`#-O@DuXM7FYM$m-myDlZRF}JS&*S~7~L;Jt9h;Ha>a=X7%;h62~F1_}Q z*;e}8OK$$9f-X7#-_81P=pKpA-<5m(J5R3qC;AV${Qj=%k01Hmx_FbE=Cu_J0A&MQ zQaYpG{pyy#tK!_Z<TU^JdbNL?7nk&2FYw_HePIFiOXIq=Yw)UG`gQl8w{6DgsBf;j z^s?)16JGt782YD))k_)!UUD9Ck0&1T^xysUYc(--NriZRYRj<Z`ZaO<C#ZpzMy)lv zlq+6){pTF}+u2X%QsOG?6+iyz2W<PPruLHTPVYTgzuvRPXa8NI^~zesFTd+gw&uNr zKF52vAZ{poWnvh3fuDTV|2JJM8@=fMKG{@){JGvw_2j?)E8HS*j9)81t_)-GKgN$w z<@i~;QJs4~;YyQbarXMqi{X0aT?*^}dCvv$P5aURckk7}E%WEkvhr3=pB|ldV{~S8 z<~7#!Q?A#lsQ-Tv=3YyIY?rGESlkYpX$B9@2n-F34Ce$!2QCkd30x5v8+=c2f+Xba zuaGT4ee{qmeSTch*>{D^;68*qXXSF=qmbQN{P?gw#15Y|03SX8SF7v0STWy+a2GP8 z2H-gZ@X-VC%leftY+k<bu6`kcc4O3|LViL1Si)@z^uWG?M&U(suAq4@H^OuIDZE(0 z@_suV;n#DoKFFV50^GTr^mcnF;bYtjKfup>Kc67GmlM9+hcAXA+~VhjFP74<FDLv4 zAAUQ}g?Hxlg&#B04NeLw-%cN11wQ*aV-5nn^n1Xa%L#wZhs)*=ZUMdUIlY~T6Ml>j zSN$&b;r;m$Hvb4+7oYo*9w*UoznpvL3fuYhFuoc#kGseQU=Up4E8S<J3-7x!%x7FA z3m8Bxe+8)fp)P(9IEJ5;wCIO{R9!FrJon<QNB=$dn$z*(^ZAH9uaf~({88lHZbd+L z1u<8;WpUzXnkcyLo$#3^2Cnx@ve`w#+y<`d(jrdb)!<r3bcKueFJHEK0J<)xeA(tf zaNSE@1AJNVICzx%Iv4LBf7pQf$}*pJ({u8hHGn?K>~-lXqssSPaJ#%N{-Xi-e-6NZ z>&7QI@m{{bXTiOf*Ir9h0rusz&;3*SaLLahAFlE&pW2^Z?!!etWUq)-7)L&j_;Arr zOcza;LqF-mMbGM05Dq=!!$sG3?at-UH~4VT_xSKPE>hmTKDxpmxxr1&&Cf9(F1mGN ze|oMD7k#G>SAFgB;iBi-D>s#flixfaF8U!KuK0(2xaf87<DY#w@f&=&=%;<S;`jJ) z(K}|_k@@Gu-|oXjAESj;_T|vW`Ebz>&UMLd{G&cx^xZ}M>3e;+=w}!7(S?_LD6Nu% zJxn|JW&G5hMc>fNvtj0nUR~?RugZ6BKze02^U%JW{4e+6N^i_9F4@ihI3F&0i4Rx$ zWj@@_j}I5U)rX6|R|?9$ocHhZ;i5;DxMcVJhkdx{xh4JS2Yk5bCzkc6pZDRSA1&=q zKjy<lUtZRqUhcz1Kdny8zTEn|qYoFo;I2Mg<uCN%qOV`kpT5C|i@w{3EB+oIF8Wa) zF8VPaE_z-$|Ln`jU%n3)eS^J9Q~@0N9v?3HVIQvakN9xWtq<|fzMS~EK3w!7AFlYt zK3w!VA1-=>4;Oul4;Q_|hl_r|hl_sDhuiP3;Gumv`78F}qW5*k4n16H2j-un&ntbn z(y#I1ioer`i@wW;i+;R{fA;01|AG$}JyPwG-TIIEaM2I@aHW6Lhl}1&(?5QT4;MY$ z>#}g(pW(wr@9^PDf4dJCz0-$_e#nQ5zIPS>?8{02xDOY7%W9YGmaoHyi+)g@y?r_H zJAJt5>sgEETn>GM4;Q`sp8oVoA1-=PLw|a)4;THM4_Eol`*6{BujwCuj}I4p@!J0M z5+5%5VIQvakN9xWbL0Kv=lgKcot5GW<CH%>fWFs<EB$>wT=5UID6TFi{vjVO`jK@u zv6p_-hl{?i*K6;@-|xdkFSb`gDGi6d*oTXr@e$E<IrK6gE_#O#SN^yAaM62wxaenn zxah4P<)3{y>F@U8qMv@$CA;tM_;?>K`Vk+l^pE;*(GNY=7v84(aM90g>rY?4y$=_? zU`HRW_=P@P^bQ{``gR{K`pGBwXJ1bFPWy1tm+y4RZu!c6xabEy)t}z!!$r^gbboq* z4;TILuKx66K3w#Uf9g-)?!!et@tOYgjL-JrqWAc4mH(U%7risVKl^gZe<<Oil-H(z zt`ArILq1&e+%NQ}FZbc1XZ%ZldX^6tJ?o48=@B0;`j|ca>EnF3=(~Kl@|W=8qIdpl z|M-V|xabXE>Q9gRaM3q>xj((#hl_sLhwJ@Ee7NX&d;7<a`f$;=_;AJF?!!foe5HT< zF+N=MojzRg6Fyw@lRjMZ9v?3H{;%@Sz8wA^@ZolRAFlYPeYogjzUIXC^v^gSE_%(r z{`5K@F8Z!-^rs*3;i50!-=Dt0hl`&3Z~f_cK3w#2AFljY`f$;=`*6{B`f$-pzQsTL za_Xndhl_sNhbw-M4;S6~wjG&&PW)USF8b~R{prVixae8m=}(XNaM8E>aJ_%84;THo z4;TG}4;Ov$cll>uPX0=Kxacn&a>=ef*yW*&hxnY|2)~@4#z*f5-*0KZI0wHK{0O)_ zd7_ttCw+9b2{GruN4oS6gJ+F*d?E_}2>3YgESJvqL?+KiXZs0L2=2xI7WiUtl~eJ5 z2wv{P*+$7U_~NU41avR<UE;2@7kB(2;a+@{>C*dLT>cKWMd*jKeMUcgNT@$PY5@M; z0r+*`-sSl}PW$TrM(Dyd2KD@HSwHk*IQ+}^;VMu0kNVT=e7NX2Kj}}8`Eb$q`f%0j zJ|Aw=kM@s$(ua$l_w)Yrd><})iw{@&8+^FvhkUr`M|`;G<NlL>_T{!OA8x1b!|n8a zxab+j+~{umw0yYeMLt~di+#B04L)4-xDOY7&-47VFDHNdeYoh0f9;ap_m}%{(F=at zpT5|Ki(Z%RPfz%8(a-yE<<E5Wg%`cXhl^h4!$pt1&==k=zYn+LclW2)`Eb!U{JuZE z-G_^Az1W|g>%&El|Div<#fOVt`N#hBIv+0jJ|C|9@Au)Ncf8a;{!Sk*dh|?xdXWzo zeU}ec`UxK{dd4gL<7fGB(RaSqpMKtli@x{uKDuz7SM6LGW*PdxKEIj=(sxzhTc9f+ z!nMD~F7S~q{xR@<;FgO&0)EtoZv*cEAMVmW4{j#(>EEw|>%85|TzV(C&H>DJakizg z&%yI><+sm&@95VpBHGt5^IN6wUY@=?GN8N-=e!V3`-%H-rN8UX{ptIBxacK+?N49s z!$sfY!)^KS;i8`(fEQ6-=gKgr$-nRj4^-a@ud~sdYZ&{_^w<BQ_g$H0NVpGE`R(|< zk21{&=<C6q`pz^Hz#j*n%un+H{nHz6rn~92!telG>`x!Tc`SBBdyZiQTw4l$_P59w z`5cM<SphEnT|_Y9bqeoZD&xK2@^7jC5&gpoKOG(K;-450{tMu;rw$TV;lBee|5vVy zKQ|!!ufXL$Zg=TD;QOin#V#HiM1O$&E)!YljR2QD#dfha{vPn+7m#lkp8>A%PJtVK z0l56}Q5Vm^u#i73*Tp{wT~{vgNAOn%uJK5go8CuUy27YFHVwdc48XqtzWFd?#GsSE zZw#P!f=eHfWjp`B1lRbo#(iJ+fbcI5z~2Oyymz?qhY#k)y_CPpz~wK_=U(+S9bDtL z?JmFPflHs}yYE{8F8}Ztpu*Px$NUKyapQk@h?_V->92z>e{qi+zfJfoXZ}j@p8(f< zMTtxQBDk&%{6?C==36eVXG-r!;2M9&-SE#3p#K(J_UW!nCx0)2%OAPLPA_QwJRrOw zzZ#D$cGJrS&;3tyk{f>FfbvWSuS`(?E`1@m{DHe&yh`+Yka-tx9uWVd;H~7p!KFV2 ze*O%3aQUAY5PlE1=35eO`0s#ge!|P|e}HQ|SK`utJ0Sia!8Kp9*-ihiE?x7dBbial z%pjtBseZ?TA35GvzH7nNpV6dkeiwmjzOBVg?=J9gC1rN$jo{v;^frQPyzAB1li>1? zZigoRe-&K)U5_ho{|#LJqthr_(SHW6@mir9UVEyoC+`4SANzjk#=Z2u;85g*@yjmm z6@MhScZog`T;rP-?nS==T>jRmix-2-Kc4I2<>2x+?s4&T;POxIb@9i+qyM8%|9lbL zyY#*T;Kk%u_sZ`PaQR=OuDqp$f83ZDbmiwY@bWi#hg-ke&qDKup1iyld;{-Gy7BYD zW$$_Un+LA>2Ty*Nh<-oy6?W3E0GEB0aNpMiE`ONE-*)iWfAr~_ZQ$}(X<sho@3Y|E zr84aYm%quQcY>ch0MDQ){7=DUFMD_rT=uz_zgNKJ58vX3j|@Yf<oEG=9Ju_&`(1hz zJVyPDbMblL-lhC31=sjEhkLz$CAj>-8(e%nxaNO~-1^-#ApSOR&A%OT!|wst{P9i~ z-w(b4{V?0b4}(W({|OgQf_s<p^D4OPwWHiCKjAF;n+1LC<#O<&kI_ESOQK&5?p=yM zZ2&$KT>dk!J{At3mx3Qk5Ygq=ssZ$S!R0^fB#7R(0bKJTo<7++ApB>*We=6R;lBp1 z@yQrB{b#}DPma0tUxLfOrv6dscY({_Ug_emfbXhw+JxwT6`lUxlZSE&9VRT|N_!b) zhM@<%OZ9O%xa>uXd$p%Y;F_=A0<QF8;PU_Mb@5xlHC`xj<$pD}{7W@1{~rLCy%=-x zN5D0|m+!{k3NC+Ffs210+`E*YZw<iz+W`DIaE*7yx#j;2c*~EGPZyV-(|p)L(o+84 z1fRXGPd^SHj(mI^qMJVpyyF;Ua`j~tT>k3QZv1)RnjiAgF9pv}^yR-6T<aa;ZhGs$ zHDBwshb`ce^*Vm4-yPtZ5AyQ&6>#rT`M(R^N?9_vSNNZR7lMl>`~<jU)mXwa%pV8D zKMQ_<_EhKA$KY(r20zymMfGtd_zC*I4j0b{_b$C-Cb;Hninv$!MFZ$}fy?&v^79V^ z=<C7d?>y|re{=x-sR1}!MfP4w^J#Fk1uy+yfXjbT;-;4z5T30bZU0DzTi&5Wlt04@ ze>u4PkA-ghJaCQo*{<0x-%N1t((Nt$(|lBndzHTuT>jUni#LONmu}nmC;vnq_X__c zxW-evUHmKHo5`C6F8)2ONbaTEAMsD)|0MT{|NH>@|7z@fpeozyI(|T&4~>cxlco0+ z`L0IALuTgA46mqoJxWq~k>ZP<w164LxzocLoMGN$42_bEl#&b$jg*X5R9K{}qC~|f zB^eebB^4DF7S&`_WMfhG{p|fcmkZC<inV4w_qYG=-`;1Reb2e)dp;wZ>-QYP#Fy&3 z4)?2=Q`l9q(?7D_bHaYUY_8vrDvtE$W%GN0G20Kx?tEDF+aIquk^kBW`<85eFO%jU zlg<6nC6_mSBK>=1AI+C%CQr!DosGu>?fJxs^jjzFPoJ<4WOF^g&-H!LGvx309(^C- zw|3mG+HriXY_88X*gh|t`)v#MXPa#9FSI)T5!qaiNY}do+5BE9>-g8p=Jzz|_)f~^ z_ZM4^e~;|+kMa1BY_9JO=rjFYm(BHxbp79v-Pdz8KR+j%`yuIi^R#ECrNv{SN;cQK zYFyq6WOIFd+V(e|NdJ&*?mzZ8{(@}oSMA$=wQR0mrSY$oo&9~Sd7ck%l)bP1-*NhP z%TE93-!GrA-zR%g&P(UpM`UyVwyG@l|Bq#JzjjD@@yFlEZajD7pMR6h_0kHDPg#}D zANpLQ^c+85CY$?tGmgJUcKSzq&XHc_)j9sb6Y;#;Dg7h;_sHh=DRufxdwOMazj)X7 zYfhy9!4vkIPT22|&F^UrUH^MzbANx=_Nr`tFO=?AKP8*rA2qtZ+p@V{n793TZ2!^T zr#~yT;(U0nY_7kxDVX-3IuZZC3A<G`zt`IK`1YQNe^fU2Q*tiv^|EJfAFbzam(A~0 zQh&WiHotGlI{gP^^Lw#Hm;XuG<?4Hl;@N-f%AP)ZG++NkHuu-k^@JbOcLzPO`in`n zH+f8tX}#J{D`q7>8_cUx_$b6kN7sq+*B%eqpY*O`%9H}{;B`H&!so{&N~UM$^!$G? z!-Hr+kby|6gM^1ui|p_Q<L;of(A`~sI(Po`*`(M!)ey>}wR*DpSXATv$ISaN<1^TL zgr?hdTq+Kf9_&##2_$l>cpjWA(%w6N_KX9gdhYqNr)^tB_x#yY4oE9G*O(?rL(s`R z*LW&4K0HzyBJ_lEpX9FiZ12#e*yuE;G^%c1m5LC~ID<1JhQQ}jRGNOKy7cpzP~P>y zK@Ba1yb__(?u%06aKPa8-m5pFSk^`5L)Rku`i!$)x|}}r*WG{Nv~m?CI(I%-Y&PbK zy?*voL-BB(J(W9__}u-pIj!&Psq^QH%`+0&D~dgRw(*#G>R3g&<Mrl(!wV&!4b2D+ zIeY39ZAd>C9H?-rb9iG>c$h~Hzdw3J(mwVC4#m27Q{p67hA#EjYqSRI@qb!-?(F&E zmgml$Deh+O-1)P~gD?B;jt5)o&z&oLI+mlc;kbFGp}6?_!~9EYJKG=$#G}e(Hil8R z0`&30%QX~yk;|P6v$0;YJtXo0Y2{`W$zhNxHshXdtRT^x4CcEf+$dFp3paxz3SQwk zPkAO(9v|D5bavqxE>aYZb&~42+%PADg!dPIR4gsk!i#FprG%0RS5u-cz{#i7h?I(N ze1SRAVL?5BP@ZSi<E*JPHbIh9Ms_@ZHMF`Q5KdH3)eA#?<*F)+uUUWW8jX;i&h^vz zxCj=yk*bq->v`!bH@v)sVwE~LCuWwk8nPJivApAt_?>)UFf>E`MX^c#FMb-4sOy*H zT|MB)bPTO6xLzZ3srOY$@dJ=Y4^xsAFVZYY)gb_yKB<{jc;$xNgf@0qB)VVO-+QF8 zE@vI7uBYnd-FdW;C0Uk_ek!c_(Th=XDl{)Fb3w&4RCZCa@!iKp>4qK|?Y?pS;^{s~ zVM-FT_o~J$&P^#q9)F@W6mj!{L`vf#m-vxc!l_7Ve%)7YTu03=Od6@HCh@6UQpD3! zP>9EjbK%IDCm#PL32s9%{%9J6K2bcvbb7{{nJ4}A>mgiEPKJRG!iE|^KTus5rem&D z8PQGQVdM1KXKD=|QTf3mp{4n2VcHf?Zau1h{Z{Iy6Hi`;JW71I_hvVOo(TtHn)c*V z-Xz8eSEQbGxi_B3>7W}I^#!{n&=<N9<#~?IFa=j%?!R`Sw?Eaddh(;_p&ALOyBS3j zn96uqU-}unSC5=|)P_*8R^6f(1{6xOc4FFzAisdXzmD<VtBH<_!V~o*NyihZwkJKU zpC-_%AO(Z)5Pz)s(aYWJjJgLNy<Aw1f=4YeK*n_FnO*Va2;H|r?k^A#-#!q1j_Xfp z?nXgZ%^8{)7SSj{K-t#Ey_hQf9;=V{EAX&!NGKz8Q7OaA7Glb<^c-6TV<koFF$u$w zAg%XM6b7j-NRJ?{sEmg^P?!nQmqqd9Xptv*=+x2jNzl<-8mJ_$4=DJBYC;v4U!~)i z*9M%BZXkWS%JP}TK_>wn-&jb@g!&4HA6w1X3zn&n==j{?9L`Bhr<KPvVv-svtXs#1 z>G6EXEJ5CjkA`Ja{bW5ZsKXV?4w{Qc>t&&osAw!Pw4*+U37M|=NMwXAg({*O3#TQV zf&|P_f_S{~Y<(zC@hqXm%g-0o?jSLR6)neML=;>!b@34^6P;uW5DxJqh>@fP5bd)W zJqSnHQB#g0ixgDI8rP0O!ej3Yi6d^Y77~Xes`y+T=F*KD+RI)jY@nHdLEtJZf1%_s z>S|yxUU_9mE8e5w6(6Bra+5Ss`A8jMN0E*JGBX5H5AVkC($_2bx2u;P*ZLd1KF~XO zG0q2kS2%l6Bsn<|hVx)p#wjmUR(LfDA;mA~pb!=k!a2^RZ2cJTBG4glr2Z3Tsotw$ zMV@2AK4}#v4z;5bZ=tt3`*nNQ5~ni5cx<s?;vIQ1?UH7(o!Q^djv;IcLJ0Faj8obJ zpBVFxpVsaoB<Z`xVH`F5LQ}O&P%x|4g)2d+JanBeb9_h-nb`iY!#?JUkchr&-x3#f zas^q~;`PvTYcRYvMcq=BAtyo@aZTVIE}=mu1~>$A8ZYch<ZkOgr45XSd0dB+<1$ku zA!lKA4zr}7Vns9|;oKH>rbS!dppuoYD?znSt4#3k2@S7M34_P>>3VnUC4uRZ=LOW- zb4BV4B*OiyxP=*7*!hIMN2};W8iztY=Y=o5+U6W7no%4hR_qXttWeO+tH&m^HYKV# zJ<Xn2wDbLiWjpR<eB>9VXPDmUc|28iOM63P$p3#x#ud_?*r287tT^Z6#=N&LNrmrN zqA%-s#Ai`GD16im4ug7p21hSR|G8*D<(eP>9JUFPvXqoxY>G}*VKoV6I^}g{4Bd?d zoYV~@BL^%8Aba*`b4I$-r<Wq>Jcd}|G0np;b&doSLyqu;CvK-t?70d{S)8#)?_JWj z84ls}bQ4w$AHjuPMI5wr*=2?u+b_m`-n<%n9lrO4AdWMRU4*+s06F_Ey|VXae_SHM z0`X)aNxDKasU+mX2#bYsOVqZo<{jIHrmNreOBZix^AJw347zm=DU_L1_-Y?Y?!Wf9 zBy0ySUA=fKJ%JrNMCHqnE_F-s_%Oe2US${xjpQ(*qVymPM&V0j9ITLm(^B{lx;7YB z$8dbd(F+;VspF-Hf-enu+H(FTKr3)iK~HPNXN5yQ^p~wMv0>n)IP`xCpT;6Id9UBp zW;$Gg)1Jl+jB7moO3wzxgDHXUIJ-4bQH4Dcmpvg<OC4cAj+Rh@(w>GTPlu!CI>A97 z(3{dCFY_fWocB=<46QDFQw{4xk+klURC-BHmvBwtY<_IJ$B<iGIJO~t9Yb`y_@t4F z7n7uT5*2S@@zC*l2q8x}cD?G*noyB?C1LK^@!ozplq#)pZg=R*dGUFWtwv$=<I3*o z6R$m&R>XS<nXfMm_o6d;KjEaVA!j~alFW#u{O$pJwItjd%luMlxNn&0C=I_wgWNaG z%<BE#V(GW*J+1JrB>Xn2^lsfZ!4|py4F|-`^Ywl_c(ycIhI+5!CVY8ma@*X8zpZ+8 zjhlKZ%sR8#L?<HD3srtQ{HKycSrYo!>2Q9dPkawl`}%D2-ZsMf%|Ua>Y<`OB{~f(| z7Jg}Ic&}ULrF!qU?zIr!55J-`$*N539Q<f$vSoV@o|b=~8sn$opOqxdsxy=ebz}R$ zc3HXXn|hxlRC#moJN4dV{l*5n4gQDT^J<&l=49l&CXH2yhfgTp_Bzx91Wo!)M~H{> z^1JPIsBvwQuR=VO6M2s;_B#By%GW*q5D(>?W!vkpMZaOtJ#pgOVY%Lm3)f4NI}R_` zJ>-nulQ{vEZU*W>3hotSH^MEwr`GmHU`f)cdy&Ksz(-1x9ozeGM7Hkb5x)=DN|G+! z+rsXL&r!VXeW>@c_UK+uC=dQrX|ipbdqNpK_}-&?CBzRxO|l)^`%v?|@5>zz^`6LG z+Xt{wzb$=sj30vM)K91f?)M$ek5n_&>JL;sBk)@lZyOPejNUg{3vcOt+VHhX2bF#T ze!MhUg7=jsD=;g~m*>Rz8mI?I#%)i-pH=*GV|)g_LGiYy;qyw9@=T1chJRI(jM<)o zQ#$_ciSZfuu=3lUhI-Fs#aB2UE-T*lH2g?OQuUQFJ_~E~9&e}zW%A~*IbqJ4OXjAz zZ<f`>{MBZi*=%;0d2`g9GUv?|bJN^256#N2iuGhop39-#9cJF-_v(aCn6u`Rxo+;5 zhi2vTV!k@F+3Ya$=CC<o&YDZ+y18Q>n$`EZe6!i?F!SaF{7`AKVD6aZy6H%GgPAwS z%ms7HOr9Up*P89-kU3+nnYYcV7sPxmW{){y&X{ZFo>~6YZlBp{j+hJPhIz-Vsg3zs z%>i@DTrqdd%CB)fX1h6NE|^;;B1-tJ)@(P2%o%gbOujCruQB_e=F=2>T4}Nfb^Nb8 zd=u&<w`-zjRC>35cVSl4DgHP0+ZB=XT?4kx^NmpF`DUo|Ji0}k=O?g#OzRc=EzJXX zy);>cdJk^qz8KyF72X5y*E$9jKMwCzx_WW1B+0`6EJ=Ex%FRQSI|h}19x6Y&H=Mth z;SXs&gL;2%%?lNOQRh<={TtHlV5{7HsCp|KMAbVDRqrfR_zG0Ln^5)cLe;x?Du$z% zLwVcS-HJDxPsjLnsC->e`KHYksCJ{L6WRmS?p>&M51onmMxpY}LA7HCzDMh5F6Ki| zhy3W~z~r3bwfV`y&z2-Z@W<s>sClpjU#IizdGQ}gl05tp{T32#mn2j0eHt&@=<87K z2K)`RuTk;ZJRO=<_sjl6`B^002)5ceWxL|*qm7OZ@k`iBk8Tcj?i*q}Iyu<r;lR$O z7>@o8_6qi8wey=q_3yTc{tff8=>dhST`lGS{2#q19cq3rnCRh<eg&%BRjB#CX0Dq< z55{`-;fCJ7-4fI9h?$S+`1#ftk3J6Npku>65xp9SE)5(u$HmMw&DYi#zAECUE%@{D ztGRDhe0vPfn6+k;*>3hg&F?{T9KKBLb^L<4Y;Kyj&9WD}9y4dQn?0~W$EWQP_+p)( zY)_kW=8Cy)R=*^c-)eT61LmYTV{VwcW^G%{-*1kabLNV<XC9iB-x2d=%sR8lY=QDy zhuH_^w_(RmoAc(rS@uvY7hNF6w+h~^aW^w&jhQuT%{sHe%$bd5li6&xn5|};*=}~2 zoo1KWWA>SOv)>#r2hAaK*c>rO%`tP_oG>TNDRbJKF=x#=bKYDq7tJMe*<3MK%`K7R zc+WgEE50*^XUt}^-Rv<(%}I0CTr^kBO>@`0Z628A?XJ(vij04)S!XtwIjDKkXuHX5 zHe1YAv(0QbJIqeA%j_}x%)Hre4w!@HkU4CQn4{*HIc`pvljf8;ZO)jp=A1ciE|`mE z%S)r*hRrE+!`v3}(=OEdya(mi+vdJ`VBRr@U#4>PWgHzX@}rjp2gJ-9bsmM9H)H0M zId3kT>*lt3+e}^_^H-WRW`o&b4w;kYg1KyNm^&uAUG#6?JTUK=hi39{Ojl->n-ylI zS!Gt687M#0*v^`@W}Vq!=FCR3$!s=T%vQ6_Y==+R^%>ivBKwRrsPplzi4Iv97m@gR zsQCFuBG=7^SIC~zxQV1ke+;5C2GJ7><$P}}2mLVWAAyP=g_=L;hGC-*2GIe7=zT$S zy&(EsA-+2@>51$yr%ZITNVg4D-`)k)uX$B=F|tym-YTec8QV2b<D4~X%{mi(Ez++; zmD|{-yxQ-ft3~(#RQR&P%Pz(6Mv-*rXORw_EVxa${JRG~Qxf#C2uBACZi?hX_X-<* zD>y9@zG$Lr74nIMqhp1QUKK=_3Zg#+(V2p+*Ob0q;|gD`@wbi66!GXuL3E>F@@l11 zd(nvs{e%if7Yg<~rub)TKA7l15x#@1cI}z1kH_$Sk?RuE@J~vTL->I9lS46mk2why zzGybylKs89E(3o>`&c-xa?B-j)7&@9U!!!o-k5>9{@7%8!cmn66O{+=);<<$-mIAi z=AnsR75%G(AJO+N_-(pg3QwsXcwYN$xTAeORQg(|c~)mOz$JZ8gLi3v?C@r@#cVex zpvu`dH-=+7t6m$~U=Et-UXgwbs{C=N`X|gubIP1Cm&D8mw9kj~!+}}#I@#LSw?l<@ znR)n=`u<`rK;>VD6}sMKmj6Js>);>jd#TxB_P}>&9}AU#94i03xo++`zHB7MXU!(4 z^GPez`KA-9oI%G=nsW|cwY_Ur{$R|Xh033U%HIyvjyzPm2cha2fl4<4m2Ms?-Lma1 z+jq>$ABy=hQ2FYh^0h(b8-Xf+0;>FJsC4sC>DHjq?U{!TuYP?DZ#3JX@^?Yy?}y4i z=J+{t&D=37MwL$ET5Z-r)z=QyuDm%2RsJYc`IAuPFF>W=Fn1lE{BR7fF&m-Mci0{@ z=N!Ifd)IdIhL}GKRc`}Sz0FYNbUA+5Trk(6((gmHzv4$CtD*AOLgjCPYImPG0_BHs zbKc=QP~{w$Rbw$-joA!UP8a;!lB5r+`~kS4_0je$RJv`m{70ib2$g=;_J(-?Y5yA| zYs{S4YId1<sB(s&`Y~fJIDFgouDLI=J{-Wib^b69&9XPe@N%=ltTe04YBOWjm|3&d ztTP+ToY`nLL9JWOwp+|rv(0QbJIqeA%j_}p=72e54#THwUt)XI95>gY+JU|w>DHj^ z{Ey48kCY}mQ0K4lH;Xz?t(te>pO++C6EVE@C&V$WCs5~~VfcGGP8`1N@Ll*VT5la* z_7>T1)%pNc{v=d6Gf?HM!SPbP#75LOmzz1W&m1ww%w_Yoi9R9yI)v(H*`%m>P;OR0 z#aG&{GOOW#l_VLc`BUTYtXXU3%to`xY%x1bbP%a$P~>|*x`)^;Z<DS4M-SBXCG-vn zN7oSUiCibEe7mUYWLc=|WX&e}hNN4Dx<1zRj+lNFD*Y5x`b87HL(<nl`J(|U-=;`C zhfw({r(?c46CFhItwZJ8fXavdA>n23RC<k5h1m#ySLYSjsdhMg##}QuOmq?{XBW!f zdr;$a+uS$rn8~|he3{uIa{s6gYJQGF)jtD2s(q-rWUiW<Q2s}Uk@{C=%%6>1ez)Sk zQR^9eq5Ai8;)k`a!e?v!ga5AkOz?uvXYkjwuY>hE4&WzBl5O~>CCM&)O!pJvgwB(* zqV|zZW*by|4^;dVlwX(3P4mF4{P`GPZKC%`KWZW43-8i>awvZ`noVZ2*=n|%9VYsa zl-Dk1zCr!}g=lYxnIG2qbS~QHJd&>S7h`xo%;~%j4|G3NBpy9SI4^QPb`{D$>+plR z9tqX|@?RD;j#W_OQwKGUZBX%j@SjV9{v+j$$fm#OJz}Hl2+?nZ=rqD96WvAZ{I94S z`G3enZ;|jl6a7T&IgxQ+hF`1wAAF|f1$>75un@y*p~4%X!rP$o^@)_Th5aV2YriJ0 z>3k30tbGWq)xHDjM*~ylI@I{@n-%Ykc7xew_L#%wggGrz?<~Aa{eYSW^X7uNXfB(p z=EVDAd*;j?sP>dEMrO@66Fo@k>w&7T530Vr*>4V*Lnb<r<ZBZ%3tGo)k79pP=Lg&6 zzb;#T%0YdfLI06_E7+Px=sjYi>j<00jD!!{%^|3DViNwhejj2kL9G`n@Lx-k4f7DH zzhz62HE>enX0|%K-5fGU%yFpi!PD@Ywf_-m*CLdEmZ1EzY_6DV=7x#RB>9F!+B0IJ zFG=_`RCzN{<;|LNCOVU(EB`I!*Y)%ae6jigKc(YJB);tZvOlZy9&A!P{9^5A;jgM* zsQU)9@GtfI42MrG%bwFd8NNmS`hckK-+6ei_M1@UR(?=a{tl@7Tz&9+w4Qz_#<#)s zlB6H1yb;Jcvm(A%`Jl!<4^{qzxoED#pHcb`i$AJyhN^EHs=hl=<y1c*s{A^rbWI<L z;jOSu>o3&$Jp-?(Ur^~+q1Ll)h@V!)cj|bD*HsRDk>(pz`aYObKcLbt!0*#_2@!wq zL9JWpM3!n<s5Gn0YBOWjm|3&dY!EZwrS%5BU*8XH57-{IJ!N~=_Ok6Y+q<^+ZI}N} zEUyZx{07@iwmZ`JkH&OaGiSD#9cB-Fs=l|ux5-~?;-c1Hv*mYXf4ABXb=>!x+feiV z(5(Jgv>VJev(Fqcr_4oj-P|+Fe=nAU&L;QKs^MJ<gLi8kF|%f^S!XtwIkVAhGSTOx z+}3rKsc|_l%Re6NS}1?yp#0GfbseJW_r=H6U-(tpkNtrte>6bFcR~4M(3~{q%{BA3 zS+Nn*XU%3aZ;qKW=DbL|7oq&I1m%xqbH!XW*USxb)7&<9&8knt_M<yW`CZsr@6j2> z9)eHT`H67#7kyE}*BoB<hYFX!G9uwMQ0cn}m;VMGKIHHT!gU>M7QS8U06e1u?USO; z3uRDtAJqPL3Tpqm1hsEohw}5LxeF(ie>29Hi?pKxYCl{F<*zCze^r|q6TMR6`^|lk z<ErA1BC}?b*=gp@<Wowgc~oiEm<?vL*=`O(`D+TwKj@v(-g&5YEI|41&Y#BmtNu*9 zN9%}4cso@34%;)tYyKtMqSm(z)VkMcdk(%r<L2-~hgbZ0OkV?)e$@7)c?T+A^<Rkc zcdgkd(#|F*e>R&fW~<rom&%vXbtRbB_oN;1L5(}qJX(ip_nuk#S24T+K3DSwzDC!P z;E?7$R6AD99rMtv{_7ZDYc`u*W?sZ^{ZM`!gzCo-R6mBz5p&cWGsn$IbK2Yy>Bk|q z%5VJ}+3%PCP4r@^=Ky<E*O7K(x)!K*42bNfn?D`%^@*gvgZ&5EPycO9KLV8={a5PA zi_Fs@bIsf`_sj#cY%iv-HaGtv*0*aOm}UPM!>i1!nKN5VbY^Mi9Jc!3aa(*y$NxWx zf35usR5*IGw6_nc{nHLdXO{4?&nVr)nji4vI#0tVv=4zA_Yo7_S@KUp<=Z4&{ojM~ zclkeynjcvc9a`F#gLmtDmf2)Bo5NyeTJscJ<+kk0ez*MkFR|QNbJ1Kgx6D2B0P46d z|JPVvCshCE;T`RBOvE8G5)^5Gs<+>qfl9vt)sNd|`M*cI)@(7m%pr5!oHG~A4Rg;d z`)n*PYc`vm=Ab!lqPL4*=AisJ59QAVbJ1Kfm(5jk-P|y@%pG&j+&Ax-9sd#iF$(36 z8FOBwJxfsSS%zxQin(g8ndsq?{!rxl+4Sec2Xx*sEB{lrzSoXG)iY+IlS{rCsCs6h z>X|d=&9?tizPD&T!oSe{mqStKtv0ChRu9y9YYr;ip5rV3JH}@r*N>pu(PeuJs+{D1 zV!A4*bXgOfUfS0Ib)Fj|d`#yRcthjm_<6{9LG5q%iPydtonG=+C9*%K`3TkjMzb0I zw$3~7Sz2$P)~NybDqUBEPw4oB?^6BnX<FZ*{H$$NlDSKMhAOvAU4a#527XNafx2$c z?C>@-{at^TZ2aE?)sH?iZw^59V+d+}7>4TSh~r1iF~^U?d$o=@e9D|LYiO^=p$^Vy z9|+aXCa89{L-nK6>=CKI52}6miFWiuwHtpCK4=b^)$kcA3x0W$)WBy&EuPY6>$(lL z`oSONl)>+p|B7wZQ;scGLe;}~miB623O`vA#<TQCw6Dijzq{ZI<VW~N+Fv={60Fhn zXLwJ1KBM$GI=-+!ukTg(=kN7j{f%3%(zAi0ULhTrPd{C~Hh8K2^3|L57j9nZ@4N3x zUs5kkih7<UiJy4>q{u{;r^vj1Ej+P>c1U=Lu|5V+(W&}eD8Vu|dT^$o8WO6A8L5ow zB|-G)wW}8|)fbCq)L*!9BdNc5O>dBvU_*Uq>x&+G`F(mE=HjDC{R1!kj{4rgC_ZxO zhC2QK{Clp_$?Zw0(=%VP{tOs5{!Z(kyq7!`Lw}5Kc!@OBUz)C7pP#0G&HBgR-kbFu z^@Z`B5!69C#+>myR^I2eMiJn@w7f>y#pO+XNZ<LDPE#zDm6rDs*~R4@${KcAAT94j z`dnPz+=}kiDU9;yTUy>D`b>GLUxrGwM|hqB{Fj#Zu<YXUDnDEj^!O-`ex~JJ(C6av z*6%Gz-mkFqFD>s;1&|JZ^Eaji=9j)Ke&&DD5&t?fZC~!3{Gzb*FD>si3Mg)0quN)k zFxtnln6~c?`dr+;7L_-m<2(IJ%X_QSJ;f2LttH7C8U2^0`w7{_^|q_t)X!h4xU}AP z=`-2W^2T2r*Hi_CzqGucmQ`HdlFFmM^aJ;#<>|6i@OxU`!b`M<e1Z0TQ0WL}o#Bsk zYw=_FpE&+~)C__8Z-@oH=r6TCr7+bwkVcX2>rz8Z)4_Dih@Mrt=KJ)$PM_7K&=2}W iU(-J5W3qdzB&@T1<}WRez89xkQz3sBQpEq#bpH$6<s!TQ literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libacw_mpi.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libacw_mpi.so new file mode 100755 index 0000000000000000000000000000000000000000..ed8428a10cb137e3ef5a777b0685726a1846e60f GIT binary patch literal 14816 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 Fe*?OIgt`C# literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libadvapi.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libadvapi.so new file mode 100755 index 0000000000000000000000000000000000000000..8e9762322b4757c760573fec51acbc5ccccf7a0d GIT binary patch literal 114960 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 Kkp&g!4*wgYlBZt) literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libaudio_codec.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libaudio_codec.so new file mode 100755 index 0000000000000000000000000000000000000000..af115d2b7e8d62b4a2ac9c30a8786fb928ab57ea GIT binary patch literal 812896 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≈(A6L^b@H2l)ffD690&C3J9<ue5?#*TrD zdJ{Zc-#?=<La-k;!#j-A`J|?I*E?@t=}6dzFM@;PlHtZN<9|Wicr5bn^JQ6XLdUch z>XY`x{4eAfQy-di+4<VqIi61dJ9N-<1J?UNhC3k!tkt_loZ#n7=Jr3_)05UQM+V>r zvY-wLQ+d&ksY~khrH(;)x1Ax{`K^$9{YNd{{Z-&6oUxnApK#SdpOsPdR~<3k_%qo9 z^6Kf%L8ueWEYHlRrt?OD!<+MZU(#dREN#4LuK(L+9j>~ZY-fXYRr0SP?nwHU^sAbe zTi9gHJ;PV0nA=LaT`xOCKd!>|R(Cm8ds6q;-c{(W{IQLji#AI7o<X|jOZSJrc-vmA z(*!-`uj!7V+jOQ)?YQGpZEk#z6#tNLd4M*9NAmx-(ZkXX3p3*I^T?COzALk5@m~6u z(2s~0)3^<}`L(QL!V)iaJA6{dI!)pr>YbU#PG$LseH<HVgQqcGpSE|;MVh~u%;$#< zHWn+#f$lGf{UfexX@|Bdqa(y;;BiBaZF`Z;q$A|FZ7sN3=5TQB!fyHenvA!$Ghj(G z=V8)2b0W+k?orRmc7FQ++IgaPZ#$<I?R4k1dr1qp&Xw9`dZ*3g)1ZCWwN^fh=r_FU z_U!O%55m?sx6y;YPW^6e{<EIe=0DQ^ls0D@x@x&k@(nckydD0u^W{6`hX*Pd&>yH{ z`zs%^?6-C;y9v2X{Q#b_9yTm=U|zPN+bO5Ki-*4KfZD-t)yp|vvAwjGQ{ul8e6Xc~ zi+$^aYl6pj=3LXL=#gWKN$}s3d78?$-iN=x;=phRUeKsce{qlwWnVhc?(b|HnNNM{ z(4UTQ2d3`NU*!IHZePDA%~D(g@6vvW4l-5Z={K77SK_PPH6~V`w?k8Zdz$mpe66y6 z7XG{YkaTwCwp8Yoe)sMx55IT##GOyKPUIe;uRP3r)Sk-TE!k-dZynROw!XSgzayrb zjL*ha^|;kLdlJ1n^h<kCm#?;d;BSx2chA)6T*_FfKl<%S;lc08WHR7&l7U|g`9pt< z|CAg3_yM)^{{#J*7x-&?eh&Im%3>#aJ%v3!7@e7l_KylH;eADlfewh~KL@@4`a$+V zywt;~`f_X0msXaaDg6gyoKCv#*hO9UH+0?af|k0T%1oi_mN)Jyb^YgIhgumoe*?F= z9ZF@Uz|HcWQ!jB#bS><!<6G^_WOm57wr+>M=Ql&~;bC*8q&>FBeUSBbC-Wz%9CFu5 zA6^FE7ZbxC2z}eO4_KXezc|y^-=J@u_o>Vj^tHVAIM(TFJSJ`aGRLrS_B-Oy!CH){ zt@TV|PwPX>oib))+^2tVPC?weXP%wbFF)&DbFJ%kJGSe_*K97{o2<9aY%OP<0{v;Q z7o*`h0QMwcYaK5dJN}>UYL3!4Yno#!aF^cJG5<HAuRbjCps3dcEcMbjKg|X3tNnKF z%{gV)&^NMQ)bUaoPv7~I>5b1aw!O6&-$wjS*|FRBUgA&qcB1pp)?43|Z4}Rw#qec4 z$9cx`UkiKCq25Ypy$qRI(d0f>=(!5otpay>WbC%ge()P}6dS?8F?E_RfKKmV{z6%I zOtO-)OVZlE_?|t+JpY4^JB&AtKYVtsS$_KL9uEDR&)&b_*mFg*qSr0p>|BlSuH|gz zeL;SA5A)5ud*;x5_YvH{`$FEGcMvz{Hf&S<jCb2rpX1%O7Z&ffpKv68=o_eDsoP~* z=zEzKHlj=uu64^X+g~8>(#SiTlz-(Y`8e8A=HT6gb*$e+28Aj8wBz>G`-t95UmdGD zUlx5azii(;+b`#K<fpuH92LBpBR(}=Ee=?;JCvX0)o^~6S0g-&&tmX-Dfno2d>`Wd zMZ7zv@!dI+MZ6E^_YvMt<K27a7Y|hUJNILo#+dfUciT1Iig(*~yb<rVU-nm6bzTXt zo+iwCns7~%7RtT!DS72s$?=T5a-F&puble|UM;1(eP7z(?o{T{meN<pCxN^9CGO_g zzP#!*ruV#ZxlW$u5|Eeo(`G!6plj-=cIso;Bgfc@x5%3MYkT6aTzA5M2C$Sz=Y`W; zZIdw~c)2fE+&sT3Jja~}0&nep;7!%m&zkp7;F#!9%wxU@TFm@8(84vZ*z0kyw0KSj zT9okW{r!35NsCgJV*X_zvZUQ?AqV<C{lzKF!8k5FmEV=Gs_re(PJI6K<>~(4zr-&p zf8u#mp4(Oylq3A%mh?=zHb=Xw@AcVqbvg8B)5|xHeUkrpH~xy}?X(}yNj`!5L+);! z2CQxRe(p$-x5hn=i=1;1zmR|0O#7#WqmQ<3?ALp1_M6(jV;jJrKlG2jGY&NkTphEz ze@s8Fyr06}l2e)6a_+%>2lhSP*+SdCTi*AS&u^Mz;@5L%DF(>vKQZ64_D9njBmIr` zJhm}TxfUTj?Yz2W>~J^zlOEw)XSoN4ckX&l`)~E@mtk9!ZE0YhzG;wW?K%3KzT2WK z*`I_zxCz^}DP(ewWo>6~EO_38IX2eXZgU^a@r}*9zWAR{rF8@S*=+Wi0zcUU*E)<d zEVH#Ja}H(n#ojfa+F}2Dv|Y+&#C-MhiTVTUxn?QPOIj>W>Fx{L>(5%mh3=W?Yuq&c zb?|UpqF;_NwC^e2&uRKg)54Z1bH9k5+NO5W^<W&#gorIqv5AM-oe(s{t?GESwe z`e5AQT(kWLpZ0eN<hf%x`KKHyyD1(;2A!YrUL$$hHPAiUXq=tSMHt(sZ{R|IV_|t| zJIbFin9qJM2z^NYDDMHBFgGjCgq&$D!#dJayT6z|iKp_?iN<}YooXHR&uaE1<}>T( z#g?)Uf0(`D)A{bNbnyAruc*!w_`D6gjk|n)CF$}-nJ;<kyZm2DndF1PLm7V)K2O@& zcjsF?Zy>+bBl~zNeKg;^_W6gLcOrS}gym4ndD<%1=;lBJ%g4UoG|$8t8|-AliTx+- zIjpi=gR?D;^HO`@M%xo$3WvMM^M3GZFLVRA(O2#XPU8yk@eYW|@a7Cke~Ig4a6><* z>Ql6hRobIY1}&xaC*g0<2Uru@Ec?9_n%fU?QhwE2;U-&4pOqtdHMgreSJcesGLFdS z2<PVaXXp2U{63#|<0W;!Y)?85(MIG2?}K0F8!HY`*M3N!;f%w}@DV}Rg`|h97)zS2 z&#Kby8-EqPuu0#Jc!g&Wm+ZW|ao^ZIbJmQ-yJJ0{V?U&E?eE}c0={}1@U@TT{|ouX zy_N~vr2W;Oyb51qd3}m)&!z2Oc;&>l<K4D>F5CW<+_v<v-`k9Zx(XOg?&2!@v+cgI zU(E1@=d<u;Lhm0jRvqd<zY7ccmAa-~tm`Iwq&n*+Yk$e^ArttQ&SlV1VGg42($4Yo zAL_$bZf@gz_sD(8zjQAe-Q^m+eC}rK={|wj!_`e)$ITzI?zT$4+jNJYbzTX>n8EtJ z?0F6P&LmFa+yJo%^YfX`%4D0ztd9h&Qm(|^F}vgIPCPfw`6t&Wk{rPMkO99pGXTGi zEadN>kiU4BXFdmx%b?Nsjr)NaGVq}eGB5!qGB7*C7oN`{1Mitc22LnsAoYKw@?R6^ z0smUy9`t{K^lw$``)xX8zn5aP=zsIEhXbFz^te3fM7qzv_0>ej=-&hMPdnhd_GYK^ zZty7Plfoyx>pSeLCEmJw`k~|ZA9d*X11BFk{;e0IBd^;V>stR?FUC&+Yh8Z6jypJ& z!v{z|mh_8wzKHgE@%!uZ^E93}@Vo)pSx=sR{F0pK{>Dprw*GXU_3b|Q@qAr(&*)|3 zt)q^2Kt%e+p7X~phxd0=&T+Q(U=}f!zZ*%{wz_8O?}_}*HD1MMlzXmDAa7GHvw&aw zbrJXvX1tC?UhPNPTRFOU%=}?|*Zus?c+RGszTe|n?QNdfTE0`+Xl%Qh@|(vFN2aeu zHr%IWyWEp9&w9t;yA#h=KK8Kh`t?hi$Ts{q%D9la_F<awG{4aY$J(|h9i@+cM1S!b zY=eC?Hu%=b)mTE^m<e3tF3Z{nXw0~v(l7CGKaufTH~le&dtCd<p8Hq2mk->XEBY>a zB0j>d^raey{0s85kh)Fmy?H(>TibJ4-<1#Z#B&`yPc}aDFYy@Mr|~_DdrnwW&71Sy z&3bJQ>$djUdcvHd?v3|#s4K6dt~4|LD)}m{CZpx^r#Bu{o}9xe<>?AwCb<Lu)SqT$ zi=?k|_`X_x!n;=H{gmm%pAV3JA@*b@wDf=Zan;=C)lWZ__B@pR4;}v2QC0i1<u7z2 z?wEHe^x6dd9ZN`S^)bqa&L&wcWQXxzzcP6HeD`ZnFT*m1TTJ~@cBPv-LJXMZ?8|)k zI8XX`CX>A}Ne7di%XEqJc<d)&|4myD=Q#$+G1ad3F^+tHbIk-=80R+8sggeG%S_Vl zA7Z|j-`*xVhY#8S{_E*`1KI5b?vH0Q9>oT;7o>B0A0UpnDADTP-94k5$38&&>dACs z&+fmzZuc|A$N1oIXdU=G|B%L`6WUmG-R`TPv29*RpN4qW-w*RU%&+?RO1?qnx^EBP zHXO<6>g#Y@Umr{Qs;r)j?D+dCXfCgoQQqGeAE^5i`V4OBv^>8B8=@_!w|Nb9B3;<p z27lFif3MAL>4SxJRp>c#a07KKo3UwUnSL|rH&C|4uW{tf83)d8Y<ZHslgoTZezlRM zokJ$?qd(hi*SUj#TD)eAa@efTJ#72dQ}66|8hi3=8_pGWYHuy=4N)g-q;;ePd$aC( zrt}xCxX9CxKgW^wH+<h~kvGSxT?5>qHn4fN-?vWjd$Stz{BypqKzUE;`Rp8Jcinz+ z&-jPA^P?%w(8@H&x6&`trlOy|=ECQDFT|_U|2@xM!+1n{PF&l#I(@TG-MR-F>(fTa zGu{#QH4W~CL6%cH#rW?U`X*jqE%3V5K7yBJrH8WE%FpuVMtGxqF@{e*cW%y8R?i_X z<X0U@whoz1?ZT%Yu@AxgzSAo?KlJqFNuN_bG|~Sg-eM1;{Yu}>!)|V4{%zs%ofjSs z9U3F)e<QKIYjO7da-QwGX^v~`KmLjF?&h&K^fw;u?LH>?1kXq7FE=l)=H4!+j66}7 zO#ksyl~3;lPi<r>4~z|#Z(YB;d*Hs^(XKpGzOA3+9NF%tU%jV8e|$D`74w|mGL3VS zdrX&?@62(-AD{;lU?Ed~fSrrEH+3b!JAr#yUP_G2oQrssb?zHPub^)adf<6)^EUy* zdeW~>U-{UPzVxvL--Pux?8_G9BE8eMy9e$YE8DaT{kdy@W!^ylg|W7#6Sto{JJCou zzd&2^rVYP&U&3RbI)5{Jyx!jYBF6W*<oP9hht#&Oski-N&Z<Jsh~Zx$zjNQ)WwTDJ zAAeZVL4L!dXm=m}H$V4qSsq(aonxZC33Mpnm;EmL7j><tF3PuS(6OJDr{_cG2{>f? zBri;F1)Tyn=%hY$Bd`C4yxziCuf#9)9a{Xw@gXPsj`co;eD~3J``Cj{I@j=z^VTF; z@;&rbzF`~iYsZYgi?+n4ZbxqiA9czzgB|my&rUYhJoWKz<Y+?Mj0ppevR(cDS+wcC zTy3gtaP}a{ZCf6KR<u#__h8x>%KZvnei&Z%WjjHP#{STcvv$e)J~r|!=;mI|4UbH3 ztRiz6lVjUH*BZR+EpJ`fbWNRleMcTM{(fXrdvad3S=P6YX<jGGYV<i|HQ5&UHWwJB z?Xt~#xSPPc>KOan<#XKgvJ$#nF>w62_na`dk@75O9BbY!IS(83;AdOMPw2<bU0#uc zmCeeI-t*JFy4$uFA;0KuCwV=qwI<1jeU}%>Zlkwl*;4m9$zinrXGQz%az*?4{I)!1 zeoWSWS+;C{9~mtAe{IozyIj%!1X<lr`(@d({Zd|=@Y?q#ayE@QiHMb)yIoJ7aZi(Z ze7~RY+w}dy<M7qZSEc_;$iMq1Pd#d!ewk&l{fzCm+{1d7V~YFu{c)Zv)z%q%S;unD zZ<b>U^R^lHGcVTN*fd(tJMuL0nwv&{JL`gR>6?E1^rQ81Yo~zm>gQK5>UB~&YZ$_O zRR@^YOab%E470?m1q@{*=<NKaanc3Qz_H#J7G0NY(#geGYyiCr82V<*akpqHKm9P~ zC!kM>x9bwx^7s75Q;()Oj0R<-E%YnP9l~0M<<?nldZvG^jO!hic}s?6Ec=D|?gzOk z;rSMDv##w-XU?UB|LVV=_&)u#3J>kScKFBLjf7v!xk%%7KapQ;m-d<d-zNO2%88?E zcYpowRXq1u=qX+6vh{pqOIXTOEAj5S-JgXvN6y}y=-N&{V$<%DPtK{7xQT0tleh*B zn==kuC&2-GyAKXq!Qt$K!J&|Y<A^y|Ptq3mI&CR!oqj<)S2wtWTzdi^tXuZgeF3H3 zV&}Iw59FBMeiG;Iac(Ex&!zrq=y@)EFkji0Z}^Ta^>p7YW1IWrP11+wb?O83U#(0J zoHuH_`at7=FXX<o{X_V2;+`)^W7fv)YdgQNpLIGJ`&p;-n-@>vJ3^=b0s4i0us+Sb z5BtiYci!C3e4x09w|bU%GfBU0rC%Yp-Se;8eXD&b<fXeNuikm{K78L?>b)NuJlA%# zt&Gd&!h^8MUje_8*M9|Gbvf5o%d^{o75&1N&$}I%+AV+O_o?XV?agYP{k#8G$(D6G z^?wEJ*!Q*{E%+on_b^PzFZg77+y6~cubp437d-O*y@YqM?*IAy;Ow1&6L6}v9kSK# zQ?2bbPLtGY=hy0$IG+el^_#&5<_J6bh6(zabxu7!7uv}y_Udlw#FzQGk8S-Za7}fg zSM;-8rogw84p~nfQik>ye??#2_Y-~Oew~gw#9p<w9aSgV_)Vb~+P1Je>Ya8d+Tjf9 zyreVIYrwmk)+C)F-r3Slrw=zjkJy-fJkI9|V=FfG%P(4Pe3N{+&q?2ikKE^A8Sf}q z4;_q|jF%!m?c=TIH#bg*aV`L#In1HDH?Ya?Qzxxqp5y9dKfTlD64G7gThFg^t=g5( zGY9l?@R@_3j{6po-}ZX^WO!*~F8+sV4dq>|8)^4vHP735H!wY`*oD0<<2><kzSpso z^D?XXb-Z;6zxsLm?3~P*(;I2b75$#F{TJ+QziexN?Yx;eW#KDB+P!T>%*yyG#VO)d zkAot{Ir+y`yfjrz^_*O0+kRrI*_4};adAE4t{?A}XKkl@wT*+Bf8KRDawg5xM`^Z! zdh*hF^2@SK+Gc+me6t0(cQ7^&ne7DYvMdjESif3>brZ1e1lGOGDcwPv%KSY?t{J;C z;Y~b)zrcq-xDo$heyPLWojncw=aXmodfo*5=tt@+@tJ+SckY_8dyy+;Deh#d_dVw2 zKS(S!6)f>BVRh<z!1@hf-HR`q#l3!M9f|!x`nGuYuJ87mAu`)u&w~!cKxuu@`1f|= zUt=J3rNLd^zBd|s*K1=hSbe|ivGCA-_T}H1{LYl_*kkW}Z1Ox4-mNDtRW9`D<}1&Z z{SmgyGUBj<_`iCt+HWEo|Be1B|Jrx`g5NIizJ&MWc+__L$afAQ_T86fVf&B;@iV`? z=b~Ol7~*g%{f=kHBR(^hOydLTQNjqCbh;}eXws+LVy~1t@2M1C>`jQc)in1xYEw<~ ztas4SezRvS?bX-L8s}I}xQ-p$_u_EpnRJeQuq8~(N;mgT_`S#XG#`7|vd;gT=5N}! z#=JS_)$vgky?-U+Tej=|Eou3yPgb#z&qw8F<5kDisXp>3FYPyW>Mrpq;Y@~qW8l1< zv9I}O?ZYsAIFR<5(BMGZvaEDcze{?VZhw<MB#wwX8dm+NqK|wGTw<Lx`tCW)v>&De z??Of_8~bMV$2;3muhfZjPbItwotR2iZOe5)V;T9Ebg+u2xR2?kq<hR?^dCzZ<#9gG z%5>5_>Zbc(;PawR@)CQBj1iDq?^$TlZ{=nlGz!{;{2Nn<ONuFK<qyy0qmSPIC>}{y z3Ou|cF!7|&m#N@B`9tmTUYq0{f$DnDE^Nh8_Nmm*gNL3krTr0LNW(#BILNcKdN;Hh z&d(#6ZgqU$4!)KT-LdaOz)La(J%k(d(C<dyJTK9yjB$c~+I^$$nN(*NlBOLsEuE7f ztwq{G(zbIh-QVukiOH@2lXdQD{A^yUL!L4c`X2JqRXZbtf9(Gjv@B`s+>kueZ^-kI zos%*RVh_PoG;pt~`*rQhg4{p%1{kl2ufO%aC{yAqe4ph_Cw#q!Q8`z}#PJ__Pcn); zl(s+i?7xM(tuNsl43{3kcZ#{&`U>_)8voiyWkESV{)x&KEMZOk%ZrweeXI4*m~r;Z z*58d^#y+~FbI{@n_tc?BXXO2u^6^sA#C1uQ9r^D*;Go+D&`n-TuS?n274jfYLS~fx zC^IvUYwqSQ)plAQ58cfjsO_{U$9<;TIY%fxv+rRXP|26@FFA-d*X6ya){8x%>*nv< z<~sI?PS&P;kp^GNa#W|sKtYfHuW)-1+#+VV9lmKJlqJvqEYER^v8D3p@A1T)$2%@7 z-oLxZIpuS9VRvr}83?;u?=v>0EdwQ8h0)&Qp5-C(<#pt1uk<mVzjzDyd4|xvf4;BD z@5)8cKJ0ECkJs%74{gxG4EM|qaJ9Rs-}q5&)BgIcziG>BmSN>dd*#`d#lWcN+waI9 zBHuHx_H%y5XDGivrvrYI^;>^aZ>Pj#n0AIU+!-C<+HY-+HX+$X@OdZYkejhHkd1G@ za80@+NM0@lR&zxAas~0#?~XqOkDdGUJllWdI^K<;JPFVFzB7_+RqOl03%a`Ik;c-= zPy8<T89g+924kOkjKg~6o~g>YcfO2?fJ;mdj=*gW{BDY?J-1N8FxIZ`)A&-}BO2#& zB4+U%tb4PUHvQ%T=l7sN-Nyb6K3sZfV?BFR+F123Z0s`Vtc`sxHdY(CVj$bh)_wTw zz55Evbmdli>v&eX?if^mIY`~5P5eHz|GR&!+E;FsFLn2a(6>e2>+=}3)cHm5VNs#; zzK5MK76{$49r67vGG@O1YiWkR7Wnrd8@6>Cc0$~=&D!bk57$voTcph$AwB#<$ZNa{ zNBL4GJSX~#%F+OP`>5-A7uyXu#yU}Ne{hB-fuk)E*ZZ;^ujBo;gTUK!PU?H$e#|6o zN`w93UWe5;39P{X9`FwyFwW`71MZLhnRxJh<)#A<qHXt?b>g{qcL%Tb$MbrBckHK4 z@9tJ6wnNJlt04=%D-YT(<stmU>nW>keQ}ommm=f;RM@hal=m#4_G>2P{*H2<nOg`< zbs*xWf5^I}Zl}G8x%^jh`OpW}^805FJT(4N^vb&GoA-tK>wQ?v`|PRbPb>1LVf)m{ zWH+f3Fs#d5Nty>0XZ6suPI~G(SZVtlXV-0??P&W-TDcadJ(70Xs{67nj4?>v7KR-p zh8=VNrFKo5mDc~*=V|=DjQ16!%NzH#x;O0*%9<AQ+?Fw4{WINl)<~0|ro|k7q|0~H z&n(IslbaUn1W{I-YWk6^1x1?n^bqJA@y`+9bWe_VnE$@bXXy}Q>B}Fh^uWDg=Wyn^ z4|v<@w|Lvn3RcBu`^WZ@Jr#_-<MH(whIKvv*nN66PVR=6*6D5Dl<fGU#Oj{ke-%9H zYdw@`qx@)}eLql~SJiM<PXlN9TfwSuw*Q@QUXo#0H*mJDI47FTUo&>k>^14^roJhS zYxpIfJq*Y~<CyW?k9!{Aq2!N<jk$l3@doLCMn4_P9zj2)pR}}}Nk>nt;2M(%H^s6U zuH#bS-UHlbhI^8JNL)ArvoP0DH}sQ%i$3xW>M)m;VhMc~^LhR9!#;_FePYg#Z&g+} zUI~t#ZLZ_k?mO*u!qL9l-lu7=9LI+ad9R!2tQR)jqv5!*8n3I{;ynvl6(^sSXMM5H z>X3SZ&ZT(XUv<I#k)9v$*EwWqpj`HWhp|A4H?RxZ!h4w8wa?WUh+pX5*jC+ZE8f1l z9|Cx3Z`rZ@1|3~<_$G581Hierfa7?ugp<c<2@d!qI0H2}U#rcf=!XM8=c(@fD(f-G zo%}bJ5C``+oC8fAw=bp-+O>O_^Hx5!XC<v;d_3G?&g9aid(ZYr&tYJ>UZK75**zT6 z)#sk!>TGJd_mVja?a7F3W6Mr~)@5ub9@6?rXf40AA#twVdd?Zd`BUb)`3Ble<DS9w zSvd09Iq*u495YvE6&*h-XKC)US?wo0ANuK=rHye@i?W}7VYMIEw&kxpd7SxN&uKdk z@W<JY`OU;u=9%>ZuTz?9#@C(5Jvjp(8tt0@;oaWvR+bwAuJ6)aU!e}UzNi1|YWD2( zT>L_D;4Yr7BfyinUDpr;eow}IamL+vJkE%BgWt=Ip($fKev?vN?`6MswMK@V(ylc2 zoUiRm>)Fgr3qRe<-Kf4_Cfx&{&8OG!!8eJ=?2LnLNmtGojHc(JZ^TXM-o&y!;@osD zaTa|)m3if=ZT3prHuxsIpnJ5xV3PKKWMAQ5r}iiGr-WJb>+W=yb3y0auWwHQw@$m4 zz`MEh-@b5m`L5t8dp9#pC-2v)N!tI?6zywYmdZEjLtkD&yTpo#hWpU3=<7e{`<>b{ zmHYaM3G%|(gCsAk^Q1M^N?xR8p>zHA*S6JrX|LQ2@vP4IoMOuStUU-`7+**q>uQ_3 zu~(<07^3o_-rM6?H`xYkkvbT<?|we-I?z7F*z$%iOm8e?Bhl!yrZu+l-{ODkoN0~K z{68>zTH_-A!-k!U4O@-BIJe2XI{xAU+HWnZY}mQ9qwNwWpS4}u4WG4L_A_jkeOpVq zwrdf#>jIwjxvpjFKeR!{M*0=)f;6$e(GTmdwmz~hEvoUg@hEFD=+rAR@53f(^Q3n< z=PRv~9Kw5SUDBnBKUI7?Oul^4wh;67>&wJJyf~-Q-oL<{$Gp}{DtjlMZF`6BGOi7r zv@7c#N7q`|L+sulGNSy6o3VDR;}iGI^F8jV2e<x&2V=Vi?fP8SUCq1wS`9x;*EYSu z*g^XQz9Ya-vOqtGGj8*nJnp6Y!9QnQC~MkrjnQ3Sm2Tiy)?uu0n{z=c`KH>C_+u-C z=Qz`Ggn52%ZBdb@E!7t|N8^0Y9P&>g-!sPc&G@g2d(6F4SKEpB^{0MdYgZ@T!Pc@C zq#aA^LiEYLEu&q>BGSw_ak4tj+en9~6LjuGD{+v=$XXA5pRF7!gYr&2RECuk*KxNa zCnc}W$-GMSc~)+f*HoUqsJF>qQuhn=ajr1oRjfO#AU|YVnQoCUEP3u&K|0EFpY5}{ zY(9KUK0De~Pb_Eqrs0eFg<I;&Rr!pJ=~Kz*SB$kg$f&fNOyADapCcD-eS=p)^OBC8 z=r4U7OGvB#jV(*`r4Q5S<7B+)MBj6BpOyLj*@qX`@ulrLZxU^5>o|2gfX`^#0cf7? zvMFgkH^)KyqxpH0(7dFb_QyL@Xy-0*?Sp2<V?JwR)Qis^i5<eui~(;Yx)$_Po>r!E zl|1>pKN}Kt>v~c0>*MfCUP!Co#7>m5EU(2+`&`<<Z)Q8umX)Br{h=R^@T~*;u$4Zn zq7TtO?R7lc-of%BeKUc5UHjw3(?94e|E1nzd(xQ_@sPGd1#Nwnw#IR*6Aieh2001- zu}Ar?psnX$EYr5%&11$_Q8(<D`>6Dd>XI?a3Diw6N4WEjvbQ%rK7L=|J8(t2J-*9Y z*~ah-8E)9pI$Z4U1h^Lf_e&XW@4)$Oxb!u_wSU^ziY61|j<w+H7)UyYE_8}J?*CjB zcN_)KxC3D=@x@wrenFEv2L?Q!%X!t;RPn_{z%#zk|N3lvp{@1V_+l~7>v&d9{B^vl z5BK?E_PXiQe0JZPerfBXhsNGJd_MO+i~rLP|Hb0v_^V1*wI3tt`M&Yj;0u&-{j;%` zV?t$Do<#rjQ^r-V!Ix-%^da>)%sUXwo6A~7+=swC9rKenB|C52qF?TNw30vVJ$8Q2 z+~!TmUw0SjkAu6i*PG8_8gm)bCcN;cAI)?6+IeG9aa9+s*G)U>*HhY@mCTROPs=&i z80G$*v!_w+iLg!Fm8`!C+>x=gZeZPV{k?2sp)!PD7^ID}&)M5njOE0sZ0nzjw)6*{ z;|lyHYh!lN#*qim#<p4;NnWu#-i0V#K4(5SJ0>=U(f_N1+NLP;$F(xXw#s|>p1|2X zor$K@m0zpT_fB~$sjuvK4y)&1KXlCp=(oDYJo+ByQTMREw?{m+6UN<+qgMhu^jZAO zyMVm8q^q01K1rRhEuHGTvtB2|S^#|UM_&6U)XR7T%wM8@r~JV4te+8n)PL0^@S}al zHA9q1<9YDy2j2;F%l(;vV@_iXy+<B~PHO`OI{9zrG2BC@tZev~N>`2NS5f|P$JjL= z<N0dmKBCS$iaM*QGXX!~YX76Z6YwO@*f{bQfNNLl#AK6{DP>PP@Kfi@i3964;o3r9 z+q$kyXB<lT{z2BMsdQkxR^~u-KsjFtuF4W|#e{og7s9Jj2Ufukb-*!(<1J$?=l86y zPN|p6Ns|uA7E)i?H{V!De3p<OY1T3A6$Kp23FoDgz==BQU%(02%G&dUrTwNqgTw^# zL3`M?Z_rmeR+p<g^IegqTi$j`8Tk%lGh?649m>_^=|0LjCSN5i<WL#~eT)@M6Zh!L z1bHJ}TQNb-a@u6_^-f|w`yTffZTOSQkH;Lr&G_&ez~|;B_+yW5q5o^otbF)p@Nvwq zAH9X=%^5G#^modewB&xAc{f-#uZ{bxd>ePXr}@~!3;ZqiAR2Et22y8V)K!gx>hjNA z(iVMWH)ESk{JWOxuV=lg@x-Rl_)eyMcfWM-GxiEyQv2?*-yjpGsmiO1%9wny&yIH) z<KJa$-|qi_G%5C3)5mq}<FJf;>jKC6I@uoDw$A}Oe81-=ZlSGIcVO?giral)AJfIa z_nvWSAnbDomP}ZK6SgoS&T)K}>>>CVe;LbG^EJde@L`>>npIqJeif(eQrE;!`FEb& zI`;iD^j(@<NxHvR<=<=gwa<<(?6Wc<Z={Rwt(-r1lKjQwUkM)8aW9K&GqbX<A4+-N zkwQLrx~_lNp2~I`Bi@nbMz7!Pp3H9M^sdR}hAH>MN2+ool)H+yy#wZ&jDtA)%zaTi zN9dz-BA1@PyftU5FQlIn`U8*GHJ20r*`Ld+{y`7?`#j?#c~X`So@*n5{?*v4S|1>m zNOs;>b}40+@mtDT$OE=>A|9EpNj|VWrCi7#Y;L-TQ@D(=uy2*_DQE5pv@Lb?XT@7T zI~AUF{_YP?``ro8Wf@QQ;7p)zz@Lo1%56#KH_+#)<o!>OBY89vnn1g|e3m|4JWoTu z^;>0s&6m!Hl5gK`KyH+8WkVZL`S*L%7^<ZGW8h(3_3dWcaGeSG#vw76yY=JTF#zBX zef8hEVvWx`<tPWAxi6f%`v0A~`e!!9Ve{C7S+;$yudh#4?>D}m<DL%nnzR@9FlRcX zc`;(K6w8|iovN`zYn1T^V;A)7HTW^lDD=@c<$W@oQW?r0+Md7M7kAHQ%mtR;ah66i zGf(^Y6}~tyZ@bTYT*8HX_s(kj-RtST1^B~wU@vaM`DggyUX5pGJQB{>mIh<Emt@;g z_96VE-*=2P*E#tfYxUo@{SBJ=%$~<;`~#hz#;(qxPx>(B!m){UlugG`rWu<UA0(f^ zd(0_Mqp$YolgNQ}O1U!q#4}7^f^Bk+p7$5=T?h8(-sYY<cyv3@xAVNtZ&ft8;~E?` z4pi%ETRBJJH$5#ow@I6Phj@hfgGS@}-Iqg;F1}5?wRz9jwLLw22YF-KKV|#dsbAr~ zDaA+PCcQ$IZ@6K4;{lX6_MFGJz6ZpCbwTgg=xKd;cOSTDv#ne1OTOUur#E&WbWz_s z#l6eg`}Xt^_$JquQ#{~Wwd=Q@ACiXhdL}r^3+7-yA98U#?>*d+cYJH}Cryho*q;ZD z1Eifkz_`_Uf_Rr7Q5L)KU}Yn!yRD^pnHP5`h>Lss8r&xt^wM^1mrl?zWckppi<8|^ zu4i<mvqoFA{hps``{>rhJHL~?1i!F_!ZHSumd1m~@B~_h>~>nizCO$FFzr7JKWJ<h zaf!e7Zv%6B`rJ36E6RSvOwvj^VvBd_=ap&o$b8m6(mek#b^Vrx_CY&lygW!9%h;xM ze3#Z;FYnoz?MuHjbN*b~o7c@8QJHVw%}+89{43C}uv<Oc|9&F>!T0W&$!4YR-*mnF z{4~x=?UByhSxWC_F3IxOB)PnPcZxNU%Y~%<6kZw!{e)lRDED@(tCee!{!}jaID5k^ zcPu#S6VmrM2RDz6h%@|Ae$>H8Pd=G+ZAPg>_kU!1<6CRLJb2c>eBgq$_=WHZ^?TjL z(L3Ac5cjy>*?kq4KmByF$I{V#D8gL_jp8o%NHgA(ZVM^r9K=HOOFN+5+^C)noHr`Y zWxll8*sR7XF`g~k_ggA&?a=<R4(%`bIkm6M*L`3oKT^rfb;&juTWIfp01nD#$cr*K zjXZ2c@;&Fm@2F=P`8w;cBvbuehgSQ4m|ID<{<u8miT8p0uFfiRo=Hr;AAEgR&j)C4 z3Gqa{+x{!FT#it`i&&wm3qI}V(Oum+h6r2Y9uWF;m;BM5#Msnv7`)BCx!N!GL;Rn< zwXA!Db(_?s{)BN>8snZf>R2@0gN%<d2Hw!D=KB8(e`$M;@r392LwtMa<G<%vqqND; zrW$LL|5ozFH_;ay#mRY7`I)|*B#hniXEeo1!Q*#hh(jNYbt3j~9z^<)P22*FfaP}# zK3Dnl2{6Jg9-Dnj<JEij^JsVE|FiHd|IBx<^;ydJ*5<uq-2?ZIZ*6Ypx0)xHzQZT( zeSSrLJ`P@An4b@0zFXgZ3T3;|9cgnuI9;FiKU}}t`+2nsXHZ@mge<yli5t8t{E@!n zAD9F00haA5OVT>#kN!2snGbPJTX@%>QrVm9UwYm6EsZMeW5>ZK{CsNfh1@&JJ{a~y z?fTz`HBu}*kGo*Z+mY+;DC+(Jb?fy$mFvBY`)=kmE=&2|$0fb+)w|Ya8IY!B-=0O^ zTn~%By^DQm-aQy{+cm$E+sJ=6`QFW2&oBG$7)Shm4SHL4bu-7<(AxC(kiMWu?<QRv zDL*21x$_$0@E`RyE`{(RV`W@?48CXx7%K~2KCT=C=U0F~x0d()oOdC4gSEV!IqzNM z^^rHHfca2Gx3-QR1--bl<gU7Ys+ZfLje4YfxbE$@Dnicw7C4>iyqY#At8=?`=uhbM zcWU<HP;lYSf{wVHBV2Hp4ECoc!RKh`I#s>jui@mGys7LyabB|DrJYlsP7-hWwip`e zgWm?e@+{`rq~FXeH<vw};}&$*@xnFVtKPL|C5(3fqgB9=mjUD5H5l)$!3Y|Eqef%x z`GSn=xf$1fXjI~PbjI^dwKm>fYa{A^200P8PB6}_!FXd0M&S9)4tPFy5?T05+AG@% znw(l|>t$tI$Z_d^l<zN10%vXw&R_|rkl*`jIIByO;jAuo!udbPC(6QMWm_F^R=+yI zd9()SKXy%&si1QmXLatBN$4Cp*QvdKsI~Xqvb_#?haPr<b$bogjuKWu?|W<XJ`CJX z&9bb2#xKu11^v{|;j7t)Q9awHdi61VT%KF^dwy}&`sP~upDo&ty3d7w`r1zQud3C* zxu{>-JI}*7uG23>%u)9RbDGsy-2M<RZaJ<w%6*lbNx)8FbJE(Qv5fowO}{+16@D;c zFKtrXEl{^fr44l~5&H96!0KdwqI~5`_Ll#(Ts~xLw8kH84Z(1-i(xCYH32W}rK0_? zH*e1HqHNfe$;zKqYk#am`;+-LZAcw%(Bb961+Px_VzN5Vui;YnZ3p9LOP<V~1edy> zE$bY*A6yRB&z7*C*x8vjq2H6y=V9v=x}5wh`Wf=7E)R6jWqo4kvd_Zrq{|hKm2UkV zZAH0GdRvy=R>RAC!i?QEWnDA=irCD0bI?2W_w%+vUc_Hz-e+=N#BF8XE#!5IFFK9C zV-NZq_J^cBRm@HF^6XrW^AvqPH*ZS!2Ca^HTVjeijhn_-<#%c3*nJ1zzR-SX8;w~X z%<;ZsMd!Zki}PHrg&318E$VBt)Nx@sh8Gv-tNHd*zx#&Fw{G1AO@pWGXG;37-E@u4 zSkm#7H1WK%w0ukEfn^3KDf6aWCTxxCY~m7Y8puw+b7O&vb2!tpd>sqE)0u}*Zp0g$ z+IPm3IBDwxr<YBFQ(0zF4JXh4iIaS@9b$q0IR#G6_q5|i%88fduu;s<fm=x<=5H6~ zH17}dc?6!jZYGb8?1bNb>P)NQ`)%;;Bn#3|ycqZQPnI9DqHMkHDbG>44)M8%E#LLB zO*^kYwfeqWq&a3y`-H&JwFYVAT|U)!<dA2^>A_FeS%uRi&EG^*^Qn{OFj?<N?Xf<l zELL-x)tN@+%XiyNYsYCUyKg<^X0m!|PrCCU9sG2sJD$=!DZKT!lr#1!wdG8CPqN>r z_CGe!0rk#3ARiyAY@_^Fz9uX8kz6ixU?==5acnI+?fWygUcK{d?%f#S-i@W)yRnRW zH(tyAffp>V<{|vvmFsxR_+7?tHBVTbO;InEt#11L9%A5S(7w^UF72^SdEk3Uj*YjU z<z8-O*g1o$etIroyfwo}=^0MD46yz^$4%SmcMp5X9?19@7X-}oT)<qBVW#v9vt0(5 zV*xYc=NK$trRM_HOEavLo?*4i0PF7qR>trCjGu8(z)a5t%mo={O3yIcWq|p`0_NQr zUivmrreXD+puK!(W_T$*!)uoT-lqz9J2Jcl1%Bzd!0)G&m#-;3!)uoT-n9k1J2Sk2 z0$zG9;60MzrSuH1T?Tl+RlvI=!y7E%rRM_P{TW_L&+yu1fcMS<-nI;HVF52a7x1=a zcqu)@YnK7u8w+^11FsLC;XJ!`XEy%p<@hgcwrd!sIR;oU=-l1)yL(#q?hb$2L;B(( zJ$$Nm6yKEA1Jv*KJ&4&3Oi0UkUk6V5WApTB$sU0FK53Sx4-1Mugg+Bs%WEsd(Yt!Y zUzl;viDh@Nf5mjm+3&cYx}?D$Km)%+X}Mz<e;!WRo<$$tJ?H3Zu6Eq^u^ao8Ib!4P zebP9)*T#eOZRdP<u>U0cn=S1;_gi4gcQj{@?*pTNdm(Xrf5vBfqXQ0;w5N|5Iil** zUKrQzPJRuVb|1NU*J1d}6|7@K`%!L16FL?+{0cavImWY!z6Ji=sS@q9%Pq?7XluJS z@A^pQpEhtMJb;$FR^nHW%yR*z1r7mYWyaz9XYpMD%3c8s_xG=Wrz_!;^kh8z;0m4{ zOR{G!okb}5-#veH*Rk9?G@tRLb#l48>O62x*mCZ@T|rxK&3KjT+qdREtOD1S;IImK zNA_$U6QA_#x*l-!FArEB8n@fYa$p;#g)IJ8WOf8UHOzeSYT&L0R(EUfUM=Tv9LGr; zWu+H6ICqkA&h?b#)>5wS3-$XKkZx?Uj$ifOn9a4BL!jZayBc?`%4cRwOM2<vnL?+I z<$k7%s5981oH40u5|%%gzEt(SCw6c8+9G{JksjrZ54ySA(7RQtb+Qkq*eT#f{V2Dr zR&HJ1ziN5MIO6a)V}Mnjt*x!&Kh8S->-ql2>t=CIntNY8=e&V>>%rkp#+ZxYjW8B- zuh&q19^yH*UE@>CC6zoFw14)eRyM|xW!Z(4l^>2V9G^MAaaFcUzT1!X8U{SMgmRad z4z0^Eg|v?Jg*95Qa?e+$L5Y*G8+L!RqSxi4kFyT3(6a1jsN+Ae>}83zv;Thi&gIe& z`Zbz+X~=xT*snv!g=ZZz{)B5b_!Rq6@?|ly-Ay^iNpHp;L4z^BMQE9Y(7Hw4TPLaO zw@#z(>uYse)D1c$`mEeIx_%Nk3kx{^2EOX9yszZ<eQh|2p1>KL1Wx&F&0QIeauaYC z@~kYi_*IS`cRf7Qq$*SCTJTf(*)d6(;H`2aO|>b?&bzTG%D!@Of&2&G)E8)cQRA5L z)3a@BwBFa&)pfaC!ZnwRIbq9b3xuz&_z`=pM=qP*xa{#m&U+(&>ls8nz&iW4_+85X z9G)-X|015R=l8SyeEWs}b9sJ(U)P6@<++P>KIfyBb{#YR``>x$(Rg3R`*p>8vvJe- zhl+Q{{=dt+W09rc<2Yv-zmC1MZH_s$ZL7gK=GmN+D|Ic|&>}zP;mR`F&;G(b8Y>NA zA9wJ57<slo`}kysa@xnB<=pwlW8bP6%NQr|44-x==UY}Rq7A;)m2~g_VejqZ^sLGQ z|7Ttj;xNJk1RI7RlNWHrQ66xtBaS+dXk$sYsbU*Tx=n?)X~j0x)TM1&LlSAKVU0j7 z1zO^2TQ+MKw5+8OF&g}oX01ihmIk`cBo5HPwyd?5Qa<GO{hs?=GiUBRGa0nIfBpV= zKF_(&xz2U2bG@DGyxiyJJjG_}g-pXwI$!yJ=~o|-Cg_!p(te+^AJ4<Dz8gE8$*+c< zZbnacU_UL!`_M`AwvjhPUfn0fUS27`VR?pLmwrw-*A+{+5#Z{6_xf4<?iS#;zys}T zSi8Y5hb$t0q{w%SYrYcR&C%};3)}eK{q7?8tl!-(KIB&SyR9a)<8vF#x!d{NduFKT zIb-X6YixQw{jL733;&_4T-Q~8`nt$FEz2+Xl=!DV9h#lSUHbN#PYxW3*WkEn1{^`} z`!bH%{PFGrN9m74&g#^CGr)w*)u+-Q`|d#4ZaaVcW$9w9JDxwjuLh?-)}I`~ABRs_ z%(Hh#EiC+&=LLQnecth^ipQnj+75iwz5Sdif3$=A?dbUTaW2g>7-28Y4M!<^pbakV zA?95XBZ@;BwZk2xjoE*JwZKu*o^==Rv^^`<2;|jIUa(?vA4=PD%q;61v*tZRJ;&Ix z-tpR!&UUe9iDNEp2cCLtI-4G>uE|$^wi}l(Dd2)Gb)mffBIR>7X49*Yxqe697w7Le zqqq#6d!_4xd0(-os#BefF)dDIZQando#=Ati@NqR#r$QG2JGE)Ju$CwkBs)V(cTTy z+5^scm#~ygi+j(T#s8*uSQk}yv@`8A;^Gc`glBu&m3dZZ%W%bys@~N52z7oim+Wbe zqvB6#-|l%Di}b=TW0=<w)94@H@rY}l$L6mi-&my%|D)s^yVUd7knb93yn7Vqudd|$ zRr%iV<N2LodD%oZ{x9eMN_eD<w=zFoPx|%DHH|km$UE%uYV0xch1*2m<5?Li@7UX0 ztbO3C9RHm!#JC%CGUun|8JedVBihw*44$dZ6V{<k<!t-0&)848-+XA~J&Xg^_j#I4 z<138$VovZ7xKbT(S>JD^*l+!s_GNrMz_a}(Bt2-qJ@aM!9XS3R9OiqTtIYpA`5T&? z8*l7B{LsUd4{wLpwK4Q7t+|Qkb(#OtCI1)M?hJh?+xr9Q$Z*H_Ao^Xx-dyXq`_}eb zA0Z8%we$bv{9erZ=5)DkgEyX8RKDpS-%+i3KA3nl4;|V3s@t$VeT#RXRrcG>`pJeO z|Ad?$I_Y|y<I!s3=#|0|mzWo0t@<i0j+5${?N822xzB2OhW!onX9StX-d^|tWvcIu zn9RA+caM+$*YLIGi0>NcJGY>3ooglVs<VT$(a_hTAF;pmWn=|^#zz(cgPkAX*%)^& zbl2PYwrd}@!<=D1IE`0^Xm41)vBwta&gK<k>o{lFiLHG4+ee>RXL*x%I2&h9?4kV; z+P^I44U(tsc?a*>0&X{XE6H<R&AP(fLf$HACognM|I^XL-YGAA$FVxL#e1p7mch65 z9vr+V@f=r2(GS~F_JM;v<a7u7z4}o2;T@uTx${6fQt#?#C%cIwY{#<qu%1?}18W1< zjCmF~>ebIwmi2y_dip_ir(W-uC^Lqt%2>}U+Iuf$)jIF7_1;a{f*I<)7+q`E)^z$^ zJG^1S7*)M{W;ySCAT#ytUC69KI{Nl2v{jxb?QTx>dwSn0oTF`UuC3wxRd714P4>IM zIlbQ%&XsL&uBhQWn|@E@Wr1^wCl$U`ZSb96!}sfT9vArPdLkcZ(+7D{me=KO|H|^Z ze5KcN_0Vz9@%#?oaYtTp-gfkz^BX%Ew6?R(;=0Ox{BQY{tv?>|!4UC*^RJ;MbLf8W zQ#^6v=^P^rfmgq+UvP{yPH}v6KUp7K`fJyP2|y0Cpy^n<fWPRlb4kml>kc-9&bj{` z<<oVtvZ=s(jBXWpr|ZwLc&FE$j`tY-D)3I%p=0q*uR9&@G#x8&PS>MjaZc5%@NM}1 zW5+?)@q#bYc?Q25)q8K+QaRS?gFnl<Sk#+NJN24V_4<)zjFHBItEuNZN>O(@KWA@q zchTll-)3*GMV&#~OXGIY4`Z0E(BoN&C<|I0H=``*oQ*feos)fpH}5UzoQ*fj%X-kV zlGtvpys5YO_M*+1cvEk0fc8q>1WtKV@+IoY7xPPB(Inm*$u{oXL>qVSM;mwVM;jO3 zSnNChzim&B)1g<>Wc5AR_Rf4aioC9L@j>`MwQqfu@68hfyU(s2CY@(aa2<1kpk+24 zKgRz5?z^-94<4Mmj@R4VU9>rkZ?pKDU!=WK#{*|w$4lE+$LGS6u$Oe62fM$zpzrzE z{hOW#PwH)6UbHzAPr`l^oyh*Y8czaeohMN*>|UKQMo_OdVE3gTn8$M&Gc3Mhe%gnL zGuclQBRqf~{#x_IiHC?09s$P#;9JPJ?H%{d<%gXoz(-@n?$oc{hs(P!juKl7cT)lP zOwPN%$opsV#QjzFVx7Z#=cmuE0r^gtY2PVXNMF1cV3_j-et%OO?kkGl{aNPH;}13Y zK6m5HiN3$(`<B#8XPOunABr@(Hx1vu3SZn~{c-wXc{;~;(Sw|$ymUf5%HpBqPp_Z& z>oMN_wqAqwo44?O=XDd0G~o^Z_d{Qk|C{*l<^StV-dpBB_K;74M(^u3u6_VI*L>$_ zqSL#+rO|dafOnYso|o~PqmR(8-$1>;pMLXy6aRtFySH8c7T2|$b4|43ml7^;PU|Z; zr8)Y#j4`Mzm-d@-xnqOv_5q`w#F_ngf82NcnvT=xhxd0@<A`Tcs~EAD|6b}ZqED`6 zaEHyFbheT)-F;$x-U9x$UDtGsS$t0U)+JBf6_0ldNJIHPd+4d}k@>Eo_c=77qX`br zSo)6Qe@2$h?Y8ktI{E;8-|^YU=Ti5TdEKU6y>{myeaCk(ZQix-;qkl29v<I)(o)v# z-*M=gk)`7wJ!#qamXT%j&wf=tKKibW$|w2Ij?dnY5O+89Q(t~=9`Za?#b^0#-spv% zRjk(U7Vs?3eHS~W;cfT~`7;?4r1!&&@he`7%Wn>eZ%ffe$g)4<^}9yT7jG%g_>NvF z&(N!Se~m|6+i}gpv0!xR^?bkLtISomrEe0}`yT5+`n=#(sgrg1q?7Q<bJ3xn!K;u_ z;t#wMPr$_ZGZRecuIE&PpQ%25Xl6dr=A=#hd$#HKUu<(bGK@CWGj-zsW}9=hQTeGJ zK08pwrmnFvP3<v%1OBh0e;e;ckj5tbZxwkh@|eyZnS$Nl2DZu*R$hyrI(^nT`z+rh zyarj~FJHlW4Bx0yruvJY;2nF`_Y-dCf38bto6essKZEkpMq@sG6*d~{?XFAN2kq0e zw5yBwp~KFr{nuBz9wl9@@%Bh#H}`4!e8S}O{=?$1jCVLw+O=YFD9eCn4LRNI(B0ZU zxlbazZ3=H&ac^X^)<%;$(FW^M$Fxzx+otg1t=ga7hCW>SmqCx~WUe6&Gk)tojUm_X z^V>4aE8xHHN}FCh#+n-c{iD_Ya(J~KelOylc;D|@(AaW#L1Sv{?8XP2#8}r0&QCs6 z`Sw`*w{6y#)BeOd$GP10RkW=wSbk0}A8vY9ZVKiK=>uk%_qqMQ|IaIWF3a?-&GfCy z^sRxuW)u3F*Bma#_DTBCm)pUKtjEKD+5Ws}AH6DRTp=udiuId~oMmrvmi;rFWq+WP z80^#&Cmvc#40a(g*oEkD*3A~O@cCNSr(9PY%Fi(txW?<;ZhjsYOfMjPLuc362xZH8 z4jFeqTL(OAp#R2Q;!U=Q&geI^&-S=FSbMMVbRnAuI^i{TVqV<0^UKurxpSn_@zfT& zncCuC`?B77xn98iEcK*A8w!1YN6z!RL9Tm_=6-ZuG>MzLh%4Od`Cm!-r`}-9bH$+( z=*y?hug=!4B41lf`h(7`MDF&J_viQYlQw2pMZWRKK$G)Cq&u4L7}M{2_Rx2aKHS+k zwv|4A?bIsIGlO^b?;p3m{$JdW;fn`|<HYa!s^>;M*X(=JrS1~*?iF{UgEnpdYfG#4 z&2QTd`L552S6pdaZPO>mYiWvh+u<H<&fEv_N|*JNv3u8}jWZ{Hn;5$tZ&yQ$@*Jj) zah-FsuIASC9S@(~Yv|g?_iT`@--^=DuC_14w$f;9Yu_9E8!P`D?WlVvpu20p9r~tC zy#&8*JNmg1aHKX_S4=S_^5ibdgArdQI^eDEFRaP5xdv(4_lu-WUF>Y2kF*)}61{V* z_k~<f`AgH^!n@h%<BpK;ioV-x?WkuZU$C)0&$lESYgYE$->BC46OZVRb0^cz2lQ3i zz56`B|MkjuT?YM^@w}Y2EHBSI|62BMYk^UY>xebZmWS|fEp=}GT2;sL=S$aG<ftyp zMBl!@X5M0(%WtUmosePmyls+}b+qfAxjM1~pW)h;dl&1;H$5-=ME$+7WZG9k*TTnX zQ&-k#XAYBmU_W(}A5mXu+d50cN8e3bp5E^&^l1bhO5+RulD$dw{>4=s61?$F@CC-T zqt$*(!}J>Pk>4`C-gy(aiB}diZkgD~y&#|ZNA8Dg@EtCAwQ&7)X>Zi|V(%L4Xtd(r zP?oRrPW9ih^T^*+w7l^oXaJA&Y;1auN9D(Da~^Fr8gF6z=36v8Uz?xn<HSPRTTZ#{ z$`j|Q&dqIC`L%NU@?5-crEUGLag4lbWjQPYPXBu%_8_dW{sQ{idCCp!BUjIh)AKf- zEB`7EzmF&U5H>B`Rm6O4<;xil%iqs>g5|@EDeifjx1GFB#=WFNw0q_9ZE0)}e`*UI zx|p@l;Ey_Wu6%)xZJh1@2=9|VkbQMGF~kV@o&75~gGHaPvq>MQ4{0(dhu{6QpZpCv zw}MzEaQ*cha83H7Hn>{g@_yjJ_r21#IMb#-lOKDtpXtxBB=-lW`wVZStRG&=8+h4c z+IS+Z->CP!Q~D)L@=x%(j5jW$KQ|JW#afPgL(8+S4%7aPz;|L}#+2jaw;OvlK!^M_ zmMi7e&L76uqwFT<mHVo*RqC<#pX!GmqCBm)>|>1yc}drL_~PBVsV!)`igq8dUD6vf z4dI{kC7W{ImH5d`_Jh2e$lHXDsE6WNPnqYSEc5?8tveq5UDlsU82xM==4N2DsjI;! z-(ww(xlG?i@VhT`mH+763kIur>kr|ddHwq;eY9=)ux|PF6Azq<4J`cdglEDRH+J!T zYSx@s7h1@_Yg;!HU%R&TyZo2&uWM22ru^w|+%oY_#u3|CjBQHCVr(<DnV<Xf^YZ+> zoM-znKtHYqz6)O3r*?AQOun##{L8yPCXO&3^nDKXi#bn<9UJH6cZu;W=;c9S8y8jI zy*ItRP5Jhsd`Fw|9l2b2tJmUr0qX<*>HLbfKb(D>v48Y`x&48L--ibKwuQ1S{BP%f zGygmCe+PJWl2(p!PNKhg3;Hs3wrZQ>N_hr{cyvJg_?KnyAjYz2ll%3!A1sei=<h(Y zl26}*tnE`z+m`1E9^4VH#dGpEjB`7I)i!tVuY8RYgz;T>?CZeazQ%73H;x?Se;4?I zKS}oJ-XOXW>z3Br$@7lpnG+8}$9B?#<k<&#l6abY26;hK_Mg+}G7lY2d~VZ*@#AN} zzoo#Rcu%|P_g@i9Y$v^u^p{BA1PxaK>m1Z?pBv-%!vBc%UGFvi-%Ob{U|DGcyQm-i z66c-hLeM)Ie>QHI<aOe0?!)oge&|&E#&Oz?wPpME;oP?JRTnSEcgv@K>@E1EJk_nz zZeNF7L#Oq%e~Pd3dGx|+jZyphLF}vaujl1)z%inPb-u8OHr4&tq5COa$`f8V);ne% zGgczcj_j{~71>1HNuIT-J6TrLeP^y4V_4h^H5;vrq2D#FKU{0i^*DL5j()Buw$K*m z<#^;;VvhzqZa#47p^dCfKgHaCA#?w=tSJq%u07J^oHFaaE8%OzP4db)eVX%-c1|y! z7n62w?_6-0^yztytnAf6<9pkW^oAmB%wzsW#!csx#%d!??)dm>701gf`Jcz`9@BSW z>uLTuHTUMM@YK9M`4sd}ys_>h?Z(Glqnv9ao#N(wRoeMo*BE;Zw7;N#KjT2siE-n} z?lI;ljK8k2I3K<s&oA`<`i-E=JEs3LblK+puf8GWvv$$vyFx$l75W07QrSzY{sxTk zK^Jx3m+KCXYBS*YG3HGCCz>}FG_SATLmX}FK77qnjWj<}28njo$r8=|(7gUS=B*XY z^O}@5xMvsrK$hv-psgD1KS}$_?lffQ{RrCMJE2=zUhu!G*s`Q$Cv-~R+462p)i>9v z+zVWc4^xKMvfeg=9A4ab0D9;H>0ZY5-hH<){xhcYznFi=dFK(1@y0){Nyj{_v8Lkv z3G~smf|H=@i?is)%jt)_h;<vjH_&Gv+`CX#A(LNmtORE&%Q_e^CuEuUZQ!We^|Glm zypQGaC)R@Y8E?X4c{WB_X#=he%y%9|xoPKG*LQS`xyRPg-<j^$e#<jQD<4Dsh1la$ zwY?(uyPEVN>}mnJw}9u3_*dKfUHIX1=u|g8(r4G}(iuHqKKeif6MYPrAIR$<;#ptu zHLab-zFRBbZ?OTtuogPXZ%*nLTnk)FTWgWM>wxP>t0%)bKh_LK@^h>ij%L_cBeY(u z5nc(OVm^N&yb*u&^>oJ6XhXeEZ4<xwzlQO}vX~Qh(x;EmZ{=+Hx(v4#IG>FJtNiNO zIMDgyLTDT2U*8jS*_Lzm_p9&7(tK%mzOC=mPdc6~B;Pn%82syDeX=&Uit;NdQwN>H ztt8zf&-O<zoZ3TE&W>5HW*kUq#w_*5G0OEL@mKS=tz)YqO<VT$VstO+jLxynP_E+` zB|QfjGmb|aYlhF8w!T_Bt{V+EdH1w&=ETdD5j;wK&v_l0Z^{3+;p@MGFZe1?KB6ta zE7x%36=xL>)%o+U_-<i8JqOr-05;^s-c_IV{(27e#&R3qnFH+Cfeju!`B%sCU|;T| zJQ${5L(rgZ;KL58HyiM2j>V>(M>+m#la7DFI!3Xsk-imYdB9pvSnFxG!kgBATPOPM z*rd;mwLJC0wH4biep|%zLg>=3-;rgwn)<7GeieOFKCa!ZA#X9Tu}-&!@;h^XEt{#m zHPmrDo2}i48KWF8gjMeL(Q(@Lw8P051iN$1b2<60$(uhwTAgzouk)Dor^I7%8@sqp zBaeJGehHe-fk*N~+i6lJt=WF}ge|tU-v-}70$#mJbduI*{0e-DdTniZhI;SJ^}>$5 zQ>`6c@Zh_m>#a5Xe-D27;ku%}uz&2q<SUH}d_H?k^?WUMu#UdHm~n4i6W`qY%EY=x zjsqC?%Q*}&)Oa_3_9Xbwi$D8ye7!o<g10SjMyzGpvDtQ(Hmdf{Z&v?9`>HWuv3`2A z^85N%&&}%_TyN=cJRYm=gE*aZiZ#a6>nhf8F7p>(p5C_OWBq+6zl9KIQQS9tyKx?E zHc9`eY5Ri??*IPXd;{QfkBTGq+F}paa|a#!h#lzjr#mm@`xd*$U&6Y|-ldmfJH8Ke z>BNS7x4-iI)P<Lhdw+cw?+u9Wa(EQ+!F=>ueO9OB6=VFKXZW5%dZx@f`qkse^WOjD zUxAPBt;Mr;8|nSf5$P<0J>P<cdEk1WRh<>q7i<Gg8+0v1I?WRvTiWv-;Kd`|*0cV1 zpv}0*ew?0TI_-Bc{5vPhUOMzu+MRnz_Q7{1-qZiNM~(B`_j*bH<=FD&$&Osp(tcd4 zk`|w>SFT-YBWazB`^ub0#69jIo2OqjzcGrFjk6&Ok<qlXKDl4q#h3Q>?IYlOd!f;| zOZ&%nrZX0Pccz!TZT-lee{CHbWc~tgkcqKeSx=ey+zGGbr+WnQtHfcy^vUMQyLRVU zq&dzesS}@WT$<(x(t0^`%OlhDVXr>iXX$3`Zjbt6+tOiMpYFdr?JvHSHd7gW5#GME zgNyo{ry!=78IHU0k0d(agZ{Im1G@J3T=K!TjKl1=d<nYR!BJkFp(yBY2j~8Ey`N{) z`Y8|Q($AUTlwa_q-WD<9H2K9Dv8$2aM&j*FP1Yothi`^IS2r1pm}_{}QMtbro6!cY zhEJO)bKU2Oj>Z$^^E<m6Pi%%?%6d8Tf{mozgHrFVCha_AbFTXcb<5{<)J=LyUB5FG zb;ZTGmLBUTdRUK@p7Yz#^XK5)1l$m@h4t_SJ(~-9@ki6nwnYD1^xyBqET{i|D@NZZ z&1w854h}nG&Yiyb;`0!)Oge(Rl&gN|4a|x6^1Y=2+MEf-_3k&YuW%y1_C);1Qhbj7 z!Dr{QGu0FKz2Ke=CUBn&u9Ly-_kG0e^TV9ce5P^v_!-F4xavjxI|kwR4|lwD_u*fH zpVpc5SIs*f{mzoh$N%>8mybV3y}n#;QLg9Mv4MLbpXM7tPv!5QA*X{r@2AW$=x)9t zbdYChn8Zu}!8P$TxS!#>RGrPrC;xmN!}PbGqTY%4*{G|oi{muwC45Kmv-;Je@N)m* z_w*lqw1Pc~KaTvaR9@9R%6*Zad(<`I>HPKmlx>If>z@K|9p{6&t=Vw8emWCQ^X<2~ z^v)b3nRbkLu`vVwMIAep^bMVzW5Vkff7;kF>%yDaE3507ym0&t*@nK&1lwEam^wEp z3uHW#K6Jcb_u(gzi8`Twv#s}pPIMfr55^zXIn4RoyWyKMOfq3iw9V%uL*E^(WIMAA zr}{cK8P0|?WY`X8DZ^dL5Z@E)75|HcwD2MQ_>l4pt1?dWcVujA;{4q)Z2uefGoDrJ zjOICB3cEe)!(!6ItPPlV6~4#kA)fU~y}&vib>rKZYaI|qA7AYm-|(2QK399n+a42E zSzGTZXt%rrpFWTESjR%+74zn&{o<+T6L=0-za3-RZ_u1l<ey5q#BmzWjyr*KA<y>v ztfF6@$ql?O%DD8^-t|Q+(uYqu?Dy*QNq6&)|4#FYGEbamfK&fIk2-$aPWuq%>72H1 z@T;PoJ87w>ZJmv6IcM`Z>`LGL9pVnl;p?8e!DGCn4(c~tqZEG1=TGSz>vu<t7pIq3 zW5V4zma#14;F?G9;7oWBblR`*3BqSu4hHTi-K=mokfVO9#O*l&ar<s~tI0kcy81WH zl?$B>eQh`9$Cw*>CXbCfuLkF}ndii8J&v(2%Fo1{J<7{EoGUwGnR=~nvtF!WiQD{i zW&}R7UpI-z_aPXY(>Ex^Lp+<lb6V0Nd>L!>bB?Zj-p|<o^VBP8eN(N@Nf94lSHfL| z?#bs7;FN>DSvo^!!ygZ!GXbxz5`Xs@S6Du&L;Vkq8#7JiT{EV9mSmo&=k^mG^-1>> zTs4PrPIe4V^wM{z_oLtHVLSYu6ONci+O&x}e&(1-S8OxJqx;a6i1DssOjlP9GVd;V z`U~)@eC8hOG|w#MLadhJyzndX$vEw*W`*;M;M`1JiN`a@$TQLH85R4!slhl%d+M`3 zB<Ujd5xzF&uzu6e_Ynu1zOPxWr(A`;J7;WB*EyZC)W`ZCYc94U|6ONVM!s{JH}QWj z<5a*8Qr~sYCjaUMx}DY@mGL5E<`|~0c#hb`a_3#@zHL~i4yXOpVdTHG9ftqW?f`W| z=c4WYqHTRZ*XUNxU{!6T=S)kZS=spy|7EoXaA)hjG+&aI+3MMcPWZ0e{}>rT%Xric z8Xtm2eY!9)Uk(2e-!}5y80pe?sTcN1JF=c}jebCxmhsI?>6`N-^|9{P<nOZFr{BzU zsUI`J`%SHx%ET4?IU)1sc(_U%`AcO)-$MtZ@5AU|3mqJy@4j0;L_drp)q@sk@4!|c zhe<~aV7~s(7(hNHzGnWI_B+&;slR2Jyfa^&k<aQBW90$;ym?VqoQ_kj2mR8&afTmx zs@p@rsrx5Flk1Sm-I&w$7|X-n5+3ZWd_I|H>&F=V5^P;K_fDk4`PCwx)t3f&=z2Pn zWqN?NLKl30L><pIwPz^Heri0OnnM}O-%I>h#_gW*R4!BSQ{!(bFYo6s<rQlxzQ+}@ zSsHs8+e=-w58A!Br153wr}jR*%_$m_EGVyJ(>0duyk|S>Q~H&T*RXa5Z(XAmMqY>f zz7JlRcD_-~T|SrBkUp2@g=y`swKe(sMa?=5?fd=Z-0yO2X6uhP8sRhjhG(g->ZN+7 zY^VFq2a^x;498ilReJs=*7>Dbc<1xlw7Mv--U+XiXL`mby(sH~x>n|U{yFqQ`~%hp zzPc~|!L%2U=G*8M{7>f&pK3ffE}ZjJbt$d2HyK~hZ)N7ZL^}%~tREN@FLYguZx%)$ zpiWirD-NY+;<{45EOV?*@I{;IdbGKs)~03Zy*BUtLegitqyZm3MZ@UPN1dlFY=W}^ z?b${r{dD%{#++TP?aX(p*mEwlEuMuo<4t7~KK;6^D|LTf|2~Ox3w^qBk2$LSGkqrc z>iiPq<ns;8QSXG$u6-yA{l7LJI&u+wm~}pjeD)G^hfKsX6a3yBQ)`>{$+luFt+%^) z4(-O8Knq;T!g#Blj?8tA=zU#DH{cIzm}w8l{Q>!f|Ln70@})lR$-jH(cgV`VnBIo1 z*;jR%HO$%91>oa71s}yX6Cdws!^iZ!i8k^>&U+^1iJmTK(g*tCIW76}=JU56+6tXM z`>vVqh`hUb^ijX*YQ3rQEmP&tD*U_oe>bsh!ZW$n(caJbo`G=M&m-0MZjRA4-~Fp> zb4B|8li#UM{DW?JQRn+p#O>{LKz~r`nCF|+^;lb6iY#M%vpxAS*%q>5&uCUzy__*9 z_Bph5*986VculqTVZ8r*bgogvDKYN3XT&@)?d^QJ|I%^i#m<+XM)v7D!qh3pjEHai zHfp_|b*vjP<6rzm6*C$e*5jkO)PLjs$JP(J%YCYQJF0!EvswH5RNklRC;biLm<QO` ziFnF!RvTm9e%x<&6F(hvPpFIUD{Etp&#pB*XWUWb>F)wB^V5T=ob^fLoK&B*G7K2< z4}Jq2#sJdhdp`fKzU8g1*7vH^iBi77-?n;zd|f}$&(M!O%G!QZdF}DU`|)`U9zO-S zbmBu#<zL(IUIG8TOX2I_|Em10Y-7*Y!Ec^1j((ug{A#ix$AAuWwu{(Pn3#7NJIrTI z*!sxtykp9219;ad9T)t!UB_l+d@6P0ySJy1j_)HoH}?F#FzEc@(IwTIjCx)2E@CNl zv)n5fME;xeH-NA9z7y`B`xY^T<EL{1?>g8|e|#Q{=QPgn&P0<lTnDN>)sbBHJGpKZ zFHO~5-lpzXsJoDPNF&#MCf8jUu({nT#sXK-?iZ+QOnjerxkK}__(5rm@8cv`=<9?J ze+ukkVD)kOI^PE}F7e-ZTA6k6&4K~auJQSA--T~9-*L#8$oC4BrT@-Lm3b$1gdfc` z$Txj#$v2<d@$LG|x9(h5z6o3M&F6M}+m`uuzx&DbUA_rh^3CUVeA|@ywlmk2Z^E|Y z+t1CBZ^o?h!T;yOH|;y(xce5(Z#;hDRLp+|@73PPd$o6+dg8?0yjOeAh0I4^;e9(F z8v97`uINYj{(~`(zHagB<;V4pY0r0FnESNvhKai(J$A#yv#(>0gPolF;!6+xj^8}s z45jgT-1%|Q|E$h1D+lAKbxV;odZay_13w&B)FJ!pe>Z11)TMx5U%;OsJUZKGZBO(h zd1QK08hSQD&&HSEHZc=DFM=N1S&-ZDY(|}~qj@Z|9btQGuq933E@0)6=kn!G16rOO zxozUf!I^3KCv^w>_4dD!ajru~QC_zBH@SR0<+hpbBF*ilG;MF9?W<_}X5{(1ZRGN` z+_rmJwtr>8=g(#QSLXHuW<vq<=?t?07<nYjx>I?FMi~8fmZvtfp8Qld=Sy?4=}dD< zL-XCQy=~&om(9$tKgu*a&#Uw7`WnvyrsUgi)%cctL8c+4p<xsnMxkLQzFnJXIJFJm zeyPT{fGPR5p~g4;L_5Bz&+Yi;ncC2?l!j)<)J^Bj%(u5^n&oqyZ!2qj3z(8`udVTI zpr9e8GY!4aFcaT~GY#rPUEh|~_!clF-}-8NQ_tJ+O*yvXTN($ltWz4AFMAELe(B77 zJ2BJjJG6DaeJ97OVWR<4^6h_Tn6T49@PzDA8XE2!zHQ<Gz9Tjh-;U64eSqsIb-sN) z;}1Ixn38W_$}nN4%BvmUq^BL<wCkWbrJ;EdG%tkanSAVLGtKH}oo~0-_!clF-)^h% ztyR#F($KK$)wfOTe96pwyEW6GebxE)n>D@#Ov$(3sPWBq+wpCP{C0d(hl6h^4b5NU zZp*QAXXe{4LbJZq_b`;X_utm}w>HxiW79|tw&ddv)nHxYGd^=|)BiM9xZgs&W_*{< zx{;scoM95bGmL9^*3(A>4(-jDHgF7NnAGQtLmmZ;@v-qy#K6|OoiQZkNrSN<>)SVx zXZ$0a@uP4bk38U9I}`3k^2)wMeftvaSRVbbPV^&a4_wk7ZCWSjwvKd*+j42yO}p`I z`7WNtW1BwT%CqYWLHo{3r}`ee(-wm-CI3_Gn0Yr`zy#gNf93MzN80c|#X}ipq`=XR z|2w1=x)TkVuUC^7yof$*kGz8an{vORFEjB!`cd*fXrGDyL3ca;Z=v0i{~LKO`M;Ux zlK)rnd^>T6eQY7ikLUCd=^dnp`QOg}2>-+K0=;V~>pZ71o(bI_fk$6xR__l+tP?so zY?*bN%x(JLk>ViB)U{NPGWRc{?52XI8w;AQ&a`aeU)sc>T_*gr-BM0Dp0Z4PYlq)5 zb$=$h)bV!x*+RSWX*2)w$o7W7rS2~}m3cv9_xSyP&N~Fm16|jbSIX(xQ>wDhQ|7(t zyEC3!Gal*D2E->1rK{|Rx-CA-q^m4b$I5!aLvgB0WxXidnA^W9w_nn_Ce!+n+>f%4 zL%HljxgWbSo}EQMw9}HFl2+}n9X-;jEtK_wR?F1+vR>dc#&hl6b%_&L*J3UEfN9@5 zxto|<xisO|R`knxwEGHG-Rmbhmsa!YfWM~(-{Bn-v($;bf^V>PQqD0Kzi57=mkalf za_;Hk_i|?WuZ|x5^*=az)V-#EYc(48{?^f>jV=6mkE@&aJ3SNSdGYf8MEjN2>FJB_ zRPzq%fd#o=_Q!rT8hI~{zE0*fJ;QTLnrq6pMZkWG@y@!j58!(O-iy=)Ph3~(Zrn2Q z2goz>+#g*)-fr^jSAE^G<B=aa^fdH7+hk3J?<#lm{hW})Q=E~|cAO_WW}9}N?6_^( zu~yh#{yiuA0COzq=%w5>t6i)OdfqiX)5k9AxTfW}W!?~TYS(1772&)~NIc$iP`!gi zpBn7#LVF3nJK({|UG<#poL<NC?N?H#%$Ila*|TEm!PCtt-O=xru#0Q3&(>f|S|(|4 zRO>_S=(%_{`Wx~QxwYxXE2;N1Wv=mZ-%*ciRi1ZYUAAWd|DH=?`Qyk_+#9NVl(qb7 zvNtxbP5xc(zo7%6kK*(EtTIdbh|JDJX6j#hR%Ym9gYWJ*Mug6Gd(MURlP6oJA^)vu zjjV+47M{8bGOtTJmDj?C{>Jy(L+7=B`D?j)<^8q|z8j>^l#X8PxY6YMpro6oc^5YP zM|Xy^{eUxFhZCRUjB7ec_O)lrm8)%dt}xnL*rvTC{{qhT>Tu#)SZl9*F6}bbt3C5m zUvmw+oXzHZ7vFMi)_?7_oehTV>X+2Nx*l-P#xZ(eERuW`vDm_#ww=1Z7?T8C*qwBg zavw*o%31v~rV(D8$|LdzbG|stm(H2=<TKfCm+RN1PmZ$?-nD9ssSk7fQs3lL;sfny z6Z)<b*y}RAt>wDBdmiePXH+YH$6nYG`7xDW#Z%H~eQcEa6|DC(ifaXar(HSsxFuYj zv}Jp&>x}Ksu-o9zetv;-QN{`WBl9xdKS5eLLZ2hu%^H8CJ^yOD1D!vk$nPuCp3M|y z9x%-!-!ri0carZJ*udlY*T|2vufm*O<a_2d;J>d(FCwkajk^Tdf9a7n_g}<e9qtN9 zu|R*na&r9JmY!depS^cRzHaYljkodEaeQ97+kto4C+SCa=?t%T2fH`BbF4bg7c%u+ zkMBUaALbc6+x2X4`lqakpM|!YgV*Y2z<Fjk`8|AUjH~+)M%b|L2t_OqIwt)2;N%SB zfv}sTW9Yx~tM9>nOTEr=wyx)(dy2Zoy|dN-KW*xB4l%`5`e)BkdtR*blx>fd_W4iL zb4;<X^8Wo<7SiZlT;`efj;%DNJn+Fo-FN=pH(z}8{PD0m-!UoAEgEA-U;Nj<Yx|3d zGxX6XG_HTVtMReN-Lo>kpZqh(zq9$(@lMX>c<#-8s{z{9e`~uP&_0M<Ke4}BH<w<^ z)$#6J_6J2-MfX(M@7K!QBkRibey1oCr?%3W%XU!~ZC{t+^dXVABj?#i`RW+XK7CKr z-%{X~Ci@k2f2CIDzF^dQcdbkt_gra(V`^VdTe4o{3#aZ%2XXZz9sjY0Pd^cD{aCF` zy9gTB)XKDlD0_3QOglDC30iC;(&98Nz2b<pb>z8g2cBW&94_a=FHhyhkorUJ*zG$r z=XK;f&l>mTJkJ*j$NheNXXL!DoQM5!|6PTzJLj>-+IKd2N!B?}ztq*reu@9C!q!92 z>+eA{fK%@B!*d(+GC%6EjeS)fybm{d7F)j)=VH|x>F=lSf$Lje$a>!7JqBzf!QeZb zQ^7;_7ArYN{A78=THXmDZ7~-KKUBw~U5lrzs~<|^a-06w?cDQFrEPvO(>%F0N1s2K z`<&tv_@oVgCd0*i<7D87ar+kJ@;|YhKI)eoBLmJc(msjfq>Q7CX`$y&==aCmAD7?r zXj|B>3~OEaBF*;Mx#!#AdDy{kXE^6AmUl8<SjVx)c>MdJu|-<kZw9wAG<^<f^G{Nj zpxgD5a*UVmY4?2*Q#;>Qzpd}R2)5_=Z(pTRy>bpC57Z6#vnTlTPUuudA^UG<AD;L_ z9oH@r-PoeOe-L_F@Zs#wSA4ZC=@CX5DjR4>@6yhdh98_G4UY4U8~+6wZP)%1)9eX3 zcs3=`!y1XQ8UnBOGL!wqI2+$AkU#3N?-6yNKhBGmWjWdw{X31ex<V)L2R)7#!kqz} zu}NpX3lX{|%T8@m7WhxhW$})o@ockM&B?xxcRgv3^ChY6F4Ct(+xi%u53i=r((PT7 z_BFjzLjO%0r+BvJ@8=&M4`&aLxEA0$^FP7+1>#nw;%Q}FOuR*Z@XJZh?f1j#0qseH z`VsF`2^&7d_if~jF}d?P&tAW%^Y}EWM`fLNL09?wna@@COh~slALBjC<MB%!Qcvfq z6CKFcwSkY?&na0<(}Q_g*24V`aO#BV8%am~59j*H7U7LDbuKR79LLl-eL!bUgEPrB z^fCE|TqZBo7yQEE&==eLVAt_^O0axfeffzw=*w3!o;c@+P9z_u9wvRnC!GqtUFgP1 zjAiBxv+iy`d~a_F^~-)JSM}b0ynPP+_$2kkHJjeQY!3an4Lq)asQ09wi1m<Lt9N*g zYXj2Tr)=k71M(pF^~!9&v)P#NQ#R$@x8?Kn*gI^@aXD=4b(I~@>OX$c{ugy_q~FTL zys)d6&4TAuxgS3S9_(XI{QB~~ieJySKQEYtj_`*sgN{1=|5nLzRz46bPUFK{)P;fv z{~<pIZ*RSKy6?G(XKhve(HGrUox7d2&DnfW`QA{;*LbfWd@*rqiu2UptK};`>OI7H zF;8@j#QpDx^Gd&b1ixJ3j`xt-;r^)^aGyCF?jr7sbAiWvZ!(?9`_NbmUV9(Sa@Jag zNDr|_=N$vi={mW4n)yoK!t@<9-rps^*K|vpsNxReEY@F+JiWxTTNTVxrZbHF6vlsJ zwjpdO`dh^aZyEnNcxl_|8NS)Kh^t0ve}Fp1Zrl};?&@&O>iVwkv3X6tf7QTVGLMYg zjPp)S>jR&AbO@bz^BcBLo||`{*f~4z1g7~-9nbvWHD{Y=s_Ph*Vp(W#kJ7jfTii2D zTaL@0&+~^t`f7iwHadxajn}r08OOO6bqaeRo-41~iFJXgbLGN2j@wqeKTvO%wW`#v zzVKuJm)f-t(xL1=q~4-iai;Iir{*;_GXS;tZQwV^Vn@ugR<WKi+ThO2=81eOh<mW8 ze_#6k@rTmdiQkFRZWr>u5`L(6zArgS`V92Z*wB3MKp)C!eEs1@b8E`)Cf~c!+3x96 zcRENrPh4%9y9D#S={@2Y2DkX|Rq4ALfm=U23_iy|>pQ2M4^6H+x~`^87~8r=Wu9f` zNw?pT@;w9F?ri*s=jr#X<k@k<HSV;g4UNo8#_bb(T4ReFU*#@HzaLh?ICeFfUr7CN zZG43LoyFPF+`@U|ukgQhO#1D!b=()TUC#`seCj*}-SjK1BYy;1wP)>?eXBm>8*SG9 z$q(meE3++Y<0ILY)m7%_M_NVMKvCu$J;}$`a4jg{8wLD4;J=;yf$cn*{ekW12YU0r z`t1BjpP(K6v^?ZF&0Vwq3_s8h?JeN+1Khcn-s>^OS=GSqh)2Pj)_z^H4f|If+L8NT z+bn0!7Cr#IIijx!94BNPzSl5Yy>|5R&Ul(*j<B~Aw5N3s{89MyrO2pVUE@*s)wc>- zojZLp&wI2t^zn%K1LXg=B7Y$~N_gQ>irsh)e<JPe`YU|Q3%-W_w4+sC#az9doBlTN z`n@uCANhxQjWyW&Dt;@o54aKo+{y2r><eOTwf;S^FD2dh5by5s9di2bJKC<@GVe%x zWyA!1j_0(Q_7<T#?QPw}9(YIp^^ZxTI>h_WDTWkI`3mR!c~cEeSqHun&i(chA9Kev zE+_rO&&dPVw3LPYH)hlh(>R5`qKA9rEA*uM7S-k0OEDJE?m|w&%oGb4k7-}7E6S6o zo7zFfWnJ@PP22TPX;i1B^F7?*C9W5e@BiPiH>-^We&3f>#%W#)ud8%5FOybj?@V_h z)5oACud|o?3MWzKI8g523>}%*xC^;|4f%hGUyK9w^)~l&?4vZxSMAlgvvlek<gw-Q z!*x){SocroW!+%^W$($X>A22_Tt7hm5o|cE1-!^u5IqowF-dpMZx;D!44@tMPLCuz zYF2UMTY2X{e3Lv*Yn0e;vS(x+@t$M+v!9(F?<E*`=l){I*gWk`T{7OQ+fT%0>li23 zHm2VtyXMl{ICuV`vGw4PPc3k)BQ2kXNK5B%{+EY72md108X(_zJoaqx;XNJjV=eT5 zDbxSb)}<3KZC%dT_twL%yS8ZKrL3vCo;XB$Jvy<j$-S7=`2hT}4|_V<^T~Mj*6^rT z_$)laTMz#(a?)4-4*M6|;dRvc<6KAj9G?bgM}KWUN_tVDo+JlwIBo^)znANGAshMQ zoHoinlFK|ZW!-!yei|D$Lw6<DDyFK^E7-^2J@NnZp<Sz>k#>$Sjvsj=znAk{!S51& z7xQ~PKY60R!cQcBg^u;Oe&c+5H)nT!SHtndb-MEzPsC^0j#}A(V-5E6vKermlk0gN zxWw64;2f!yotAOx6Wh^=uS&EmsMVWS;Cza6v}JqGX*bXrHuExgI06rpuj8?Lm)42V z6Zz>FZX9F`qFw7x(%w8gP^Zk(CamLLSLnn*p%am}Ea$1u`UC5!Bc%-SGDoCO9ah)S zvz{*gyF1Wz{{Oloul3S?+KYlNc_UrUUlu03D-u2WNd0a}d+B%WtG;VFIHbqEvKO!? z=>3;_DxaWUtJBiE4PT^RbuHKSs{YTdJ^h|IY}5Vs;DKZCFJ*t`9kTj?Vd+8dw9~I= zI!4J)b=ZF$&GaJ2J@(_z_-2ZE%27KL&N0P2*EyxP`mf$ob6iQh=8mNnFpe+QN&Mhn zJot~jVTX5R8iJo`o>cRXRsU9`{<(${^k`eAl^^!ir#x&cjZN^Q!T2N%j!*xQewcQg z(;t{dW@!uyn709=Jmi0pG5t(%)YqTYWs3bA2$^o3MW&%crQSq8OT8)O==~4sU!5-{ zynR*f%K2Zi4YZT<<#Ukp8wxp>d}U5k?SUXqWvQQ%=gQpub^n#Qe6qZq?j!F5A@AWi z%e&HNza?yY>Wy?M>v{Yer`cv#A!Gg4Y&zh6s&!`50e!@Sz=d3UGrcR(iO4&_Jaj1h z!>XdJk>OVtdH?pA%HG$I=bUqmbfe>?pDM?nM`*tZjOC8iD@h+uCs&ITKU3=D-{p4O z`I+xlCs$=!q)*>m>U8+=Qb$XDNd2z)!n<an@!!K2*7>ci49;RJyD~lc#A$Wg_{Mi5 zr_fEucgKi!zOkK8EcqfYl^u4nC+y@GG97jMFXP72UuY-liS4)eH+~nd_ClQ1r`)1U zf5><=NqcGU`q5Mm+t!wnFD-10^5fc2*_LwwZAzTce!Q<NZQ)-!7<Zj3Kuf~knV;=T z#F?g@D?5HuuP2_x6EUfC67%i9|7nlbIE%hCc~1Q)#s+L`OxTFIW4&tOWAhpV%u$B; zJx!GQ6u)79>-oierG9skv7~J}A29xi_O)T#&OR*N!&Tb*=jpS$W4{=8Qw(}f@Bv)f z{xS5Eul?DE{><3NwBMj|oDyD~_V;A_OTK=<@juhC*Yy0NP4`(wrpgbRE@>h@KQhuJ zj&88u_&3!)mSbu7!9nor55$jr_8QM5pMY-Duf6L0wcr>e-#VTB#yXYmN4)VHl)I*% za8~tF9CCHeADn_ue9{KRyMVUK`8IQy6k9G39v<kEj0b$yuexXN8c&=hq5X@*^B=(% zFyizawrjA;Pa6&STn3zZVPEpvbd;~A-2Q8$)>F^z*T58>9^1R5M!$H3uhXAo*oOY} z&9REEME@(=&|mT=@Gq<JCv-&J5#G6IZ_#hoT@pWI{+jrSPAUJQk3HpF_8;J#wqN3b zKYilICr#t?-vApn7-#On&K5E6jdPyXO?NP)I~~$`(B6(_wU@hOZ#B+JyZ0wVOzj!x zpj$hzzO)H5iY~-l!LcFQjybpYOT-xj_iz6DpV7uB{*3g0Gfmt+(_QtkrWJQf&_81Q z6DPb|;_AGvr4A)t^S{A0CeAxvfNxuu)A+RyT$a<XBY#y+<0n7x%nRRon7L-p3V7)| zAJ#?wJ-^<YzLnAg{E=r!JD>L-9sEEu!?EVu!(POZ?kRjd&o(O@=Od$2m?u5uGizvF zt*>&1@Wct{pyoeP%ReXQ-(Sl=JLlh3%XjP%&+b}2XS`DW&RV{EFv4G5%Xcg?|H@iE zI(FnJdXjtsd^JW@w&fbsy1$v%Sow)YW9g4J8lLUk@|i|s$69Lsr;f%5K7IiK=I#97 z&u<fBzytj5<F}<)uiA)iY+yZRBQn(vl<&_W+fM#}p8ubNwin_Pz8}6{=~+m4=>J*h zoMXZUXj4}7<Gc+`-lgxjZQ}N?SAJC=^)c|M8_4g7u*xuCf1Ue@f3FR!@wvEe2iI@6 zDc25+DP9PFMj2z(<5zIb<AvCe>1F72f@%EYqxy;$3Io2M0mlBg4yHd1JAx%g%s;8} z`F%f6TD#N6v~i#1%~pQaGk+d=qm{3`c@#QQ9&1U$8uPU(TnFamyzF;BpiEof+z4I0 z`3#Ti!1Csvd{&tL-yHSCwXACApmmqX8(?qDu#0Q3{lKzMmSBma6YNz}c>89;D-XoG zatd}D4dO+!5?<%V_P_Ksjg7S0d`aWvk2e~3{|Rg4=;iy+$MAo<(6b%r+0N#P6T8s0 z8_@~;&g9<6N$}KX?!V^l<x3A43;3^|g+DijxDgtg_`m9%oZaKQkoVW~d7N{odk%CR zt!V9=2flNd6I$n#=7Xusde(V;wf;GNE_KeW)mfD5xNmD5@Q27p96mcf;<x(dUsT<V z?0hWBj592om&>$a?;i9nWZQU#Z*^YZ)iHJsI-z~JcAw7Ju^z}+l<sUv|Lm{5176z~ z^>C1WpVPd2;yVrRLFPOn`nxKhQIK!vf=?PwgFa#0a~;j)^7AC{*bnGQJQ;(oGirGc zlQ#$s<6Gfv&-0<UlP7$3y~XF%cR%-pb9QZ~#Q8s|e-d<@)3|(M2j%_H@B!*3oY<=E zNvG%BSCH?sIDLLKIBg?+@1y_B$~K7;9FuKF+hHC2=3`(e^X%+$+EN#9%6)FZua<SI zKKG~xAB+Cs6U4J4w-fb$(td&~(S?o6hn?aeuD*`C%CDUq9?fSyl!JIno?IJk)_B@w zTfhcS|K(5H^Yp!Kc*^&GpO7wTmA0P&CS-5h=;P$Q&GK6viuJ7y?&g<HhJz#MU$VUt zW<R=Ct%+3YU;$t6*Ba`p!{+<$!iT%Mcz<r|*bsad-w^cKrsIS9`a;@#VTM<h3_s_+ z(7MRr-SDQnS-rEhrGLeQ`Hmabam{q0GN50K`+JP7^Z|i0%J9(#8?CWaCQa&*^`l(> zDqd-@E%&RpG~bf;iEZEaKkIZD)2jp4vu_C>^rl#!XZ!Xj^eKn!;0(S0OZ1_XPtu{9 zt>{1P!!-Yy-_fj}SMI#9iUB(KcN~=mj==-a*ENDok{-<I@RQD|dNbc%4R4&k$W!yR zsgO%rkD*W6N|p=fbt!M0Iq~Hj7k1_Iz4lui)=6@qo_@f3gc*B`0hN>f&$iX2l3wRE z=F3ZC8pj*!gg-6o$Q%0@b<`#6*pDk|<Ij&CMcx%Zyf=FR`TEIp-&+3GQpCV9{uqCk z@4ep3H*q`<VPA*x87jy4=ZL4Z%TD~sf5k7+PQt4Xw|)CKAARyZwozg>Wq4Z+?$ea{ zO=a&7w4Sj0hpIhWd6M`*y`XU;&OYdL|Il~qIw<di4r!8xCFrxU*;4+o-SK7oFF`k# zHZPx8h7L-{yYiTJCwJX0rOdYc@1kwLRkDn<wh=L<eR(l++NZd?&wi)&!1K<cKi0dK zvMtEo{&<h>x41WM1vu3OdGFj(xh8wY*E?q{?MgqT{z#ATL4)sCI=2cwlyi+FE8y+B zwr8L9UE<M>#i=dW7j00y>LT&?UenT$bdCRx{!0!i>+~)r_u8pf<|+Hm{w<u(;oJ&7 zL7K%|(OBJOn%+x*#xm{>S$TF&`lPj_QJ-OqDc(4<9)78eJ(X?pQTPXSd_T|84}A2V zIn|+kd64krxpkT=AP@almA^mvYWW`R%d^CT8ei&ilLqZUUj5LglRZrHTcylmj_Lf+ zxWlovyY+DDTS<#~^C&kKP2(+cbB^e9z{?x`gYl60lk$V7%E<Ure<U8)4b`JkMzhkD z>UJGc|Cz`2NyC2lSkj1GQ%oQ7kp}f^P&$EcB472({H@Tc?Wl8}ds6Q0XtW(^uD7L5 zyRMUbXx3}{Rd1U)WZSl<>Guq6*ZC7VyaOHHg1^~;%;dQ~<{H}8-nR0;)xM%%*YF?X z#??H_AN4N$KJ$=+rQO8&)gSw6H5b%Z$TRz@u8Y(DC7mQ))m@R!m2`8iNZxMhKdl;X z;c2o9#-i>VD{SiTnn?E{<Z(dX6Sl)1$^m`s7G)IcCS_gT4Ogdkr1rO^d7$@#T1WZl zr_z~KbgJ%~;=W1wlznm<tL&RR+s03w6_0&ff_}&&bq6oM*Y{q0UclPP^{0J-@6QNd z@gwEuI?)&Aiixk`V~vNEgXL)~p<U~VL-{!-+rDt}T%DB9whztwk=uj%2X&vAI<0jD z?(o~{uKWzVWjoQ2bjLRQk!Mj~-_p*99>{%mtcM2&?`>nRKl-+}y)AUIjDgfM+aI8v zcqdxA{ARfSUCnKWEbHaW{~-Uqui*2a5mQq)#URpXf9GNAmi1*@i}&rA7o~S-e=Wx( zi@EP2wZVQ#YGa@4&eVgaOVK~u@OxXIW8P``q71(n8XRwz0Q0{n3)#!hrCAT$H*nmR z9%7{)(~C$44L_b~Sj73JkacQ<XYrM?Rj&QiB{n`F@3pNYXY|ZD&ksa@sB8OC*Emp| zi*p;skoIpO{gW>6Rr@Ebn|O}EGa{ZRbN=`De3MzeuE3tO|EQ<#EdWP#XGW!;oy0)G zn7`sx6})NNa4s6-w|V+rX|lcQzw(E^yPck)E$=rZSz+VJj($GtL1(jqUxW<g>1*z) z-USJ~o~@EU@jQ=bb<4P^ZsYN8wCzgkn~;;R(U&)ncLF@OJjD{Hz^B?f%G!BZ$8$8S zfla<w?V7EzwSKN+iD$pICI2Wd*0d=zU!Nik`X<}%Kt7En)XVAZMS4e(-dUt~<+SI` z4sy3{>LclgbNZLL^V>4dja%k3dNVEWy#-8~%fQ2O><v5i-suI5Eg|!B;iGBmKgE8J z{$Lq;VBW<i+qW|(euOgD^z_et#2e=ASW?|TWB+{Km7ndG&p(~(zKgp3x$cR%ZqV<& z;==lD-%LNeq}of757=TAL*)O^iC9D5Nnh&gSDxQ;EO$*w|Jy@+bs6$8|HbqzbUg70 z{aH(yI-$M!AM>?={5+WdTls&8{~ge&4({k|^q4Mr_x{dC-&*pzSU+0G-H+ZStBtRt z-mYA)PQ!Z2Zp2qyW<7N8#@v=;iZtmPQope08--!qVD0yyZ6Ca#+P6ezJ=0*ob0zhJ zk-y4TnwjGz`m(+EY~n1Iyy$r4?!y~^zY_Qj(4x<<uZ%}WN*pI#P{jl5fRR@3ZL^Lv zbz@7N7mOXY9(_#vF7nO#7pn(3z5Rk4CgijEJ4wrH(?1Q2{B}Q3e%K%J{upt$<qzk+ zx{s0iikyX0&R1m|le#rSf46hKEc&~VI#+>rW6@vt1Z=Cs)2`3f%YJ>b&(_mcqMtj8 ze(oyzsZH2Vwg*yMAw%Nr<kRHe^TqXp-vhs2o9PJtp3{cEo94*h<=jCT{52-s1W&Fm z`0E%k7yerBcslibcpdtruG|P++Lf{30PUoC1A4~V=pOZVlzjcHapNGgtLJy>8}k@o z4A-Ju8~Ve-p8Db2Lh_e$pQUl6aqcC&W0T^^{wweUj4c;d>&xO^2p-43Z=W+ac-u9G z-#72Ji8B~Whw<ai!S3Ywbe_Fi&NUoqIGc6Fz;8O$C4WEd59fAGkC2uJ9sMh+xC%b# zpGM)2Wy6%|f81jpA+1a<f=|lOyv_@5cx)x*^2@O^;!e+kuOeT#Mj9J#Np<IETW(+v zzMrf-d?&&CRK(-iM!x}VJM(}Q#`Q7bR%JNx4v823Ge-2SB(2QYdrW8B=6Ad&<*&;5 ztc9g_7={{WPW;;cAO;=H_Y@*)*8+TB!I)!{Wy*+e%ZSglCHu6KcKx>4v}b)EeH_ho ze>&Io4$}41lQw)wU)0%E!;zkAI4&!2gnv^mH%bTmAiha4;50rrZ%8~&vLN2EJ@r(X zeVCZUu_%1~F5Z1gwmG!>@Mg-RjQ4Jm-fp9>8<x$ii!qN1y%K(S4)E&UysVd9g<hHt zo!*RWuKbgV|0l2q=lJayw4XM%P+vV4<_GVnU{0>VtOh2H7v9-NpF5k#5t%;t<%Va* z$G2&B<Ru)mqwNH|HW=`K-Uj~lz-wD|J255?I}w*Oj7;%+vTQZ7Pi-N?GpVCZt;zH{ z*XG`p!&}Hx#@Jq3N40znd3D>vzV{qsYqRLUKcWNrzQBJe^AMj`=k}P7>`D67h6eqF za6x0}p)^LnkD*1Ipx$hDJWBi8yKwTN-p8fT6m~Ng+q)Lur`>)pw)e{gj?#wwzMuM` z&fC{mL)iFSb+5sG+AVDq|JJ9^v;WQm>M?Ab1AAy`cVp$smEFI!W5<qDPC2C`;`0Gw z+BlOEcaPDxG~bpEZ5f%R_w6I@G;d|j)7SO_r!LWUy5CA)+Y9~H-`=L&cr40|>+AK6 zV=R}B1^hd|(kI)-S^8+x*r`4!#f0d9W2@^P(uVD)IfgLh_@FNmr@XaIzqu`5=knrQ z2tLmUENbw+2zGB?%(q;p)~1X<6TSV_U69`UR_A%l8-m9%2kLF+b$`B5qi<M1JEPgZ z*v|e}S3czV)Nkeb?_-{Qv<;4O4OE?73=OBVrWd?Doq6&UA0JF>*p|tE`|145IjiYu zaI7UL5B1Nr_{5V+2YO;okH0#Sa6p&%oU_VPWi)_{f`)o~#HGiy=h}jJPt&iG77z0r z{xhAq4bRor@i8tQsAO5K_ad*fKjnHo^e37=25;)PJX@9a{_yLw&25$IKIWY6gDTT^ zeX7!(5!Q}u*ZVg7e_MX`{he~pBlN_*gjhch-sl6=ImZ~s|Ln69k3*le59}b(FMKy^ zTf)b^QTWeU;pb)e^u9kbJRbb~44>|QnFIU@8U6&;Z{|Y(f(-ASGIN1<-Ov8^&XGS& z){BJqj<y%%wSxPN1!{UFFVD!ZX8?=dr8SAq&H%eO!@5R!dWQYf46q{^)_bwe$gqDj z1MJ%}?Aw67Aj94|1MIaK_F7=)XV?$V0J}58?kw<L+XhzMHMXhyrBU>CfH)<-`#Xd! zhTi(GPac$q)tSA$rY|FY<BUuiD_oz{=DvgtwkR8EQ}#v51}IxKqK}`n-yUUy&zzi7 z4O0FR{EF)h0pB@N!Q+P#Jn~NP`s-vT`PsJhN%{q8+=ee`Njr9BnL21J%zP@vkCXV% z+jcmm2e&0ZqJJ{JoGRZxS?*Zqx}#;63|4o?wZK0@U3rya63X<qjB)8(viiBL{G8Wy z62BzB*Sv*(S9=Wfe{7ri#P$8iaG>%7={@0~!Le-!ytd_;pxy?1r*~HIi@Yym55JSR z09bi(CH<AI{@kB5cVh0f4qJ1al_%^QAGDn)bFA&`xZ$xfZ$YzKn^%68_x7`HPOQCv zf5%_tAdT{ewajsS=!Q>D(HHbw0zJ0tI4MnjchGiP;FV|0g_GRXgM~b!2R;6$H6s3z zUyp0Y^Z4g1$dR*1Bk!IM@sA(n-Ns7KzVLc|Hurx+hdRIFk8`XC9DJX47nAjsxqKwf zPHTr{-|;7h-;vjtjXCr=(n?zgCgGOc@R<3YW%OTJUP1fv!aajjhiB`@IppN`p-tYD zcInwq&wbX%6XjUOQ;a=_fAkYozhayZ{qM^CalK!-3E`9rZS||G<o(lspUPWKUMhp{ z;?UN7UY?)fQD5MM_f<RqUshlP%Dxw!Fovr4CE^y(Eywz?@?>s3O|G1EN^)f!??J{# z^a0YKTph=hGyiFyA@Pm=$+LFjc{%<{oAIFQ4ff0P$nsHHORI83{|}UKj>7@Z8HD6> z0!NhD_P@Zt$$H2?^_^H%*<1c+|E($?Qn&Lu$q;-_?V=0PU_6@ig?dfeovfR2C%edX zTb0}<{dcTq`wilD{#(CoU)8w*`YJAM&b!-h%I8b6z98#c(tU*R_@K5BJdSdGd>RKh zPw6^~`O3_+JVYl_+ILvBr-1JV-nNGat3AE!Z<38)@Ve^Tw)(>%U@YV0X=VSw$K03o znUtr$3Aqpp_J}v~*5c1%{l{3=GJRF&YpStB-H{h(W_lbGhT*5}`VC{@6FuxFn06gu zkaE-7|Eio`mFZGHkI~2et*LGuR(%)NaVPl7SkM+W>wDh=dCf(d>#)&hWq^M6^&-zr z+IO@1zDp`+O-I^G*sx*cxEC9<ywb1Ax2s>sH02M`&s5)W%JG7j%=cr=Q-@33jvH%} z?E{Nmdv~z!rT2gf8|HQe*7W%qqeDYFuNZ4P>Y8cu?W<{g6Mm}Fv4!+6^o{vTpE_~8 zaY6r49~a7Y#b46zUims>dD@RP1;;V<@pa5oOW3qtmVJrzOqN}Y|8KB9g3aq^(>lbG z?bBpX)-7ehK1Idz<R>aw)Oj3rUxUp!uIXQ1#P~YdJ~Rc4@k9UM^%M8Mbh@0%^5v9& ziSlw>Dr1Px;+N7`jw~5xr}|m6qyD+~(2fS_yMr-zvJC&2cvASsU)ocYgLggs>crMM z(PQhsk2$gO4qH<`+RuFc7Z7WxBgP&{Kls;{BR=xpnK$LLfa<$`T6!4|6TL0;JK`U7 z^k8rEmI>>;i@kp2n&eU1j^kDMNY1<-nCusH%Wvy<EV=%%cW`FMeY+0&v7T|?cI`{7 z-*jSNF|K=#G3JS$vr_l$qvL}0^k1$os8?Ug<9v);_C?!Je$FTL!Pr~+w!1zU8%S%j zF=y+~F-SZw$<NL$jlYd)#pT}mf=qLLp5Xh1?Y<QtO|fQ!UNc@27eWIzf6#HjcjEju z$iE%uemh}*7T8q3jeOMw{q{h!I=^snj_FFCybT^mOB0{uSn-a=gNe3yzCzo9r+e}@ z;v;Tq7o#_oX{&vV9_vx+mhCw%C_B%u``*eO`T^=X_LlVM-?S^`_p+>0$_^b&vP*uJ zXU8!0Eyh;sSmrZ)P2(%)w5r&FJnyL1j|H5uIOENDtc7{rV|^a;OMa;{>Y8?E{AOC6 zK!=k~q-S&@ja%w5<?3@?H|lrggdS`2#_Ns;w?Z#*{1L|ZBlP{q8~FVYzsva*`m@)x z{X~}zR<?fP#BT!=eA9Q*w`3<D%5~LW%Z*1rFazxN44ZkH_?_mX{o5FKl;O6CU(0o? zeD@iu{9m2{=P%BHvvY6?=g$;4I|rw5uFrMVg|*1EUH{%v)a`ib6wcK}-AiYv`^KVf zXHi$aw`*&JeC4K1SgwzB4&XRAge=T6&W{*ud2ToIw6zlEifn6tmCqT4A8u!B&KGC0 zHTBxKcyjKQbv5~`LRZ6oNwaZ?{rD2&Sm=<t=h%<_r2m<8I_4~X8ztiE&}aYchyT(O z{IbmxkmH*e8??DWp5@ymlVe52H{<WX5jsB%A5E{#_6?osE|_`zs~h+R=0;WA<QQSv zxXE<tOHSK2@i@0nV=e7dejw$6+y0s#<4p2J&>FDB*?UUbUB9)i^OBIcG|6ZAYyb5R zrsavUH!a@B;d?2EPxCB&Ro;puo2st+$5Z1o^zIeLe&gr%BtAoTHQr9qF%@@Ic_odG zeI<O9MeG#*Pe0af{#f^Ao;j(@+rDNRlP`K_=B?wNJWu-(RUi7)zbhygM`{~>%2)M+ zc;vj~Q;Cb*`%%x+c;1olq<B|<W&F_&F7~V)8>NS~(^`hQkKP=yjxw=b&v|<G&wY_M zG8XuKb7g70i?UqHy&-U=^>xcHEXq5uKhIrR*KyEuXr_DnALblZwbl{mVD9dJcsyX8 zQ+bxH)PH4@`LIWQaLvxKT0Y##Ij?l~nEZ$6gJr%WANL>%@7~ZP-&{X#x*lAfy8}Lt zYoVv<yeqP3H;$ES2O%%<$phl8r2ER)y%h7EKUwB{)Mw}VK6^J&q6J<bA*PJA56iS? z_ZQA}{YAY%4`V!yIsKFPo-yR}%_g=)Z1`kN2h%($?4JM2DE}tyug!4bXFhe|rD?xq zAm<PAKL%Wy8^5-i8xx=PJWif^Cw;$wuNS7DzN`a&9cj;ht|uLE!=#7F@93%Gybj)z zjJy+&)qdnM1k5+-=l=g%#X=)Ik5DJYhP5>~eO@YaU%R<`+<K=oKTrnN8={`Hp{Hq| z`(pNd{2qaDKTyGq|5V-&8wGw8c;jH+`95G;-BJD<DEle)xvXpckEHe3&an-otGhSv zc=Rhnm!oG}d4KMXM{P&=W`;kdfOjw2yHx7%;<YX5cm$iXUmg8^8?ri=pZLif;bQQ* zHYjfU@qgfx{dC`4-hH0B!~M#I*eu6$orAj%d#~Mk;OE``+!O18|0b{@7xhG3Ka+WW z70+Y9$UAv#x}4W&<Hl0z(<fOQDa*qzzk@M0^j01BSsI<w3%_FI!HJF3*OoW(tnFSw z|2^}pzNI?s1^I8j^6f<D|KjQD{BaAImi79NT_;cTDrA@CH*KAKjP`6R#-UBQtr$n4 zZ`yj{)s&b0b3ZQ82A$G$?(26SzM-Rf|8a8-wtE)XEg4puVxD!_HjE|piB&9J*_rEQ z@_I4wQ)T<7&Apgwr#qt}e!$Q4r1W>m8~f$_aX-9{bri=4(~c|XM2i2*^)u%e>YP4f zfIcXD0+Al|>H&0)vT^f>K^`Q%Ki)xTSML?ni?NBAKj~lW@kod3UFxO%?rBzb@Kxqc z{XB<#|8Ul2ec40aGYoC_bN1~l;9Wy_sC8*N)BMe*HotrP)fv7Y`iT>cJV_toJnv<> zKeU}<3;Q?^n9HbZ|5oOCTk@CSivABmqviMfVb%Zb)Z3nM8E;fFXMP54(jm`Zk$I)O z7Xzz5qMwQ1&gHb}P2{^S<5)39oqx&mQtdHf491Hz&+p7}FZ@dLKG!9kvqdZz@TDBo zvsfRv1>YI{xe1!DwhWqlcO=n|{%TXPma&GljBfUKq|>ow3uT+3)4u&`UXNG>o!+Zq z{ee98sVng;z5&*nP6C(ru|>YV!nG3bSW0=lv<(hzXeJueyKfdWeCZD=SxCbw>e?6N zn$~%h-%n-Po6mTBQ2F&|ndob-qK@bIo&=}o1XokXm`S)7WjOOfe=o@Ws_QRzGxVI7 z>n#ZT;C{m$)ZIZF>fX+r)*i+GUf^~%E1mnJJbp>@PHD<8O>~i%<B0m*4~?PUKSf>h z)b(%V_KvoeRqu2zW$YrZL?@>0ag{n@ys?^gGQTG6KpRvB_Rl%Hb{Xra-iJV}(gPol zSl6?5yP$V9bnTL6+stFL{jd$5Icqbumuh?HMxSlO7!-O?u9-z0>?+aI4p!ZFeJylY zxo-xq`JU4VUFys+j{RRtxnpJ6$vpB*yI%dn)YnG!iOj8gOlSV2wE5teHlC~j*P0B+ z9#XpRaggU6&;Gmk?VtOXYK)YYW7>!J#wjHojxpt!COz?<3^B>r74S^HmN2b0Fi~#Y zA}<}|jcL?P$L<f_SDlXx-0qKFHCpNO5ByPOm)=A4I5ehjr;^s@9tW2`OTMeWu`bG& zjT;+zZ@$U5jc+9O-AL@asd*x2!1-=AeBKCrdN+eLy;ZemZB+X=F0l>M>eChZc`JGB zp-k?*ch9n}x3S`By7SaF^=a}~oW={2?ZAgJUeL!|W}Gk+jN_5xs`E*4$Ntx4x$aDH z%i3J-n6WO`)lYWhy{)$*bMdVlG!Cm|r4I5w?9H|}Or2r!)!|jd!y6myeeo<G<X4?P z_>N=Zt*+LVbT*+Qk2wh+`XFxKtByXaFF`}8FGu%J=}Uq|U!u;xr_99p?;)plw5=zG zRd0RY%>S4#orCS$=i$XSB>s=EZsxNxa_ltbaL)bFY!}MESRd#y{forj;tc-Ue#8jL zSHpMDGAp}(_}9uOlz8;jiKZ+casGJ5S*`I`F{tsFIxzwbBk1}%;MA3+IUZVXzIn{w z^zFvi_Ve@?vWC#ua;RO|X)mv2ZhxE2t|b3U@E7)7U6Srk<#9^<>%pJ>S&wP^Azt-G zy5j6?MRye++qZb{PkLgHBjn)tM9i4hbUptje%8lREFk{GL+YJ&*0w`yi}oE?(;OVW zMZUZgKJKPJjXk#n1K;dZCw)RroWZQ*`me+x(t#eQcx+9^?_QI88PdX<cUqUZ5?YdO zp-aMf*Q0gQnLT{U8sz(;9M=e&^ay>rGUId{>z59ExN>xFxPsX>ITpH3VSMj69PQ7` zdGe{Nwfm#=;ZFuB2On!h?5mL8Y#Z>dmD9?@XXm1xt1-?Lr~f6qbF<6fqv!7Hb;~mG zgd9SjTC^$5CUtFeEA@-#HCu_vrsQyX-uoN^R-d)0iJ#}Lht>Qynjc2C*Bn~3kMzD< z(T{b9JNE7FYV6y6+U9-#_-OC?-Qyc6TlJ+|CoUU9=f<v^=-+qU#2WGz^S@~Qb;RJ; zrEi-z`B!Iq`5)we0srnfb@SiozYhCny#`sm=i|>k5jvw?O`|p2%TTN6&pz+fDW1os z_fI`@t=sVun>>t;brH{;=6l$kqtH*;Dq?BpD$AjzA6kre7W2Po6#84_fxpSWI@Qbn zAph=_4)E_@sXC($`+pMs=%pVQ(~mWjtEaA8C4It{`|~+HbuRfOb&mFg?L}`xx7bfO zrp~LeJ^kJ`+7O@qAYz9%exbTYU<3Mab#52`)3b^6D0v(B-;YkLB)yWfXJ=Lt2PB_S zi)%S!*E0%CC*#g2FurfK_xmp$FZ1@EdwE)eEc0fA^UiW<nAFS0*0et4vtyNd_cQo% z_vbpZ&FgQw8mwJDaOt6qJ3jk(?C~D&Y-KNfY*AOAW(=WR7V@8Xi|tvi>|&h}Ssc** zzMSp98RhthW}@LO<HXo$o@Z<w>-N-3vFkqS38!sa*Y`XEf2;@iEIq~}iRbWGx`GyE zDJ=8($+H;)q@$j7Z+aEyN3t%f&$pg)eew^+K#NoRE7CrJdTJZ&U#9&f{jq*TUJsJ) zg7@N$SV{g{=Z4M#ra2uZ<n&@>B&=&y&ZqqrRc~$&AD`%T%yP}fHYU&QkQcGleEM$L z${hb1@1|$=89U*nX>DR9&+@39Jl;s(qFvVttP`^7p5k#DtAfW-UdDv@?Bw^Azhj#E zmu)unCF;m`-+yR#9zi<v3(J{5>KBwnd4AKmuIG95d!C0lBk$QSpuGja+TP3Io%-%x zQLMiu{YN&|H}>vseK3`a-}s`7_@dOi|A8zT*o(R^9_Iw|#n?$78P7>RGx(uoBlscf z3D^13HgYWT(wIq`_Cs5ZHTSU9So@bwby!)1++Kp*Ob^hGJTOM^InJ4iuZ15q&vkQQ z=<_6u<v;kbsyxnAmN<+xgn8hjY3@|*6M@S;MRf3hcX@f{_ly7RI$mYJ%H*Hnqvs8N z6Wr=wyMDzvlhiNp=?lDL%{^r6glx~IjJ2Qx3y=r8HolD*(Djk@-;ZyjU1jU}{ODgv zOL}L6KA6{Ew8P#}`VR1HIJFz`&%>5_(FN1Da(`trrx!K!SB`BrOf2KBG{=&7PIrZ2 zmy^%jXO-3@(Qn&i>>9t!J6W3_8v8S1E8$joHzx1c$KKFLeqNB<YvpJ4Q1~}M*Fw_A z@VK|Lv-_J!n%}c<|7m`)e;jvD1dqid-*^X~xUkY$b<A|^8=a4@@HzZFJ~sJ|_!bUx zx>VOSn(qUbIwpLqNwHp>_Ut+@s^WcQJsB^KDr;n`%_?(sHO|(%&Ya|i9$LnJ){($_ z9_<(xB=`dF@>ca;Xg~iYUh$}h<=(1`L0^E_($?G)^PL;Nr{|bwy#>g5A^-Za-sYJT z2Uu@4UmvTiOgqP}^5U6TSJ}{J-KJZ`9=_k`GX@<1#{%vR3SZkz+CC5Fd}%RlzIv(r z96yZB^l$pJU%;Pz`+|qZwM+Z@Mr?mE{dt-^eXn_=<au7|S@L@2J38z44qw5zB<xcc zK0Ka$DEXex86aPH^X<Dh&ex}q=NhrGo$Hjw2|nxp-GlPkHUgJ^;`EG5K823iFX>CN z%59#Q;T$KO^9_JE=6v$RJ}L`om&T*WLmC4<jnU|n{!(5!eg|DK);k_cqx73LKkB!l zy(H6H5)DZ|o9e(V6F+h)b%9Cuy&>bMH#9>%c^~zprL1Snqa1hUu_tuJ_xi$S<D9yB z+1>o$q29(dkIO^nO+DCv^G^SbfB2u=AJ?Zkk2(>%vHz}<IzFAi|3d!frF{H0^#a!M zsM4n?TUqeHb%$Pj^!)MI2lm^i^4o6_4njL)f4Zwmos{3+Bcz?GlW)tuW11Yta$JaP zCuKEiY+sFWFWkqw{KU>DG_HUAgvQRt{r+BW<A%qb-<*X0{VC@Je6LhqrgqYpz&n%3 zE6IX(88Z$#Uz*>!`|vBByN)8`Iz0NJ4s`-^UY_6jzPvhl5`3`!SzWsiFFQ{CE@1j< z_4OAW-D#ZM6EwP3nDiLGp$|t^$)CxaR5t3qVWp1)`R>P8XS}`-ES`vw{~+s2tW`D| zTi(}Vt+JQ3%01uUE}2er>QwG&S;~DZ7qaGmVa40E^ldG8PJ*ZFNGmh<u>8L(|KIzn z>RH*E-^%|TgO?t<v-O1pd+!@AWvsg;t(hAeyDlJJ=jQTM{c?@mGS5eBpnMT|zKilS zah~(Nex4Ttv!nCOiJwKL8>oL(iKl<}xHwmd6MNp6%i>#do#>sm>-g{gd}8W#*#^_y zThL+sxxlBj4(QxO8=I&z%3g_bxteEf$T4yW_H-p>>bU;rD$?pWdoYtS-nEoGeGj@Q z9&z}5HSnF#qyPK`{O7ScF*E!-GJMG1d+FNIfzCfKI#$>4J^|iIesTA}7;*}losaKC zhqN*O^{vTv=+9-hRcq^;;Y+}{ZsWMHCFjYH$lG4<lsGco;o~<Z^n<pq?DWmrhtHOE zB3s+*XzV_GO125%*A?)KNNc-}IT7Q3qr0)E=XIB+vkSYRdzkVUzy8v+rl+49<yjqf zUVj$<tMc>e{GVhEUVUUgai~7NyR|jp+i_~;f3|h1@6x?xY(92X$=owRH-MXO&1U`K zyj0&vu0I0)cJ<%XrhaMn4<n<%cP{v(T^i+6vc1w~`nPfqB6Ojnm*EeGNE5Fd^83G@ z;plE|Jv7{;|IO<Y&pMHLH8x#OY_lz`e+uszk<ko4ItzSB=Ry5bL0hunOk1K8o7m5D z(0Ar{LErQ3Pf4He_yx}*j%A$edA>NsVc%TqQP09&er-24LI1YMfBLHKu4<e)@ms%N z*@}8LSr?i2yqvvLeFZWLy28FTWL(>8xZYdf3Z2kLP2z<nbv<bM(HUsEvcNN07n)xD zikWFzF#}CMQs7zzz3ILU`c52tco{wfofx0i_vW@ktI#d^<hwlbP#^gpz*EvP$)Cn_ z{#aMO=xbbu8KqwEf<5plUewx=FSavOYiF|0$7$!>q8;?6ujee*E}GXQo-OF#dg#)V zS#yJ~qxweZTAgUzmiF_F!|bQ;%p^Gapse36e`>IsDU*-t&^CCtT3FKhCvm1c(%l#E zo=>gpH>$WUy*sCW(;oLSZU=vi`OI@HUqF4wxKCgMrsd5Y|K+(Sb`WO;Jo^QG{gf?Q z0>7bGm`8w7ru#?nft2+YWnZ^!4Y4x$14aH{<vLxh_mAzTu6wd;ppWtENFD!u1^zmo z&qi5+!@Y`Y$lnRwrzvCjxueP5Y~*)m{o5tKpr>U&;brRr);metfA*>mn(kaOcK9vJ z`2K^u$A7Y}mex4sqwfl&y3OkQ5Vu$BBa`=o%i}fF`xtkxx;7_2Q<{5GJ6p@rw;*k6 z9=v|$4VSYnaP-jz@rM8J;ePQ_M(mCD$=8zS?~8uJbNN;B{A$bKd6WE-=kLyS=D}-u zZk#L6<=3k+zkcWq)A@CGwSF^xW9HWoIOW$6{4yQ<G9CQ7aRz>+y722p+FMuSm-;tX zem&QQU)EQT?@^EQSc|-pZb!^Ikm>!n`ki51mymz^FWx<_97-O)SN{edZLj3-M)MQ@ z-cMY+ee5!L!#Z)&TlqoEvUet&KQ&pms%LytZ+C6>tKv{6_A@5v+id4Dcy|Ea-Gpx2 zAIHy|+VFchcrDjH@0Hi^{Xb;c-UN<IvRrQk=P+=_mHMAsDf{P4W88HwPcNel`^G$P zKYf2Ntv6F|CY^q^jf_g!tjIbo-{o(~_eHi3-{nim_fs=n>TmE}eq1{Te!QgM$FF97 z{BXgK=dx|=h94sZKX!xvlQn*XK0P0vFyHR!7`gP2_g2<zJ@AE2vbNSI|DHX6>c0F5 z#}I5ia9HQ5{;!UAA~R+DcRBu+FDG=oXG%`_9%lS}+UM1G$=7EJ++WVPmBVvI{{7Db z=gO=f#!q2~{+E8NyJnA;r*S9S;%(Fo8x7kXfZo?<+p?c0Dm(ZPx_yGrEqQR6XUjfD z`cLBACu2#EHdOk+3o?A@tvXFxJ>HXOTgzx`{sq;3GO>QLY1{qZ>Oj%%-}?;j=NYT? zGkyW{uB<~J2hS+&YEK_Wf0h92`#RFn)fyX*F~L3r9p#uHJp=L++n1(=q@8<kp61{n z`1)_9ZQ7J(*THYkFvgBIPR>26^@UV7?^AFdvf2v+7iSRmxRz-D*+btWTv=aVZv5Yx zf;lKm+#MS2+};lk;21O09V_BvOiQpOzJROIQ}wf==U_q4G4<QflW3kJJ;(Gf=&{Wf z{FC3Y*5Nv!ac8U<xF+TJ|K^Uy!L)XVzHQ?dYYxiaIcT-N#5x7fiJy#<p8(hK>cpHa z)uA2chzE{WCuoa0EMXszPW`y_pT!xQL^nFooA0{+8tcYuk(cAQXIP~36S;5LZK|)# zN_fvrP2y>y>#UD_jeGGuTQ!+q;4kYxNqdeVt|jTqo_p1lKYM5PEvfvXsWBTp>PtS3 zcWg@dpDf^AtFlbH{92K3JNmV<-j5XJcfNM29sF^hzOICQQvrKdZbN<kF?bWcnLVTQ zjaX!z#>=yr)0}=w<%8~m@8z1zhRoYPoncKT@g9CV-)mO-ljeWDna`U}J#FGH@_iS? zH3VVg@6;ON4HL)1@wHQq#Sv>rUq^<{E6Tncy1DAh-81xM`}fe7yK8+3I{d~_@R#!{ z$ME;FnWlR(O^IIkkmiHT(d2pLrMX+P%9B@VEpFe`bK>0?=O(a&s@@f2-{x$xXH}kh z8F2{z-{N^8|IeLwIeQG(P22;l_X@4z-+P5V!GD}TKM6n3iyiIY>>GD79K+B5oN3=T z13z1tpDF%=-mtw*OHZ44?xHDsdGPm;%V=IJslh$<+9|ld5DuEU`nQiMTlZn^qwUb0 za&7W>x}*N>Q)Z`$qnc-G|DlT^Kfk@8FYsC4a|d@x>X&?8$n%;1HYMM6jBWZ>*Yhkh zoz`jLVfZq~Ir?yTCO`ZGlpoJO#vOIW0{Xiz^1jsZ>eT%(@x$}>!;IYrzu3Bb!u$L2 z$v2mLNpl2rr*oF^LtcE5y%Wb9_cq0)9>;j=x~6M%H?r<nuG5w6d=hz-{7?G?@Uy8N zP~SCp@w1mYxmFx{_axs#i8V>vP46`_zN<eWZ}-#FIxgp*T<djj+C9$R2QEF-D$W@B zzG}O@)Lv*XW^nJoc|<R`ecx<(@w|#>_p453%{T8&rEfBDp8bezxo@Cv_S-rOtnWS_ z`v~!E5b1qSgYUkHbD!_v^N%ighD4afP4*_5+|hwOd(OnY3il)Y=7u~rw)0)cZ)baQ zPfVS3%!&QE*qd`d-S0D{SR6gp{=EB<cr<-aN_n5mvocY~yw5VPCww6C2Ep%lkZfCh zE#ZipFRGUro1P53JRn|3G4}%GD=*sNAjZ4dGG!>7-;NOHY<1Az^Qt;4ChOGk%a3wD zJ@yAz!jn;A-c|im-~92NMR{=v|Bt-swu$c14~>l`o>X_{50G|G$~bIQ%CF9R`aWWd zXXn5}l=U_qp11_s^~b?0W9?V|Zsq%WTmLh`r*%j8!`$b9cX<2`F_Cv?Ji|9(7v0@R zeo}sX44RgMcR6jSGnddFvOB!0dFI6X*^^pMKZYn1);$ULhJChe_aD>?eVOkWFESt7 z`e=@U<GbOu&(lKs+NJ$@Xd9%I;;d->|8-zb?YEcY!>_^z>S%Om}!G`j!cdaAxb znmG4+K>R5mIQKz@Df1hQrY-YX9M%t9;?+*Y6aF;#WZ&h}YvGe~l9C4ft<T0cA-}0M zxq~jZD_-^Z2jy96_c;7%{^O&=z{#ihuA=_qcy*(W=e3UqEA8U<O#Q5|&23||mLpTY zyETn>_@R#0=V!-Dy|f=W$y0O#8R;+7L-kD^RUb>)dmdoj(W3`?`Tm(Y{r1VRU`48v z{0%Tm=fG>*7awb#$xmrdwtKw(#=h(E;9|cu`sKS_*lN0)hc)OlhN*A%H?23>cjOWJ zsK3xo{73gVbH0Dl7R{^AkzNAsREK`)w~j|&iU;s3XWdl!m7pQoO#Pe#o<s+DzM038 zz$3k-Jimghv?s^u1^5!jFzuFe2<hyVe3*>=n-8XQtO*7`<T<?#bVWNbPgwEz-MZ3W zIp=fS^_=R*hz&=8QIAq=Kt11qr@aHC7x3N5{u>_?m%d70=h<ZIk7T->bCzwz{gGAP ziq!tIoWbg9f~RiRIks?5Sef{4+ylpfP47Kqc<(sgeH?iARsug~NqA>rc3OH1_)*|T zj|1=hzJY%w@XAiTit`xTe{x>qNha2dS>%oLWpP)xvBkzbUM2ogFXD<47M$bh`=0%m zr*C|AqDQvzXx2&7v)1Fgn!-HwJCzR4)|RoFbe-b*k}{to?iDfTDBvSDT1*@ecZoUn zf0}Q5s`H=bd!U|)+IH$P*6XXd#rDcrBKY9>S7}2}nU8TtAm0mp#(wql3=V1Dn&(;V zXr8IQI%(Ws{VR{t=ZIrH|0eur+Q3Jj%d=VwXv6qcJI1%|SwPxYvdU}U-_VhTP0oh0 zzVQAwZLKEg3;qOrg}eH8Y)X4R1D^gox{{vpk;dJ|&!ICx^CEQJcV|7%t{v26ao0cb zCS?A8aJ09fxf_4I`|wY+p|1`*6KyNzK-<r9CRo}wK-V_?#teEAbOqmD-G;8^1j2Kr zZSfpv^Q@_~bzI~(<l!4Sxs~~u{<2QzBfQj5Z~Fx!+$(q<=U?Ha@XutQU^-+}uQL-b zUo{7MZO`)@>0kfF8ng5pqiLV=*En=l8y%?A(e>IXy8rw4K=-?;dp!NLE$L4G-y_|j zA9v(+yOP(<C3Dx08}X^fqdV+s3HQ`EUf5RY<DTMD>^fgNxwEF!iC_L6czfp@XtX_f zoBm7QqQj1%b(-7JyNGk?p~G)(LvKg_-1)lg{{qe7=lr&6`8^Wja^u?nkG%Jfv$Lx1 z{m-14A;V#S69^cFXik2~fCHSspd*ejLewZhBSuY2)Id<9jWs~LqN0W*B4UsTTpJN( zdP(oah}WnojWLZWv6gR&nhGk7w4F%^V4#{RQdF9JKkxOdb!N{q=S&8qf8FzXo!9d` zd#}Cr`nA_y`^U2%#ZG%TXQy3#5&gLJN%Gy~<GY!sBkttvC$8UAEL5yEYaL(f_F3F& z>uciDVmQ8O%{)go)@mN82g5hCx2j*?pl@BX{zDn7L%8XuIsZ4SbGv;X8yuRqw)bg+ zj*Ui#_7fzq*d*~EJkZbFAzbjqJYC>#q*LZ>*w;I~oXKH}Xxt_rw@KHce8*;887EKE zcQU|f{g{6<gLKxTh$T}QM*nB?P4aW>*DlCc5o0i(n4~?1WyznjMxg6vjU`ham~SGc zq_3vze|Ri2R915yUUrqrZjn6YCkChK55DlDXBG>En4iE7I>jg77Kr$lb6z@y|DO~5 zJipwZ8K)pW*X0g)WKNGg!mP_3`#&?D7?bf1E@kgzTr55rlTYl+(q=e5_PoFoaBG#u zn3LGZV+EVjiMSj-BCd?~7w^y5cgz(RLC-kNt#IYr&Rh@E^(Tszpjq>oo14m#v+C=2 z8h}4cb1B$Mz+!tA8>vqir@ZFsj~@jeV~OBjqAVSzc@le8Ou_f6`Q9kwHO{9><sNO1 zxJWb&f{R#=`sj0@;U{VbKebpji<7uNOtK~YXG7_`xTlT56LqA%G;~YM$#-b@-VpsU zb@ELb>N=jfWFO2aUZ%OjpXwgj=-n4PXJe<@H*J=26xW?<UpuG#eDI<2&#k_HbbW$1 z;KF`dk};d+xoylgNjfDKK%RU<8@piMcBj_vuh2XO>AZVUtSrycZ0;xfPW%-*!z;#f zhNn+>L{s3*)3(lOD^$NXYz)YI>(~Oel+t)+jz$}EioVYkivz{7Y}ROA@!vx0ha1rP z(+0G%CoAQh@qWlA#=5^&**3lfFMV>J5#M=-C-$G?<D)I1Z~3BO_|U^W(kXl+U%s)9 zj)v;U%EuTt+G1+kF-AFDHirK~KeQ#r0K&H$e8g7!{Tp-J{kz<p)t1E(+pQdHuHpZ{ zfsf#sHLk$Py!@TV-oE#9&3|X#_imCeq22L~af5Xn%}E*F32M>)#GU1T;>@{$#iNvO z_VSFmQyN+me9$m`6dc49(87M`6bI+<*|W;uF_~ET8rzSS(%<T3i9gb^hsX0MWvLID z?{fV?19g)2^CV5{7DgZAowSZ4<9U=i4)?OmSEpr<j^|OzmIMPWJEvs!b+~-zRN17? zJG8ZoBRv0~JRka@kupC{(x8*H`;)YzoURGVOX)f;o=2hUXfJzwz`EVNAf87ltM?&I zmJ<Wk%ko_#qhpk^<GpN0z<Sve<9U>_$9P%3iInpD!gy9$?EXcG-Sa#-d2TLi93=V6 zkAI_CXHcB4F;HrY$9f%n11GIxN<259k8yU|Kk@zfct3|T%d3h%=m%%YU$kG4t%p>l z>!X>U#1|<K|AEi2aj#;lW@0T}k#kkLr*9#)usL*<W6n2lSia4(F+Zqx$Kg>nMt>D? zYNx}ut1L2TRlhz{_Q<{Z_}YFU)|kK>a5~GQBj8k~21i^#97uUhec74k;j8P>MV|bG z#VVgD7WM^B>JB{I8-Ic=`5f<2k{M|w(S4M!r+r-ORiyD<FVm-JIof$0r|Zco!<rX) zilaNAXRE$lOdQGm_jQktCC=l_F<?340X-mh(}V7jJ$<8%@pVu6MzGrwSbQhAp^-V^ zE4O|95ojM3|G>)K;EwwK=}q@5mc*xKHu9jp|J+=?<x#DtKMKrYI=imG86D!CF%5by z>Uwfne3viTeYs+e%gbMX<e!V$TUpThr`AAYFN4;o2ALB-s;t;vw!2>M*i#p4^;Z_^ z(>jd5ZNq8(>0m~yeV0x4T+Pust^uv%%6ivYbQN?>>0_@2YgC*KvQo5}%q3H7;iKyN zp%r^Tzn8nsAOmbBWKN#mGqKp3HCn#EH$`cuYK<exqw^yrFY>Ad^t^lkJK4ES{OCEa zFY@V6@mK5xA!eW~aS3(o^_V8DPy3EX)ORS{(T-BweDg4L1aI2cH-b0qsTomM%3Ij| zq4@jz2K+tzJn#qZM*I=Grm~aoxgPxt(^o;y+v@3Nwbs%z-4NT;&e7G=Q-|w_{cO)i zJ@Ap%(=lyiJ)`+Scskr|_{E9eJ3=;v->&EPj*;Ixs_$a+LHK;)%$u5vw(d)NXjXeE zsy*MZAzSl~wOqw^1K>^DQS9rBa?nbj7iEwgWxgQ40<Gwb=g<ZH7WeqdBdD8p?>HFO zzE$%mc{yuON6kK)2efzMx#+f_wkh865%_AwWdrn`_~>YxqIE>u<U3c-H$7$phoHyp zy)Hc=OZ-R3J$%@q^wP*i<ljySJ=AbYKSxQ{+1Mf5Cv}SVk<s6v!&AI}ZN<*y*CLN} zbT9kM`bv$lB9C&=KN`Lk?MbPJFSSR$lYoBe+5M|U4|yku<`YC0eq6r&divB83ThAH z?SyTjcYrpZ*#)+c*~MpdUWoez`SohKp6|HEe8<PNCc<|#!?#lxyisqQ+5X4SVD@qd z8m<uyFCK-4RAw7Tk=YE%4ErK}V4SSDuA^QI0?$3FFJer_fm6%b8pW%g$>IX~_0e!Z zGcj}EU|beBs=|@d{D5f2cAE=|J$xV8ve&d0?$su^{rWHUGdMYSpht0YZ<+T|bta$h zBkB=P^nb*+*u>Yg*M_vCMB`XuY4(QTD~N}!oc3&RJ(BYBTUs_M)t==?hyk#pMzML| z>wPh6&e<H_CvM@p>nHA=aZ@%=$Udhg$&|D$o_4Bi>R-;t=A_hSOP!*@;yAUlfc=KU z(vGwIY!3u6B{I;wSxI#o-v6D0W$#PixjmN``x=P%@_25^!LlzV@Z6BgV_!q$U7O20 zTzSwOeH>$iqSN}(fYlr#I%_%0W82F8k5UF7sCO9l1^fpR`0$khhb=MJcf5RorHLnC z(53b_tUrG4#d}-5-nTcv(@GzvI*<4E4nE>7@UefM{VLi6aXruMW#RcG`LwV*vjHD} z(N8kY>FU#2QquRj&t*2i9B^L+-=nMSp-;GwJ@2k?A7eZFHi71>IAc80uq$w#D*C}e zyAC|e)ka;PPU?D8@(cQDyJ}ju#&fg$ci7Znt|x4-P4~>j8l2h%*T{!2@=1&RLV`7% z+5Vm(oZ|#1c^MwQ2~8Q&xQ6Y%QG6F%ccjzbp+oeh_aILRyV~zOohF_9tG5?yi83+% zQ(dL+osroPbMn&rzD>!qwq+PCDg13ozQ&#V)+Eo+#XK@~#Q1BO=QI8~&gs<H@f7Uq zxP=;XNj|;hY>v0=-y1T2Abm03B38l9@Fn;k`A8c_NbVLJ9Ot%2z4SHMVyDUidz$JS zFZreR$=+Y+i#E&|h>hgglgRV7I`WkKI@YoeNaIW7hdfp%?OjJMSD$0CpW{Jhvh z$%FoJtnxTMCl9_=fjro&MZ03`*W&H|oz8RY{XAOvvfU2WF=<zCBVT%89s)lfaEuS9 ztM37y{LHZP%(1yB|5}x2PP(2ypk1Z@pnuJfKcEkc^BQ|!(OS?MyoI?k?tV4a*}6U; z!)@1<zVRykJJpHPN9O0E+eA0^w^QG~QR!iGQL%;;dnP7nuSuJDo_%w+rhT-^(H~GQ z*3bS)bkwWk2QxF-+MI*hNX#w4M>_u%>oZH#hc8wizND;kWF^OCvMp?h`T5KII|>I? zKl1>S<=ZaP`XGEPDNB#Sxz}aIT*?yB{3d_4bvN<M`C}5#txMrw^IrHl&G+m=FTf8v z{9Wiz`lhc4n$hVyyv;DLvsgH6pI?QwO6t${<Ix9!>xYhuGi?@EeEm*svzpj!y2p?H z16~7nyoXf}_un+Yy>N`U&Hpx_JM1k__nJ{~bG|4%|J7$RoiG;@I=NJ|hI~IAboU*6 z1l^&tpL?3Wr#Y<6$eiV)22B6b(?05W=*Fz=vBt)HCq9DoHwX{c2Xgs$sGnUbdeSr9 zP5<h1%ci%H>!<neX`vU^v?mH4d;5{vP2B%b_xO!TsypnBzB0?#nVX*X`rzI3*smJp z&d=r1z9O$Tmq!d0d1vMFh~Xmdv|Ju>S<rG)E{{H2ax@+)xjg#ez<EM0kN&;M%N>); zBc4MB5zpoQA+c!SZO)Y?o(sIspilLIAyeWm@G_39=Vw#A|DG$$8Nh+}kz5|%`T#F+ zeLcKd7c7PRewHiCH$ejL&RibnWs82>Hv<0f8Tep)#>w(OQTFemtb7J-$YA6%*dL^R z!TSA>+1(9b8CL}?_5E;)&Q2-^u4@bz`<IPJcoJ>+ID8$kL&zDsrhZ~$_KW<;{S)`# z4gXY+j~g4%)|b#0e5`5!J2!!?#|OBc4?e;d*5l*t4QN}M&=!1L)BtvQ0$Yy{a6MN( zYWSoNd{Sy>5r+m}nj75}w4T&}*8V)L>c3<Bl+`udCSra!Y$9U4s8exut<F+|I@cw2 zQZDQ*`oq9YEY8?3aO?f9TD$p;`W^8;NS~Fqo4XR+!TVzkV7DZ&DIJ`rRw-w3`oFKv z`Z9d|PXmwp^ZVR?+$TEe!zbw7XU1LZ>)=}ofA8lK(~pFn=-XMR#SduSe?9#qxWDVT zncIezgNi*`{T&_SU+we<qL=r@SW`&p{e|ddUzPi?X4Q49y_+N1p~D|wC+c@2c8hqA zb4OWs>@E+{_mK7@beB)GwT>70Sh${V{Dt?^=!&^Sd`>r4*$=!8dMp+B%^Ks8pS>qx z=jWIoBL5uuBIHBN#}!#}MQ-2@{~3G7x?~5;BiXa$Qk7hIuLioav}>|7>_@a{tWv8> zXR+Hm5K*>F*#^F`jGlxay1JA4Mk~Xb8D-#sI<Rf{VD1up5!(?T<A*~&yrYVI%*W<v z4*3w%A{WN|T#0#+PxxhY4Zk5DdloGV6ZvFm*JNp<$S2B<=5u535p*G+v6P89VR!%@ z`M?MA0UzxL9`f>GjsW?X?`|NUPT@f=U4D)A@9_7wCoz$aJxe}o68U6l*JNp<$S2A! zrECNHiLp6!A)m37=@K0F0}sF>ANW8%;OlB2pTk@})(7O|XZ|B;|BT(j2e5B2_Q2w^ zKKdCyk6tk^@hUMl`=vN{o9|;EskzjDQ5*WL{@>SM=d|qmvi_gb|D*c1D!)blX8m8S z=d<)L=w55E`wr;;U;00z{~z@Kz5c(`|7rdIQ~#&*2k(>m|3?2`>;E76@7MoV`u|e@ zgOUSwQxtu~#oQC0m;GLG&>rSN%(iq-d>r?E$vv@gq%TeGiHk{ZQ(596?#Jmq;(zet zPk$s@qWtAv2H%Ii(s&A(ALY^m7k*812{rgb@q-<w@b!4OTy{X6K@;|n(iHqbEBm18 z(aPL>qzA3RH+l}f&v3rsBdsI&pv*CeY*N}ow#X(;kNQTVJFP45Ae%HD*<ibTH%;b# zE40|SURUT3ozrinaHGY>rpqzH2Op!!ChQblq%sJe8p);+&a@poTU!kMD#ohmH`Qab zuV+hZ;B9ui&=~Ou@{IYSk6S#E_4)Ylhy~~$frIBX7SvwrU1{8x_Q_gHEHTb!?<DVt zSuCXbtv^;;yQkS0Nj{Z5xE1ZmjQx_>5%tD;UeFNzZ01id8qCv>_La|thPh*)A^NgL zG^G8}bD?4RC^Qhqpqr3Ke!QXaa`qj7kZ~?HPsbW*{K`4Qg`|Iqc}31rh<EMKqs7?L ztIy$GZ#Zbzn%5z&!e^ml;^TGFH#X3szN_SY*XNa{snLC$PsQ9)MSuL+8vSq7zfXUi zH?nWF{_oO1i`Cw|N6%;DM-)fi%DN77RG(75=^(AY%DVaa<~xH9%}p3wi^FB<(458O zAB=ibjymXLwfA!$?M3y~=pC>7(fHMxWL<h%pCvu;58v=9SzSLC9$)8m*W>X#$H&<R zW5q|zK)v<wo#yzEbI7YxX(2Do_3lGfjpUKnPr%iy%WOq-jL+$qbH!6z!*;PJXvV)` zk7|2n)98?V>wD}vd>%aFuuZb{4H}DWEFZCVlWcv9+S*3&Np2U&-Z-;_`&Pea|E6$T zI_Le%b~`o*ey92;-s#4^>{)$Fv*tr5=&TdsO5Rb9GheV{>YzOduf9u{)gin#557?} zsPD9~*^62W`?d%cT%4Q2H;*{a-O|b{2DomNFFjg&`N0Ey#|aPV_|sZB(Xa)dtM?+? z%3n0!%RDVI3s~?%E8qAvSo!CI_6M?Wo^u#d-lEUXc-Neq{L^n*3j27DzD0hz##<x# zNnx4%a`KueTA(dtNuR>I8XLsJ&hhuyIWzPdKT)0G8?W*;3bO;1<xHGab<)<<NxQ91 z+MRXMqK`z@(GI>M8pNOZjjMG3f0_&XZqOB(;Ik=%4~LiNPw_{Lw@%Y}cJO4+l6_S= zV_Y)}_#{30*|aZyNb*f#Dqa?tO^*M5!OY@b_S52L#4XdAaE$%(>C2VQn9|a<CMq58 zneETDb0>t0_Hd2fV}dWnlPO;@j?^AV<IA2CzMw7h@Ahp7`z9l{1U>K)@WHRmfvCNt z@nJgt1)lQI@euu4LQ}*Ijc8h!$ZIS#rE!MZ=X0Vd;)q5xt$CI-Ep_;3D<}A+jQqB> zzlbS_`4kh|IVb2f(kFR3_CeXOhmT0+<i(j7_>J%tq^JI8w(@A3q?@m)tQe@-U^zS2 zaJ6iZxG`cvXk<SvWzciJp42x5Orts}f2ewaiTaTR{Z06F+Vf_$?HbKVd%{1}(w&!O zI-@adpQ%kBFP>`fj)(Tg`SrDQ$Fp2`YH1FOoa(`@7OedL2pYj%kH$v0>%oE>KV@>1 z9qiB<bE$8O_SVR^MSGj$Z9RNmw5!p4+g!Kvyl<N$dh))lQ~2}g@Xy?irDyLE?3wG& z*mCSEz}~{QRiP97J_f3CFP|O0&7O0<ZMwr8t#;L^dt?PY*g?Rjc98cY={ywhl!uP+ zZ9!AWx)DtwYveT+nnDNl{K!~o3g6a<rZtHU$3oLmhkv#-ftxaU--bT$ZKe<1hi~ih zbnJt&VGsB=^71~1IEeJr&&+k-Mtb;|IS$j}?Rc$hFno)}tnS+=gP!yCq`oa+8r5lS zlK4$NwNbsmME%Gj@7q@D-Je?7oNue8H}Gw#{ovbb@HyXBOHX`TEzMz(6TYpM9`bYF zR!dKC<F9JzhrnGAcI_d2TiA9xIwfu^4v*Wyw&!_UH#qr*u;I~s+w!Dcq;cE4u%AR1 zJ;I+)$G7!Hx_n!+;<owzj4gNTzFW9b-`1zJ4d8d**5`bMZ?or|ZvzLs<J)?4k3B&T zzAfO(&P%;E+bcN67tjhk<)I^dThJ7~tr1PBZyO6uscq){?O16F{Wqd1^pBp$LQ~kq zvz1fmG4I>Z2foepq5JS{y`GNDDI4~HZzC`7bMS4Xr+#L>`!>?Ux6N~y@NMfF_%_O* z=X^b>Zwr`4byEIN^#T*V4O!%U+Z?Th)M!rH6TYC9-oUq|y27{B;1mCYzpAAt{->7a zu*j(%>^k>tdH9IiYUzi-U5_7d<Bv>^vV(lw7Cs<++sQt53m;aMY#Ea-P}v2c_nZuC z>4^+$X(1<_YrCNwW8FjSk5NBXE1&S3@)7%FVr(6LqY)qBHx`PIg$?+qr6+vU(i-qF znt!1`u9Y7nAK_~n@e#h}GVyU)13qf$2_Lnz27IJ;p7)dRQ7b=2KEekDAB$vHSBc)m zqI;FDOLR@gNBwSR_|Q%8rM^bzUUn?eecpfIrxq(cZRfzHKBUFx1W7mlp}waqUl!w2 z#&fUHSP7bF8&^49+^^Do+0)CqhlglC|KRfsVRx}#1{i35Nv{2{--Y&*@+JA&T;GdT ze~LTy;soy4=M%W)e}>H$v8SgIZuQf3aWlVa^ZtGvF;^<NFmH-{nhPWMuT1{e3wJ-( zq;oCD>wC0Q_zvvQ9M_Zjo<=qoyM6Ct_N|SKZ|<#qN(YbWn@_EpSERq<p7*8Y69@JK zFZoF}yBJq~ANq7{ll)U$#LmF6&&p&c-^<z(x_?6Wh%p`;pY8Wyjj7DqN}czdW6l_S z=$3lYeO5J^WslFc&b~jQ&S?M7w$7!0M4i!AqfW&a4P`4kwz>9HZk!K=yt4Jr^YzWx zY)$2j(&1tHx9ZQ_e5@Bp$Cf60&dO>2JhPqcdta-x59_-?N0c-ByZuuK9_P7P`;Q-M zI&trPE3-XlN9oKwkDoe@fF_kgr-6s{i~;{vce$$l>jlks7gpBR(lTD(yyq0oP?b-# zXW34)C+gHbR6BF%<2f3>nx~=K-z;0T{a?_;9@ae0iqa*6;py5p0Nr}8u|{_)SH2IC zwkhLLZ8Gx*Lv3^IVoBD|hUBbG&ijnE!#h@d2fpQ#ncT2*>R@k))=xSP^ZaL4W%>9X z@K?M|WO5p+E9%LgeKnDGDS1)XFA`i$;*C7ccH_N`@MT&9>HzjUhvl6C`J9_Y_ezW9 zc$U22179}L>HM+7!v{9irL)nRt2b(0L^1Hpn;#{eI_MiF=t^Ia=V95qhvb##W0J~; z?3z?3`*Z%9I^_rG6PUw{^sguByh}p9eQ#8>%jQcu$HB_~RRYJlM3lchN$1=4(7Tdz z4)ne^b|f4fq@fGuy;(aqpDcSM{mGd(>%B002d)&)6TF;sVRc`d)WLV^p|M@>WPtx{ z(HP~9*E8b^>;;~$O3F=CIoc!XS0w3^oMz}4pOvrSJ66xKui7(oN$Ry{^erFW5wchS zUiOyiEGB3=YHGIEn>yc;%R4&BdqXa-oaDVWp;hPOjIe`vA11z~&6#_APrIV}Lk|<( z9*6@(pY4;xo>{-sc-iLp%6-`x$`cAVTiK^2kLGRtgWzd9L-zyO{WGM~MwCvh&iZ=0 zzIi}j+otPDy7DcAg3jKE@0v_6>uhFy_Z!);7O(fG?0u>~woZ5%Yn|4%HJ5M%I@DVE z--!ldrxp4W!_3ehKmQ&5H|zgx{ok&?+V8%*^=JQBr+EHjX&#fD)K0M<#TO>8|JUmM zQ_1`PHJ+aje#g`va<)YrjjiF6<2<_PA3N0#$2p$(6!7Ci@CmeI{4D1{&QZVIr2FZ* zKhfigwC@5xF$w+}|4I25oz}nSnJFvfgR(O~ie1@r;5od8=j)FEAHI}2in+Y-rR4o# z#gGrCT=-J*o~-3%{VMxZp^f*3*>`Y~`*L7^k%MJVThO*Um&aaF>cVH*K5oV8$4+(M zId!GI>s$8zs$KlE9~Ym<Sv{XUke%&`Y~&k;z0-!Q+Vw81-oM?~rt2$pHCZYiiTA#s zb*s~ZpU2PD!^JrOyw?EyHyxfhVUpm9H@NcdD*YMn765l=0@qg2`w4<!Y!dLiYoI+* z9c72VZ4`KH$Ko>KX#<bOKk~Qs9s_mVpt8g~F-GOvGT7$d>q=i^F~d&9!1^{&lY*wA z{$Zyh-@zNOF&FPg{QR2XF(G@pmT7DN4cIa<0dVhk+9UQlLVX4F0=Hqx?evw3qYI@w z{r<JOUm$%T?-uos?0b^mD!~K$D&D3#!23Gh<xrb5IN3r9559ONc9D)OmauY853vL= z;}sKR^2z8TZOS=%e@k%{u@?5ryf*2dRQ$!<0sS<%&hz(47{8O>=5)}no2_X4@PJ~_ z(-VH6N8{`cYz7=Na`YVM^srA3IRUdgk+tSMOmE8=zeslM>7nkBmG)Y7zz_BF?hkDX z97p8pIVQ)qWM*S(;%4mQ({3l9;wl?U?c{IdTxPcx3fN27O1!Il?PSFcs_%u0uh4O! zGO*`K`6KRmZ~0i&8|g>Z?iJfecBB)}QrF*pLiVL=ydx9wSXa(>c1cFihs|N{XSuAh z*lfUJGW@~y@@?dQM`xR0H~1Ck;)=eTRd47PxPJsraTU5XALOw3BG+xlRo%Dm?a=&j zt^Ir5*cN5l#UEG3p4eI3BYW<Njj?a+HJ)FnXJSX5TU8FZaNm^Rpd4^ggTav(I8z&i zk1yo-z(z^`a83@<UqEZrNj*i`;S6Y0Y<IbAW4ity(Erc%f4}}q^#3#c->3h3^<S+2 zd-Q*|{_oQNGW{3nf2scLKUk>$JN4&WBH}>y`!R+iHu)3%=j*RFzVEI2zeRt^!uEh( zr0bjXpR4~H^?!r@7wSJpe~r`kp<~(s-`n9`u^XIk>;gYm&v!G1B=0Mf2S$Af{qM{5 z+@<F>?^{G;$(|L<b8Yun{>dpxOfR2+9TKAxi}JlPT?ZpZM{aX;9>r(DEgGYr`knib zvC#R68lBnuZDtqhW5eFU#+bLqf7NVPdc3(<v@^%hKe6{V^?T?I9HHmqT+c62y85eq zC+p8%&Xe?ySROv6=|5HfDf(CRpRE6j^naoL=&M!#4*l7?j$Pri<SF)*^tXPNdct;J zlEo+30JI!^YW93Y9oUFvS{ycF9dP3-f|v2KS^O+EJ41QcUC@l(L37xheB{0(^=Ir9 zG;4pN(aanaWs$|P`cpRcvO+Io7v4vvJ$-BW@c0Pd20e@w)4oJ}@0z7PLGg;w9JF@| z78{l9N~wLE=y6Qg2fi`l$$WoZ@BKl}NW4J4zgyQ|;!|aljK5`@_v?Op%%@0CrHN<i zoC(?gHqnMpqs+&|7d&$R5$6%#+T>{;^fY3gfLrQm6{RuPK-oX@H1^X3+`E-VtV{kP z&+kldze8!$B^UFN(j|I8_lzeMADKO&2W;htY8D5f&%^zmbk5|lctiJx`91d8?DyDb zMeP#4SLmL;lNh_ItMyfOhK$c4O}Y6|(w|meK+J}|W=L+FkAUAGFZ?w3;lHhn+Tcp{ zCEU{n@fD_1`P;J6h}%T_t+&}3EjQYFMA7TBc>?8&)(&8)OLk;&0Ja4l&J?0;1?>}L zfA~Y<7q#OOa}uXPtFC7X4|Lq9x}y&SPO>$)!yQg_lxVZSMjsRR^lj*Y=c4fNj4X+F zkmcz~ImQ@Kj&TF`(as~C_Cg!ud7{%5dElnK@O(m@yjJBc@OpuXm;;}{GyS{9{1(r_ zzig)z>CrYxN4^sr4`qo*Xm1gN(B7)^nhV?BEXnwsYP_$9K6zJ|E9c>HMGn|H^Hg8; zwihtiB<~JmZ|Gije74osO}&bbz1)|)95^|XjqyT^6(|e+;NqQ)JiS39aXj<B@hyUM z9upgZclqs7lj>yNb-C9WW6iEgHlFKJzXB{VrhOAweH`ELWd4zFJW%#pFKawF?)><R zeivHtw;7(Hm};TqPdmq!PxJcZpF0BoqaV+F*l75%TkvC#q0hW*iXtK%>o6vd_b&N1 z0e&iU$Q2o*$1i#P;g9|7uN_Z{ZsG=fK5HB)&-BCaNo;_;hz;;-@m~5Ze%?NHpi^X= zmbYi|L>_$?-(Gc{*>@3`S7se_<>@Qz9DB~xZ)QKg;IWlv*~m(*f#EmsTfj5MRGYH> zvp+jCn^RW1=wKZb*<+Iu(J7O}7rusa_<)zm7BZVn+Jyka))q>R^JQxb%34d899fG- zelb^y-mtUzlI0^VOYCfc@SiH&c6Gh0-VUCLNl#NA{wB))ELWC%V8dpvXv)f-N-QK^ z)pR?kvy7~z4`3^mY`&fJ?Kym>Q=ikhCGxcYnD!R*Rs};pN%?OzfSKuZ&2%~>s#|C2 z?7Ry#ZV0>LiakLSaM(*(_voOxsc<WOD0ST0pbp;qr0f|gi=U^C0gX+%y$<vq`QQ%y zJ|;Nop<l8zY(@LT7F063L1*S;VjWd*_zTu4%x_39?YajC_9*?>ngsW$?#@J(iS8B$ zAFg-uq3=x5Pg%u{CFntK@&zMky!Q0|J=pkV&{<e9kmn)tuRZtt-3BARNMqdIs+eM# zX!)LEohNjq-mnqP2X&we{3G)Iq{m+I{N;~jzK6JGzRJzprnScbeLuLc^|7N1cj=#9 z#}&T(*to*#$L48mk^bWdjSD9UevZmDqBVG#r#%!4;a#$w=W-g&*Gbpr>%J{s@GX>M z9V+U++-bf;-?NBVk20LScbCfGgWz?A<U+iADEgp{_BdbVx}F7npA&8?E8nwFdTY^| zE52rhbi&*o>+#GT@O_iZgqvseor7ok`Ud_OpNV}K&!Ye89M92CcEYpUDzY$J^|9P^ z>6pG1p1+^Ku||h2obEQL{;+1t*yE^jk$o|SV!ciA(wJa<&8wqF@!spjN4KuCbtUdF z+n1lA-O67Li}QY~z4c8_|L0w|;g7n#9igA;&QG`VqcKeh+wK%j_?#|zG*8d`Ah3b+ z8pjD-$mwdAQ<P&*hTW@Nr|U#LK<P2j8hAdCqwTDOwwL<-Sxy`AX4G{_t{kw^w`7pT zl_UCbId<Z*CUy4F2NCbY{5m|-ez?-VVngT{-!jwNJHD6nyzhO9d=KT&1Nr#Z)PHKc zJHj{NKbeD|-^G8Xwx{t(2lEt<e<brG;36L%nq6<s`c{>NR`^~lzG;`KP5eA(6YO{6 zd#LaUot<v$<0RL3Ua5E>>$kISI3Z6-Oz{^!H0jGF%aCJ!zW_QS#(VnejDEhQ!}n2$ zCDM4M<mqXwS`r*>SJ*okt57d72{h+vi1&@-Tb<;yE)AXOnT7S>!rt)_qKW#fpB+nC zYZGIrqlz8m;6i4zWqY#~|IC(r*?TanK_3x)#nI|3j#ghW8$C!K@h)DU_JgK++436o zsJU-^B9{pT#(&a_=7Y=S+xKp!{UrL-7Yqxn%ZKYUeTN$yaULl$!`|tu4Yzy{KAP{U zLd&1K-c!1QCTyh<-d5?n9==}iCA6lv(tRrU-aL)W*^th+bf9Ow)5iB_N#AnT{ezqJ zeKL<@<&*2%d$a7lD!I0AxMBBH?O&@D)rOAITK`mif9?$3pTT_M%H7v$&(EEl7p=OU zl#DxzipM^hwFBaVCbbRHW;z}8wX@U?82^#}k|h0nr3d_sB>lVuesYrjDy0)=g6D)J zy)VIYY?6Mi(&-C<KQc)_CxIWAq`xvrZ%Wd8lk`70ukiJXB>lHZ`q@f9((C<IE&bpl zo6fvoko6$w`9+d`x6(sCdur*wdZb%;u){NT?a>uKdY=0a#-0`FB=ml{#+yBk`~M0@ z<k1Iq9+TPaHph*h57^fzb_tws5YBGLe}T6Fd_HNZzt{ZVF4pAW<8OjqecQ33dhpL( zvc;8}U*nruoY}IWvfcc9S@-ae`f$GGVEAQEo2Ff?cLOfgJ3t2?p*&a4ispK_<}&$y zBz1IEmyf_tIcNnp{#EmsyDC%j^w`<OqUU~(E%Yq_!<VC1>s?mwA$ZF8$i6qvnH(X< z7bm*GZ-o5MldM8+?{&Ft)we3?^FlW0ZL7XJy=BIBlLfp;-X+qvy!!sZ&@1il>yD$| zd8PQU7RB~k<R8*9%p069S%H^%o<7~T>t4R@)=g(#JV;-}_yFC0SM8hl_^ZM(%gZRP zGrK#+V-}U`$d~(u%B@zpFR5IY=%y~soo8^b()YEg=c4|>bA%H<F8A@p&8-@*S6A5? z#=y*(nyu{-v%$l$UZ=)FCFWY_)A4Kaf$NcB(EUrr6~rEvrWm5l@kl1S3Zm;nqU#yO znICl7&_<3`d^KG>-=lW_D$&K>BYYn7f_;^X&HphEio9qGtQ*j;F*gYubD{9V8U)YG z)p2d|d42Mb!$pz<ZJM|e8DHQrP?w&=SMByR=6lt558F3M3?6N|qVo4TY*po{k99-l z&1*I%T~z%U__Jj*)O#xB#77r$)7iB~kM8kn_?u42Cg{0UuopP}S_dd05A<RCl_h_z zA#|MMX|_*RX-6n+mZ#Z%QKexkLF2WPHNI0{js7o{%$e7m<#i|y&TK`o8akvcay~}r z_XP38p2k+!-z<$4kC6_+^~TI^+kJeafpf*^-<an*s9^ASiUpYWYSMq*xy^-$pE%bg z<_GCJ%WiL?&E}i8$S;f&9TBgk{W0St`u4K&iRD;3N%Pg#6jNmT2IRXfj`cRU89%~V z8D^gjgWn*1$d|hB5)ITJ^@P7;&WifMDY@*T?(xKD(lP1iIE^vW_%Y&*Si5H3n)L!= zsTa!6zXv}f*~a`Yu~d|)7w@2lA4o^U$?d{*n%gM;8(KC^-)=OeG1UnUL)oZjv^vtV zPkeYdeQCLT`~?0>ysm@QX}cp%+SEPvI4SUt+!vCKtr*+91)9`{(buAjb29zz=#&3h zE&U@K;2w3jS7mK|*!~>ZLurEG6}Hykf9~+J8o)m+zr?&w;Qx`szperNM!_#m;I}*c zYZ}0>68r+e6SqPC-#9#DZ`x{`{HR^M?WE%&xA)R)FS|r#1J7UO@Ni~x<b64p7iTh4 z|6k<tIFp$^mb^9ORWcvKyaseJ=eu&+P#WjA1N+GoRxlddoA03<F()urdtJ<Z#+Wtc zRpJcjqT1mEhwskdZQM=WoN;4qQNB=aXcsmd=ea(pHbx$}X{VgYUoI<O^<MFzZ0}Oq zHt=2eu&~AduJP8Kvqz4%;@k9X9wVo8&64v8nri+8-ephn|0Q^2e*tCwU3}TId^d7T zeN6b|_%{7<`c4nu_n}<sySDs(<hSXun_{Vd&p<6c8tGFGMcensKpWqp&(jn8bNIe< ztfPppJ%8!86aD~sNPQLyEK+;IM{sUj*b^}s>-LJ9_I2t168+UL*4FQ*=>Em}&(J^i z98A?c>-VhHPZGW+fB!=o)VNR2lJoUyAF@%ak2r#7@~(2(J|&q2>}Na=xal*rzun6P z>^H=dbShlg{O-mNn$NR2d|83b;eiWYPZkZ<26V5!%I@K@)$ds=5?z+=`}M8QrS4_2 z4V#ng16Ti^lU$a|s;i9lWwIygQ1`Af87<dkx@T?2c%5YP11IiXRu*hE+n2(%cuN1C z75^jSnYwz!Cp4qi*k2I#%$m+z&1uXlYu;OHIt$cJ!9jb~7}wSx=c_DpOi@QseL&Mx z&0&`n6RIu0M|F`mTV>`V8_~|WUB<KYJz4ZhCbqt>n8NfaJFz_^=jh6OquWmDUisob zR~mTG3AV+(eAaHR1Lc*wXN#`bgM&YThId|-^-U2EfbRmyp0>#TBj$^skGih)HHHD< zpDX)hox$qRGxo%s$dWqvUM^i^a5wLzT$|>(Sx<?%?E$@uHCJWx^V{hdPBCcdF~xb% zIpa`tF;^&j=<RiCyOObDjBHK~{<QbzInh&_yA%%m*L<f(ZOZJMwj`Sz40|_!CRq9R zj@go*+hqw^^qr-BQk9i^>|S;TEc8aaQxr1haKrcI&lwEdnco<w%}?=O5B(JR^eL=M zVPoJ<edTk(%baZB<^7Q73oq~41YX{qsfRb(9dTB~<rCHJm}e@xZ1EYk-XobyF1up= z8UIJy^0s1rR{K3{ZKz9j%evV_+KlAI95sCl_F{Owocx{nP4M8Wq|@3n{wn;cwP8Io zCqwz^(lhnSXW6<m`6GNnr{>ekw2Kq>UMjz7^olP0zx<>5tiU6a*g-!1LzLO=zBX?^ zq2rh{ZZBtRmnqLNA6>6M&6hWu6a9Hxin&7KfBHGbHuxX&@q%Z+Bzpqr!={TL$!^$Q zIrhTg(_^n3dtNAechCKUt9(x{<9^aMDs83a4I-bp1MWZ0_(nGVx4w5U<`1BQz7m+L zMGN!t=q{egZ`6L#A2?&|$apdO^y%WYQ@nNxhHrV}tFT+}k%pdAzCR`!*#GlU{Xe4r zhxMmke8&IKpZSM)?<aJ9g=_{~W!Vtp-3hXfUoX>`-SM-({Jjp-ullgFcZoOhc}7l@ zIV<aD2AeCZ1_B@B=+vLR4Vjc>Q-c4r;E@mb-lX}I1?pSiOLKzzDE|?U=cO;B?>Zk_ zk_YYJ?v#BlmRz#Azv1Im+AOdWUah^Qs_#grk8jIS?$iFhGxK1~?SPLmtjhv_iQp+u zz0jz6DC0Tkl5e*61c1HCaWmee%*Io<4+fo-Rg7djL|OU<gTv04|LV(R_;A+7M#!*T zw$0i%dtAVWZ4t*)_sdlGp=>MS3VeO|xK7zttkuQ)bq}4vcp<CjLEW<!MxCARUsO+t z=N^B~`i1^IZ;{U0oHqO;>s`=E{w(SBLeKxb_wCqO;Gr+EeKVT7<t!9z09+|7YhQQV zRIomle0(V7d)*F53p(*NeCOBJ+~jA$NxPx1MqZzDJfu;EHU!M!q8H!6`Ud_`GPZq= zv}>ND9kuFSVzhR|eBfl+kL_7f8vQcu+3IvUY|c=0L_6qlUqjzfRo_lLi#^g7e9dHi zteHd~75z11u$W5<A2CaMtjb65?TQ}tRlVXXd_=bADcf6Z`@O^?`Wf2$C7R_=pe^<` zW%~P~$;Dy}<!Ak$(!9K#zh}N6E8nT|-I8s$+b_0Sb=ju=NeE1?dvx8c|DgV#)PI%! z|EmAL=r4a{`whcCy;OY>xL*kFO17`CtXKy8S1HEkO5EA2E8iCQOZhJGRGSBZX5uLH z@}R!y!Mhv8c{?>%jor-f`WUBIRi3z!EAgV%Nb2r`kWJY7?i$A@nRTpkd>e#sncp9! zdtzJU1D*I1=6Shie1q<}Uo9J=516EJ2G5KOJ{@Br(SNe=TN&9q?`ubSu2(re^N*sp z1}A?;J1YwBr(Gs#tSeL65xS?0^?B}#koVtFM)IbO*nFt`dXL|mpVU3Fy;68qY0d~) zE_HsOAO4p3bLdh&bO-BH;D5E-is6#Hp`l-~2yq8Kk@Vn&dS2#s@I|MKyqX<I|2!A; zegM~&ZEhEmYp-y(Rc_Eb#24&t(Uq}DyX*trpyP}y8rw^}8>M)n)bIV%6z3_%q>Ej) z%+DCTZkzZO`c93FJ1Tv$P1Uu;Vd;a8l+Q`~9mcwpH@wmt@Yg%M`8?y#d}?We(^B>{ zl{Nbanm*t>p>LxpXE*pZ(nC-9Hf#Zz$G8ID!TuoP!wJ6ckv<T*&Q5s7KA7v}TxHHL z=3E+sS2^<&k^w#iAD5lmNgOU%Pv<`7A@V*5`A~l&Jn&Dusr7F%YUZe#RblwYC*>ap z<R2d{5BWuSMK%K}Ph2$%zLgexCKvnj62IafLq3$Tah2vemRb719{e5o)(_}Pd*_)o zmViG_@Krs}lKl2vnc3WIJ<k?Cm&K0Gmu2nfliEKR<w`!Mf)9(dm}e2I!@kqF)a%3c z*pG<ZvB6ed>BsJS>FrwA#n-D1>Pp%cPh%fHY4mN-4jfm~=+~Omrn^O}of#q9o#Xkv zx-L=rTwUSqTh1Hl&>L;PN3_xw!GS+{o9I$qJGxar_Dx;LyQ=zu!FPf06>e*Njt|)f z|HM%#PR2-DyWGWhfALkmR%hP~Zq}ZwIi&R!2bik{_w=yi>Z(ET(}%Q)H)v;16?~_- zkmnlhA%$Ma-sHqR^g?^2alcq;^K=av%-4OiSJtnVXr81jU$o5Tac<ClUCukXVee91 z*{{4<S9}%ilzweiS$&ddE+p@zAb0pjp3r=mo);wbsQ>9$qWlF)XUzHF^sN6AAG_|= zK2>O!ZR`Vw!DyaXJgo2cJm|f}%V<ntedrp0CZ>hA@FCQL{AmC8XwTyv=kN~Sih*&J zqTT^mG_X*0L2p}Sk?pgz{n4)DYh^Q8-uaei{0JW~@D;YPl=`G&=8mE*w0ZkboKQ<E zdfH6UNdH?+WTG)%_U>NcO7qRw!C`K*wByhhZJB$<MYL!1*`+IV;t!C`1c$jw{m(<v z*J8C1{L$;xw^fwiq&lSQ(lXt98_(t##RI++9DN=`%n)6SX`umrm-%&)uFSUr3l7aM zc0fzCk6)`Uo>M!Rq-W;!DT~d#Pw(V~?8YBFXf)jGYt)KuO^<22Qh(4f&h0<?gWzXM z1Ab%=C2RlmJ(VPGa2+2h86!{nsE5i!vO1_XNIL81#0>NkJkz&#>54BVHl|HYAYE7F zW4!4Zy78^Z2Hl37=y&1$b?CM)^ChdDHrfd`MxU*<mO<b)Nk+{1P`=;aiI#sd*)Yx^ zZiB8~(FM%a4kN#8=b?o@9?$w-^JQvh=ErFxltVAjsWHZ`dAg4>|Ee-Ux9T)I=8Q+= zF;{T#4$ttu*yS_H>3Gt|6ZjP5|7PlkCzWH|HX!((88_J&>mkA3G;QU;G@bi%uy@h! z-$@tEg*VaW&!(M3ybq1g5q|PdWMgYJR-yic&LO+e93%DhiKeji;KTaLB>!Q-fnTyI z;WO;n`gr_Y=AT0DW|NieHQdyl@9z)l1s>jurr&35bpM5ymSc=tO~yvZuTAuK3r9LP zMXVq5akOjNV7smpCCfslOB+jcs(qucs?s0z`5*8B_tfQ?%^Q7+g^*L5>Y43r3|Un5 z3_oSJ)lYa@jIHsnz%T|!J|FUD#^F3G&epgslbz<VI-uhwr;oM}wk1*Q;vU~5kysza zeXV}U)9$4!u9KjtlF7jIt1>lMr&V!+#g|6EbeWd#Qu#u4(e8TnLA$*_B>c>~GtNie zRoSE73md@KfeRUs{?OFSPVv1J=ase+@9h4s&t`J~=!bmLv4{JWF8ft~lf~dw@kZMN zcg5<<=6;c*{Fm`kRh{^pVr9_)a6A()sNCjuJu`-<9_}e88LUU<-~IseLPNH2Sz-%e zJK&?uLr0XCPu<n2bZiKl(IzB29|GLclXRA?J5ZK6k#3bm-|!dXe{4K#yC<2y3EK{t z39O@6W6*z;45kZ5YVXJ+?A`biEw90TB|oDj_kOBym7di24qG?;iY;TUaINq!&|iI- zeK+V9U2oR^CjH-||GV|SQUA~C|0(@f>pxe2@R(n4`#MkblE#`3{C-S6o9Cup&6j(< z^c%>9H6>tv<hBo8(JpQfo-*ZpoDGf#re^-SsB_(T{>{|w=EK<6ioHw{Z?Uh6{09Zk z75zOSSnk<V^^m7utu=MhI;9`3%o`w6<_);!=M88V^jpZb)%i5u)s85S&%{>OYD@<& zZ%01DgWlexcbIv9vYBzYVj<qIWZi{zIo8!4T$<?(n`%_1rJT`8o$AACb)K5j1HLa` zCpg1akVjeL=ZP9ew=<5`GvjKmF|M{gM9<8%RYc!g{*ayJV1CkNpqR8|e2bn+LJxCn z(az%x8Okv>UG8loVv*1{ehE2z9y#P>5Hf>*aHsN#yo~mh(vAG2Y-&V%lVX^2n{#5b zt&_2zE5?<qmBo5H<5zqx`U>3G1v;NDe$)I^p8=!T$-dzhIPx&feawdpZ^z&a-OwK1 z;xb6<N@-~#-qBu1+7s>dQ21Wuwq<>S>ZXnuXXn>!So3KUJ@~r3&B7yP>#Yms*NnPn zWcyVZ^W)R<<-+%|21KkDevkR#Z~Sh^*6Qgp%I41&1P6YQHj2-WciulH8A;uC_CQ6~ z)AT<}|Em7Pqu!pg7+$ul{X2@!viAJvg0Xu`-(E{!+@P%1PirvmOv-9+Q!V{Z8kChk zsKMY{qh6iiR7-z7Wu+hT@LR7*p4opO|7&qV_)^}{nWV8f?IG<uB2Hi(Pwmb0v*XVd zy9zh3dEH0*O7p`eBad>i2kGC~gQRDCmA(mCqn|XJrx#t)NloUJJdAt~eXhal9$w>~ z{xt51tK*(=M%)vlV>{R}wio?w*v<&MgD%lTe~TUQUbW$p&9lE^oYM;J`Sn}oWf(gE zAM<u^QEVYR@<T`1+;HIXxg3LKo;UPVkH-8yqp6|+8AAiKYAiYQ>}gsH9hOG_j-RfT zbNc0Pho!+I`UtpX-hW>xJ|fNKQ)1ou-X-F%j$ETn8o$DcJp0ri&dJ&3WaTN`-+`|w zN=_@SU%Yg{u9a-<g}5@#(p2AJw1s_fCT{qKir4d?`j#_P&!KRJALJXj>`{Q$e#R@6 z8wco<dA`M;*$=_<b^e^qVQS2%XZAFZH?cr$Lz}#L@3da^@9Mwe`TU-Kow><(j<Wpo zbvA*$L#p{8_-+!f-R0Z&HkEH2*e^c~+_|EQJr3AmY8OrF!`2+zTv)CDb@~^^H5Yri z=H6*CA1*xU+#z;=&e=bVK3Q+!%A6^&7&Omvn-yF`m=B?M(QW-~j=r(dp+3AM-8ZbG zUv#LwHOyb}{>=93*<ZA4<e2B5wxM|iYuB+B3@yOMdal}lwN2zg+oV4_@@dT{ATw_h zzm%Uu25R$$E7BLa{GN?$+8pPvrF&~<(mgiFeT(n;#O8QLPo3CBopuM`>APdZs<hL; z)p&riZPGXWBL170?k|bC>);8W)2BY6snEaY%RZh+?J%!rqg(bRd6ev4?Ev^y(vv-l zCyN7;`XcT)S7Y>X8awp49Mae#>bXw5Emw@Ns(ggn;SpM68;TcbBk<ayI+%B5osYVI zX!2D1sc3#gysVZirpk6Jf?Fs!(tvxR()cbmbG4B+(bM?mVWb_aH0oe3cfkv?_DcEl zRFAFADlcLk8;eQK%O!8dq5n(cP5PnhlxDHN{QhzNeiq|>>!alVR@L&E7e9aZF_J0k z*r&+OGzVt;`KIVPP5&ACPxpKE3;ReXwqXw-bBr(4U;TdVOr|E?)21{A-*=hbtvF8a zOF&D|fls8|qFf&10P-|Hzwgpqp8S{PX})S-v)_Ziq<h*9x}hv`zz1S~_`aw&i_?5B zjAVJ4#v`<|kP-dt8}+@`e7cSGfRk)lBcKfZhQ0S$S)sij8IA>#VVpO9ozmz}cs@>i zP*$GvR$ya(mGkNIbuq8Oc*Ah2jP$UJF%SBoEv?XgO}^8@oCtJVon^jPI-DlTL_R*B zbF%{vb?jB$*uj<MtgmRqPn6Bm2@jM_(*qW~<YSlf={Kbp+RSCLfmnZ`?JksDRtq-! z{sVb>Z%+D>&DV5k`jK94Ro@MsSSJH_<YBWKzuR6VY=i#f2>r1o;8PmW2Q*N=RWR5Q zFzV{|wFdq=wt)>;yOB;bpSEjp&UT1Z6vNrt{%UVm!}L|YW&nSR-WF8O+il-4kWLsk zBP(dg<1~3l#%X%U_(IVeIzLoB_$YjVzSE<5fb3fheX5W4(5Y)DIuQM8(>BjUy)EJo z`&m|fv(0t%2?iThyBq<tr2J-m3;u%L;Gs;=$n!8<g1c%IIB4NL`GVvhycr#$+hm{E zd%gOg5u2=6N80vN`&^aOhaT`Bm$=P#=^mS_`W2f&hu}gMn!j34ez(%Ql!pI!t?ZQh zumS9iJ$<kAIKM}*6_x4LwJJEqONtS!46(Z60lNo|_nLsiroqWss<K(jKT@;;Gtpu2 zwZJe24IIZhOw@;5+69A-!cWCor~J(3dilM;i&y#C_26eMqf31v?P0Z^@o`J#kHWUY zu4#M7MLy5yLbk|rqh#Bya@d<<AshRU4qey^GB&vg-sCP@$nr9O@@19Bj~rcT-o1!E zMQ1mdkFTs4yp(jc?PkTiT0b1Tg#4G1e~>=F=6JKdbL9N!+M|c!+CKIFJ?j5^%lfvN zc%3Dh&@;Bd6<>x-iDCN+C+_``;xlw*F|D5eF`gwO`tz2;7xzwnpWb;EkI)K@T&wo3 z^oe`VcOD}B^ho#EJ<?B$bmM6V&#CS&%|2BJ@8`+??Woq#H@1t;;31Xke#sU327KKC zUv|yWHV$2njdsdDz^nIJcWrYR#r7p)fsOvmI^LarFKO=R_j}o<#lg4uGvk8QeqYi( zV+81;4`MA6`=meDIMTjrHea^DvtaFcp+6H3W1l_#j1T7-SbRuT`j7rb>mC+&Ggb@x z$KT+ih!rxs*ly3wqNC5@<jXA10&Z56wY2Tl|Af!LE>ig~691$zH_DZ`iz|IESNuKl zN2c^&(?mP;!?R+HeT*AuLzL%AdHO2K=k*GY;L~_xA2AYTI5&|p;G-OATuB24Jot<j z&!g`nkGhOT<(UlY*bsddKH<f(1^jd>Q`$0XBNl%MMsZ+A&_YZT-+t;6Onkek3w(*p znQtPtB|T&g&VUCGa)(~(4;`d^=}y^mYTs-13_me1!#<y85!WhVH}jY9nq}NEPT-xW zbRR!D!>-y?AAVl#;d=OHJ`Y*QN86ds_#^sb_AdatQsXx4t?A_cJ#n_cO2M!{%IsX% zrn27c8Nc#T#;As`0S@N98sR874(dc6(0ae~TyKn%AHN|-Xb)YMRaeo+Hh-aU75UJO zpNDS7HIaX#kB>vPG0&a8SC*d7haUwWay&!r#Oz79ZC+Y(v$|Yv`}GbneTBvzHun#W z2G_Sj@7`xLH!AmJ<>!Mz;~g4LNr!{k{K$80ek9Y)ssUt*y~5ul=MQ^Zp>ylm(@o6A z+ELT^n;vb`UbUiPIdqK9pf&98|8sfATz8Bo^Y7l$R`d3xHQW($NbLtXr2Kq9{Isi& z!p4!$dn6y^k@A2pdFP*fa_9`XTe}Py=4>=%&3>4?JOUT|V(;?x>xbbg%O=Ph1vlf@ zx_I@SACsrn8Rlw#!IhQoJ~G7nHKrf>h`MFPA2hKi1KYev<?+LHVW}rCgE7#}-hAY2 zwv)vYcFspVI_uSo?O-cu+gzUWM`0^3(s?!y=v!<L>RW6NW#3{O{K3o%YW9NNz#mt9 z`g?W84Q-M3k9_~<;scNWVCKbU6Y5h+59m8yz~NVjua1<h(BCjt*M1-yC(*Ck9GtH7 z3G_d5g|+jO6{p!cE&hpd)y8wPbx+zI-)MS3bOO__bnaVqzt->R)7JPs{ug?P-MF4F zTd{aec4*IvcZNMH&ar3NZl8E~(93d7%i42N)}E8HY5az*;CDpt^_NI?=BwrB+7zRG zLi^*=_WT>^$mnuhv@^xl9h7U8%!&6X_Z5}v6JF-DH#F(|e(8q3iI{>jCT=+`o9oT| z&5D5yYRh+bUoaT?;H96WT+HRo@$!5#aDJWgTfIE_^~%pvd1$XtR{PdJC|j7|_tN!_ zcE5j>(p&s~iSC~{HG_Yz?%TAN^Z|eV-+I2+@0(TrLBF4=^aIlIx}m(%ZGOK@dH<<A z<i*@~$m{Kr*CmrL*gZ!wW5424-4_qCU$I&IYg{4Sd~xsl9cG@x9B>$7iGaDR0UlzS z7RPh(D0l+qBEkIF=_D=aJhMSr=!~-GH=to$0(15#c!HOi4e+G=b_#}ek8Q=A*Sb1% zw>H3)(tX@0FhNs$o%*h$zC-BlfcCWjGn(#x>o9p6NOku_13am0_XuW@Xu`i8rFNt^ zp`#vsv@K$JZ0n~D@FMGg`9TBvh@Fd$=X(wCKwrRoM=-BwATw+4j_Vtv)JNP0-FG&q zFXioahat_rYw&XU6t%6Cx6e1glk#>$13W2js{|u|X!CoiP2%S*MwdR`A${QIO75rr zR6Ze|`!sHG-&JD&6TT0+=ezHt%(;SDpy&D0?*jEV>;qePvi2f27YE)azXETxiDJ2b z&z!?=-}{sI4#jz#S9Pa+Aa!W0xc-37s<LP8IU`OWpR#wV&mtYWL1qVLX8wr0kUih7 zsRxtFzOMmHD%Y1afJuGdX$@e~wlSjt4C6TZChTRBV4!cE_~Y8|*W3KM)~~ntb&am= zJy{<<OY&wuYE@C+!;x&BJ}K)L-Yxw-;rG)04qy~Vlo-ceq3ipKg?&3cpFU%Y-`|nk zE7mP76x>6?%N`GKXkO89bn41{gKVMndT%%A0lh5OI}YeOmH8g+y+v;Uvmk+qHn>YL zFU#TTb~tnsZGLACS2=+RT>l^#`55zoQD>94v6QaA&EX1|w7#brz<?*}`)UK2)TSO5 z3~lZx$uyP4T)iI={c7;|&pCWu2~5<99R8rbKgHGJaPS<szMsQ2p!XYU?a^%zIXsrb zwJCuMT;Iy!y2W8=7Xh<A2eUN66SV(j4rWe*Ct%hJX1i#@53yz&b40Rd^HsKv>%OT) zXOaWQ`C%<HM#gd9d}$WPkzX$kTkO7!?*QM+`wv?4U+H68;=s*bp8R^{mwNd&<*%+& z{+ln$>L;Ieqj>vzY=bc-F*&r8$Gk9k*cN$;H_dNzPdnthIh0rYUy5hwxyWVmkZ2|U z4c@;l_PFfVFCFrgp{G8{ceAB0(mdzEN3N`X_YrJqsr+~B_e=HKJqCDuU*PX_9W&m= zFZ}vt84dWpfSK$t_2>*cINo8FI-cJ<FVGe+M>c?go`7i?g`R-<gZ49?<$j|cO+oj6 z2+m|xho*pe%wb03|KA*@UR^=cPaD*g^7eyK>IyvH6AX5CxZCifvY~ix)W=`tc1;=j z_^b7Nm3Y3|`*_}wppXBvTpz!<>Gr)3y=SP8zx#{}2Je#nMj!vw)Qhuc@8ikGXWgZ~ z4LD?r%{+BRW;3bJo-01;!KA+SwSxJ&w=2%kddBzZq-}cZSr-gO8>-i)dU9>5+n>R= z!SS(AF2%V?d>oi@@!-><yQpzzv;6%p6FF>E{#NB}(D|%f*;h~7+oJR>dfu#SRdlx> zEY{{anfojpC>FN;SFzBl36^Pc3N!R?)qk3vZ~ej-nhL!azK{7)_K!Eqfi&y-2?cRI zPZkSL|E5^DSO0nYi-mUmdwx|ctWaL(zZVNzo+uWu0eGrZCXeuY_4wJG@B_V@ogefU z{K3x>;Y;OkS5j_+{At>60hf;%e){|2F~j~kKI{iMnBO}dd_%Ou@8w{gahTLseJ2MK z^rSZR%^XZhPqeYG<X{dY^aM<Q4rag3C5892J^zJZEM}MeNS#A_C-lrb67xx6UngiT ziT07kjnK^;5Ah+kt-Ylq`ph%D{il8FsfmquPR;Cry-2BzZ&hE0u2;zyFlRvQ-RyHL zb454vm|IVhjcdL(?!TGbZ`6I*+;v_@;NP!vbPuSX2;L?qHbcFE@9qTOCf#ctY#*^3 zFvy}FZ6~|jSGmuop0K$XKfJsF4Dt+^D+H6*!6wm3y~OZ`X^h00Dl$sv&`(mo&b$?C zD6wweKl51giJIrr*eYAIWQ~ovFU8shzfyZiNMmj|ExUZmvA#BSk><C2ze^)n)x&%w zc$f!gU6Fk)={(v4%ys5y{!$&957Rpe_fBcHwSknL;AOS*(xW=^{31ij=6O9Q>d{;y zbN8&vKx^2A#bEN8;2VoPv<|-G_d5I8;Kzsjv=;~2YaN_(q?aR;GV)k7z&LZW@H5wX z$a3Q|xl@jJr74%^^IqxZ_iEShQOoms;Xl>G-?|=BS>7w!iig|T0-I~)wZ?}HL|&KH zdV5@-^<)j)_DZ%#Bjua=f6<^$`e&`d+InH09&`asTB}^2)qDQ#M)j_2P%rOX=lSVT zED`n;Yc%huV~bjAZP<RK?@}HwI_Q>sSO;lsz!UA1a#8Od)yw*Xm6NQupS#`GDe~=N z$tbj3Ql~9z4@yRR1N)9O9mVa&$5?D!d---4&w;b-wieI1Hbfo7Ba~@~pEe=>S*M9L zo}qS_t?{rX@x0gTzKnXyYE!J)<m(-cZfIVfYgf0st%YuHM7QdjfQ`Mg$RpN6V{K>H zUSYKdg;E{NrzyNLzVTtcZ*|X0e>?O}N}J>wV?+82&1Knn*X*~wNBslzvpyI5K}V~b z@5uol_^6+82{MUsFmo}$bjqLO+ii_ew6RY(yC2Z|TiN|#O5dt}GGMkO_hs#GBmE5L z%j(sAuhOY6-nG|Sll4)tzD``BwWb}m=EzuCzLh;ITy4EZ?Pr4UboxGa_`UjF+1_7t z0v^6sLfcAZ@$|!rNjIFjx1jGv<j*UF&Uk<4uOts*B=%0QzjdzuAJhLv{Zm~ayMCp? z7wuW|=Jp;Kd#1nO>F}aBYeyn;?akGhesyr&;APm4LOnf_)29ND_=<C;SgXsg*+Fl! z{={@#Z7x+;>iUp9XSAhyzg+1-m&%!MW~@$G=3|ln#xw7+c1=0?pIy-Plz)5f?a4E| zgA1SdHu-Vjo}6~S$>Z*6+XpZ5y3o&a<>S>2_&9eAeB7Pzp*1Vx<4N(6(*2U)$LZcE zx?dc)MK^PtYO}W@)2R(;F&`$m!GD+RfGgt#vw6pb44Cr_T&$}WWW&Iw`mr@xrD5|` z;X=opwUX)A--%GUu=8}EN7#9OA4{U|(!^YSirdW|X!o=s+Gw;1&C6PwfF{}ndyUwm zq`o3+6YRm44H!<*%HD4HDQo<frc;LWXXrB$czht~2Xg7eO{CkqfC)T4kn}davk-Mk zo+h8nezUfp$|U@7qy2sGO#CrPS7aLN?8MqU+rB7WiE(+Js4L?j*IB7kY1GZ0Oy<?V zMV{JLsdos@eEusn|JYklTe>8h%V2$*J!j16cwBKd`M)Gze6zkxx_CT=@j&nxbswp; zPT>stgD&dkjB%^$GWkfqUv_C$?-uN^+CSnfckoSMj@02FRoTF)@kS}qFBKke?|)~8 z&*;hFg9iNTMA;QG1^(eNz%xD!_y<RUSNk#i0nZ)<jq{A>Z;Ni~yVuL}%?sA1+T~k= zhYb$%U57!>!K>`AMEOml)IUxzv@6bo#8zmZl=-Tc!CrX&KcnC<Jta7R|KhWRzwueX zqYuW`)U#Clvu_36$p;$0SC4{AKA@zsCg0s|zw}wiRqu`}j>y`Ec(OQ!Ivx}p*LRN* z?|nJEtqt(rBRK1KoR?RM7yK5y%yC{`r#h+owO)6p>*IWX?(*kz{kf{=u#NS?-|6_| zqiTGw%h7k3=nI*ADVH}+d0~&AS6;}c%kj#Wmd3d}KbtGd_XD7PqG$`4Pv&6w{s1sX z3np+^9k<#-t*w42SB~!=1fNS2y1=z_Vb-4W-=M@V;3x6D$XIcR?R)fj&e|EmoELyS z5R+zC%~^PVn8sw`ljmx`WuNx5%_{3$Gwr#aqdI!3oNG1Yi}8WxUp#I;LG~5xl=d?_ z$%jr&VeTW1F$w;fIT^*ziXr>=a3&V<^J$V<z|0YBo6_0S{Q{R2{>R!%VJMz&)VI=a zV2jYqHKkSi>ucXp5nUx@f-gdj_#*l++sCfC@QDBTJ_Px;9wm9&y~~iXLZdUTWB=vK zf4gw^(@jV0eP+C5sBfdSoRP_rIV|LXuX@_&&dpBF$Y|D_Pl@?3=x^11dbVDir>B0% z`mvdZW$Q?H30Iu;N15y#KgnG5HmfdtDt_@!>2yN%GqwJd`iVE7sfGF#M_i}-XPhqT zVQ>8lsK@Dxv}2TZ9r6*K=%0K4wzJ~9{yin-gTGfX2r!a+$11@PV>oZS;+a^4^7OIt z=bK577$wqGuf_3Cw(8u`1dse-T|DA<eZbKN&@a`)D>y4peZZ+6<BNOXiG5b<exv4T z)=7S0$L*TWYAb(n?{%`*AN@x*UPPy1dy<L8^z2LHew}c^H}X4N^0`NRFkecVVoQ@B zF%3QhTSi~uPmn!n(1VUBL*Iyec@LTQLhN4p&aOAtU_EZR6<lfDLY?@<r<;UBep@y< zxW?;<xRLgnj{lyXLcgWCD(pyY0AKQ7YOByinNF4ObUxMQc6C-5XV$?{STO(`XQI~4 zuV!P+=5qhwUg0-b?VkkyBN|&?C%p7C@U~TZ{wAL@d>`hS?>O-I3v+3wDUEhV|HAba zU9m0nbBbvFztxLv4%g->RX=imP%vMslm39x(dT2QYfV}E`|v3P$^C;v_Z<%kZoKMf zmEIrld)Y(BQBDhX$ygS;STkmf!M)&Z{K&oFZ9HwX;|twxWJ_x6*i~jLYX!T|_lL5_ zo&BM=DQ&0QExrW)%Cg(rWVcg(bMW!#tAuM;Q^9RS*EGFa&gxjF>s`Xdd50%RzO3b8 z3$zJr;5OCy5}!LMtKPem#`~0RgX^<6r?8K7<e&Men{_W3o7Yl%kPY9ZGNdtYgl|J% z#PnRdb?sIjbLkcN1llFf%%R5nUc7ITPshjL_irvX+a7>tuw~UbowAzSXfJ2;#}8}1 zi8R{OboGUn=X122=eSP!)W<jyT6kxU{p#3~^C|z`zh_5FrZb~A$(OCIH+rel@vcke zG&OcB!Dp{<_X;O`s;}KKqKwVyU9kI-)6d)8TRw5`HRILJH2=Ml_9j`d=F%?RTr!z+ zG1U(@>Ffb$tS)z$Y~GJNc%i=C;w9yc_c&77_XvhDPRM?z=;t{v`+WLXW&gcVWY2su zvZp@ig%*2XQL-|+ls^Gl<P)@RWOLc6?vSz3s(g*1ODCM>v}<0KZ<SbHsuRf<81~e| zA8`x*=<gJpr8Mw8M`Y9`db&gdz8V^C(OB`soDVwk?U@gX@n+bJ<}KFS7&EE=VbzZg zNk^w)pAX3ovIaK-Ui?jTSnRr%pV&2N$d3B|)#;w4d*1U2*<C7H;3rR`+M3a5w7A_u z%l?Af+3Dx+o<;q#L#sQrMdlSGyD7xAYKOq3ZEl@-<r~=}(xvZ|=3Sz>2IDk*Pkh(X zoY!^Zle7Zudiel#Y}fgw&E+ZbDfCy1cE3q;(yV<bj@~>1hr=@`_le$VyZHtj_xR`$ zu&OV`3EYP2JwtpZw5~-)v{C6Oj|clF4IQBu-ka+3XYA|UdL~Z8x8o-_G%Hp~boY&7 zVLdj*cwnLWn6#fzKWqIzaRB`U&-4xZ<s<Ol`M%*+Vj9(T*v#{H^R5AVKcU<FrrHDh z6@NwFnD|w6Oc~yFSnFlNCq=nAs`Ho6q1;@R!!Bp*Ivf5~5A95IV5h8697J20E8b}v zTzQ`3&uirCqiwJ^gZ2#lp$pRH2q)>#m!{A4bn2gtY^57$_!sE{xQV*IP1kk0a<;^N z+2BUWl-THQjc;gI%s0NKSlE@1Ne*9d;PJeVXi*w`&J#Ya^L0gMm+4v&e)?VFPVj$O z_^I=0)z|K6Ur<`Acj_-B@xd(ZtK{6gG(Mo7g~Gp3u*|cbto~*l_tLGU$uF^%T6=$1 z?|C<MU9j8oBs0yi4swnF{eL6)XVeDr@F|Xh&iQ*rvddtuvA!JrD)zY*`rx0Kn0#~q zy+4)?E;IhJ_x~H&@}v6?K7K$p7i%o6dHg<k=KVp-7w@XC;~UD`p!a&^7xs~kOf)X( zAV&O}(wPfJ?i)ofb)t(`Nbb<NKy)n-P4toPk{tJoZ=TaW@?wuq^677>lisL(MVlPf zzT{KpQ5XG)Xd@4wlBb~&&bn>34o>>v5ja(6tnnk4j5pU~LeDDs)k1Z}$nvrwd=P6* zR$jKmyMMgX4lmq4QMpKdZ~I<iyPE8@Z-KO7^mrPwz*cBWz;lm&KA+glUrXkBy?wyr z%32*7+i;G6^l7k*g=4Ysp<~&I>6qtK$FfyB@0mJ*=R1w8GYq5M=jSJ>EOBY-KcB6B z)B2w;{SL$V9P~S^{PUpS8oop5cQvveV_Tdloz9c3&3FCbzj@aoY_F(3ZIYgEYAOyC zrN6>d*^$l=SzFdOX^Kj#EFV}Q-kuqsl}X#)sO?04Q?ZcE(G0U)w~1&A^Hq1edp!)! zWdPmS82v<Q<J%+y?BD#6aL^CnPp2u41I~C-pPt%WqxNs@AZf$!6=}8cvhzYZb0f5c zl=en+{>*ii@7Ld?e!Zqc(Qke&q2J^jag}^ZjCWq8@eVXtj3xg^JP@?Tc#D{EqQh7` zARkwQN&F^h;WOy(<2`luZa(oqv2fpgMcZ>(k50uUCg+q+Vo+#!)#UTc#;_agY=7m) zwy&;6gY(6hW$hv83|*vj&UU(y=~o)acdF!D&pxz9SeI^WwVo`W3yq93QyL%Ca~jwF zUj1tt*FGg*dYyP8j#4aB`nB>S#?e}&&7EB(UWsY1)|Gf^xvs5(<DNXO<PkTL_bvK$ z$$z=<4x1B@-L6(__{~xBuT%bN#hgoo=Q>@N>RLWy^4_g4zhH2+)5-b=al=iz5|2ao zcF}{aEED`P*>uFPo1_cyv6tt-$wT`je?lzSr?Xz_<oz&<69*a7v{a`J@P0I78O;lB zt_Ocl0$*=TQ?JZldl_(3hIa@U*DMu}w6`U?ViT(sUtgvBtj%TeyV{?Zs0_XUSw$Ln zNJDPR1c&V+lW)7N=H+vR<b#~^^0~p~Q!nq@gx|b;>cM{`fv+c@dS%`}M)_QqlMnV2 zvUon^)0NoIc8$?^XFlk)=iGbq=nuV(MUT%H?ZoQDKZ>vI%9w;_{$<fa44pr_A<idk zQ+~{yGgnHxX8q`AkFzgXdEWQXw!o9$`&I9pQs(GB<L$9cwg;a7j&n*|RnO(nE1Q>p z8eFM<l<zLtwUY5p%sW{;*f&%U0k=x;X4qQZA>cTt^iXxy&M@6Z>^?euz?vV>*l$d* zetr^j3-Z01>+B!A&-aXd<6_3Gqt~}C-o?;7$Dv?3pOtsJ*cW#w*m(}i{K=tUPn1qL zo0W4xmuGE#xP28{iVtor7B=a>R{yK?k2O`!`R5y;U1jF0kJ!6)YPP=~TkDjqaTX7A zD$nq)jepytU3tv+MBYG>S61Hqvfh6vXx!<3C+s%b2KK*Lw$?5j_*B-HX%BY-FZpBR z-QtJ*Zpoke1LpPwrU%&o<7-XL>brRE8G7!Z{q25RHs-w`sgwH7lzv6a-~`cJsb=#_ z(8ioYK{U1NJ)*6Dn!!vo7`6Yh_Ad$N;VR4d?DzzD0N><8;M-ETeeZh5Hz~n4N%(%N z^hv@8{hg}c+L+(Rw}qLvjrH+%-J5L)hA~*2&q};(_NDZ#de3Ro6yAf#<TxqhC76oe zqr>URJ^K=o*~yX_<x)Szw@-H7cVBzhPTue7-64}dey-PXa^IKSSN*<eisqt|`&r5T z?6}uAh36#qbCdgde&4Nc@<Au-V5SHBmTU<9{o`9R9(ocO+R`L_M-H1J<_*|wf<^cE z`%AU2G3C1vzgiPBez8B`|J`MV{qg(@o+Zmi-Tvy~j&=BDYKKdu|7B&p<5r>HRV+9& zo3E$;i?#!8U(=o|(k7`M<^e5V_ssoq&sy+2zvrDz#$2R7JyY}BijlUztY2e|EUl{i zs^7y0^Hsq1>K=c<eV6Wg{2tzz<08FJ_q~2UOZR<#KUep&{C=M9iSLmuzJYy;j2Ri@ zy`!mc3eW5#;92eW6!6YbnNGpd2NSQMTb}RLd%DaC5?|2{J0;uy`V;A`uYYiZ=l$CA z_*T(QZ;vf~iw1aCn6i;STlv4FtlB@{EtoF+ovI63r|Sy+#6HxG?A4d=if7i*c=v)b z%(12E%s-M2zjyoD0r(eu${gW?Pv(Nlx}T#o-e0saui{MNQsQl5&JE&YlgdA>a|Vis zUuo;{59qsTk%oP3cVB`HKLwm*Li&s6XM9mVxM>&Az}OJD_^!=~F1s}Cc$Z1U>*JcP z)Hwl#T`A0w2~2V3G|k@)3=-?4Ff9%PPx!h8W!Y=t#Jyklbke$!huYvm=NVZqu9J>W z!`E@GQbsbAZET*Tdu*3|q>Gb0t*dQj{uO-WGo}h1%=PkG3%}mvp4P8@qJbZMkH~j? zsZ4p71wN25?FIa-$&v=0TCctyTOhA08W(uF#)G?9uU=44Uy}KU!R?Y&1$xB~ZJ&GA zrTe^$=6~1ssm#ve?R)P+$I^R+JjH3-j*)#!_b+$(ns1Xm^a%edw-eehxGBSZPl8+f zBiFOHv`2ZYXVbpssq8k&svgp@OWHW!hGzd$uh&Hydwv67l%Fq{4a3S`YUSYv-jGY^ zCECVo)HZsRpKlxRbD8La2K0*kj0)Gc!rpz#<G~)Ijp0Y4EsS>=6{@T3TrlijHn0O( zQ3iQnzgG*6e!5(T#u{$T(_ow1Cu95A#<YQ^HalO$Y?iha?Iy;o@_qKrl$G+$k;WJ{ zwKdK~g=cIHzuPN$ggr~IXCqJ2v6(Kxx&5t&hc2Z<GiC9^w;ecWeF!#5pS)Cg-MXjW z<{n+rKXXq#^x@oNBlOkWvmQ&I%>8WL(<gJ^rF;5t^WADwq|uK<A2u4}r)A$R78dB= zqkoeQJG)gI2qwLD=zPWaeoOT4luh?)#~!<Yt9@fY{#x?rpsy@Ru9UBc4&q6d$tjmu zAD`v5i(X=*pf9Z>`u<M!&+$ET<eB!z#FeCVst)>&w2oPx$2TMBH;6mhl6bideW?uN zmdJlhv40wCLqB?h|7+d1qr*u_%t}8>%(Fo;=6HvpZDD`d?u3GTjnXH`c9BEiyW$Y| z77E{gxqq6N;3Ec}t+K?x&`(^2kLI4fuEp<(O^HWIhrj8GoMZf(k1Nx&5GSf!Dr?Ol z*f~xUBx~a>^RcGS8J;&C|Dd{%_3A{H$U2qfna(@onF)z3u?J*1PrPq+-jO$L5m_?M zI$UKr`xE+tcka;xymJo??SCY{Q|s`wd=#DzIK7Q{nk}9_-GHYDlpZ|62YL%W%A@d+ zZ-?q{2RB!FUwXLi@NuMVu4LnqdhIR6rToFWh3BcN-j!CH)*SdZne)o~foP+QN76FD zJ>|S|ANCgT@va^Fk3z4Pd7oysB0W#xSvsf999_xw0j^|!26H2#kG&Zw?x3G{$Kq^Q zdrwOC1HWN|%;6|*slC6plCemg`4;>J@txUTX6rf+dteWHg|WM$Xc(<5a+BO`oI;zY ze%n(cd7z7m`^q?5i?l}atv5eKxgOEdr1nC)*m_WNU1}GJ?$-lz`WWb?jrHq$IoNJl zbTBuB+^2PA@}I{1uI6<tEjMqo#OG{gVZ$oZq;V&0kG9M+_RDp)+D`gSonC*&*2%B> zGro*x#;=UO(Os(N!ePzDg<mTcX6fIjf3N<j?$hs{APe&;!eep~PUwky=!|>l;GXt3 zQTI0Yxbri+TQ+>@;TIh|eK2e{^^u&LOFJblLcjP$?vW$k$@}fRY&<Yo`$v#5xXbi^ zvNz}=rV5!CwI_!7fpH9bPI+%;oUV$uOPnpwo<;qw9b;Qc*Y|0&Zwo3u-M3JBV9a}l z{39~Z7<m}%EQf7XdXK}N<ghW<3NPVP;U#2;ETRoBpEYaNTl5Qggl+Qf>O{#S+M3BF z<HPnjPjDHTyp_(rY}0c&n@6y?nf4|g_G?ZcwE@ZuvjP9cQ5qX`s&4B8RZnL*gMZ&e znf#G`r(_FGV&qQr1AhtZI~|t38(7+X3R@7Jln*+mi_Y&moutvnqEE)4;4Y}2<T_Dx zjME+|E2n(y1R0@s<Qx8laR7X_$k(-*9B&rfqTTfU#5VNjv<>b#e};M@o&eY5iczsI z!>4*uc}4r^N@6MG)#bRuemjLb>=zo58&_lkFU)CRdwM6vzU#>xR>T|FjkPVM!3VP2 zE`6GuMYokF&+nsstIx7}$S+G~wX*WB@Sc^=-XpXzi0W62Y3H~?A2P(&s1MpA51P$} zl%_Q=-v^z2_bRQ6m{DzMSMaOy`-11R{4hEyD+aRX;49;uw2+C$nRcc?(1wnzUda#} zK#$SZkbBzJ>cznerMtO>BlgZKYo1rSTOb_sD5op*GA`rFn2`1LNw!x;I*=T(74}k- zZhBD~<Iujc_Qh8}qwhm}(b`v&+Q3}lL=V6t8_hwKdbHj=q5K*3VbZte>+L-g-xD~u zptU{ue#&9<T<h69`v4+t)cMpVZ}ba1F(q=MKJC5T6}T+T`sWqe3z3Z@Xam?iZ2;bZ zp??JzZNTtJ#>gYXGt`e@6BZ*oZxfp|_EveuZoo2shi{+_A(NP^oG%;0_GmA?#4NIF z_S1EV_u2CC72(77u(OKNDNl^Dz{}aZnacDk-F&`qQ}*xQa^P|N^r7I>`ewaJ{ymYU z+TxCoSMVOb2KiW;>!rP%>Gh7IiFuZrZLkNdS@xX4t=!9e0{87IgALrFu{1E)5wsIq z+f}%+x6mQ*p+osHdxtyk%c?4a?yABunjZH_k13CuR~pG<f!Hih-|~Uf*Ww?7{}Hg| zm|Gdnzi5{}zF70wv`hE}m*F@)lY_}aI_+_trgFh{^7YZ~&`X!&i+LF2R}XK<a=K)h z`IVK54<z$#nU5SM+X4Cs(JB1&UC=vAZF_cswUwKtryKU_eG*$^J5hbsEWw}$bTHel z#3v(lLRyRB5_kuHv@_OfN6@UgLsr;bKHtW@f}xKJc{Y+$=&+uwkT-oHzJfk8lMS&G z_6V<wY(5a$nOA|wjE|Kg_`qK<Cw@nw(|q0d>bb&2|4zKf{Uqs^zK(l%pikp|qVDMr zY0vPBzuB$%9`aJ(NZ)MrCT&Y}XX_%;UBn33MxH)=LD+`28SM(a)0ZGu`XBb6;h#QN zY#KmT>>(=ZJ<Iv!?7pCN803=blyjjn|2!1y#TrRErXt3}w?0|@xy{WnAMt?vSfQ_f z@M%wDzV1h)$>v%rI@`tgU%5B(Df16rCh$<^9xu~eS!Hwc&`9hV^Hyohna26Z89Yzv zn-Xz`B|5;?IO~bH`2ED<!WD6B#6<Zs7@{9V2hdG_af|5S9$DVz_q6x5evi!ibx-Vq zZtL~m`Ef(6RnS)OqqH%u@PZ!vo!t_9n&gu;oo3$+>e!&~zuW$7!7<0SE_o*ASera6 zu2C#AV6o;d-J@^#StnYN59ibKjveXCmBy90Y?a?L9=Xo%vH#Tx%o^>f1qbg`(bs`@ zoc7{cpD9}d*KKN#v{Us_*8|I0r;PWb9JWmRZLVCJ>6?7X&*t)~3+)?vH#cd$(DC&< zKJlgZ6*IopIbXLZFJy@B(mFD|*n2<LUMyBEt1ale55OS@d}r#L&^6_>_o5cNlOOH7 zUK!wN_tei=9~rEzLzl@xya!!Vyd6W=VU-oT<C_#I4<;v#8ynGiOanUOTVk0^N0v`% zX0K)Jn|lK`CwpupOYH-!$&&Awq;f>ZMd@+>n>9~aM~-~Uv>yD!f=}t;-Kh~WkUgCw zzn{{Um#5AJs?ml#gFcgmXv<`IN#<{z*1u0^O=TIhM%he`!^_^Cqx+vlH~lNN9R8;7 zr7eYu{ssO%er4<&-<l78tPQHIGrnhRg#0gb8(){$5`M${Dz+<I%IdplP;&&vJAHAn zDf|8kwrcT-c-{DhOeesnw%t<5#<wZ#R|E?jHcfr(%Y?q`phNiWdxeEJ56)1X&>u8~ zK7uB#yVhtjeTc3+9_B=X#?K@)4%3Bbq}=MH{<Pf3a`f{4U)IKk^boR7_uo|2r*(_J z;DIZCxKni@b97H%%=2<R(?`TTJ_kJ@BkrS&`3LERJl+A8F7FWDZ}E<dk5jFErDcer zfv1hrmq(0<4d5H#9e?_2*+2D=hHYEF?Panw#hGR0+4~V$U*9R%HkBEsbJbU`EbF7g z%0^w%TU|Wce2qsm5OXyT_%|W-Oy3AElv`K6DWh3*wWwY0)V}8EuZd6TZ`x&}ZKcBF zCP&c+&6G#J;mh21ZSIWx@VS32eNztGq(9^SI^hVpeOPu#+8XH-9q=x#*=W#RSTSI* zdbZfJoV|x0I3k9py}edr<tS@BCS|M0z{{@o`qQ#KD*INo=_qe9Q+a4xC3vpZPR2{# z2@ffblj_uO<z=79dRV(DXE^K8a-8stsMp&kc6cZ`v_|=Q^%h+A!gDB@{6^#2pr3X8 zjHXP7s~q<_#jS08BehO@lD{lbCgK<Rjnw}}yce-7ZJc&xJ~WH1?3^IVN4&><#CY6C z?8kkhcrWT1Ev^hd1C5R1Jmz+Z^YE#}c?*+g;=FmubHsV(CzJ<I_<zPF+|vga{2m`m z4AbWFNn_RdT`h$k{U_=lezK}Qs<V*oQ%wD2#9HACZEjHQD(|zbua(d0t@*5xZ8~CM zd@i!V*M^MX!}?s|(AkIUY1`Ir<P&Q4se8tL#Gv>J@Z{ml{u~Z@0GExghWa<o0X4aV zKLD3tkzJ&RKdZ@9`B_Y`!sZBo3xA|F8S_Um7mV+wFEp7%9cuUC^V7B#Wzsf(irPq& z4WAQb)AmKo0$f`5M3rqczGGfEuj7f@^Mw6H|3<&TyWCabW$q1mBY%7ivb1OU?uXx) zjRm1AEz>nhnV(Tc{-6C|rn_9(v_6wjQs2E}s4rjUJ4t=m0JI*K@Yg;Ht#>8$rDdj% zQs(xgzF{^xO1*iSKRbqc^JT6{>P>APeoG0z6GowZX;N=mX3{8S7A5uO`Au=8_2y~6 zXbkn{%e*?NH_tCR4g2M+yGHigEgZ4Ws8N}Gy(g&*dsO0FCe2rtx+P=mc0xJZk3c-N zLU9AWgfSL*6O~8Iljh-{=@)3bD+Lc8$^b`f66rQhQ#$8tA!BRXY8Po4WMKZn)1yq# z#`iNR+f=!91a0g!qkNjj{7KBk%)6ynsA?S3uJc-nrSsopUVF}P|ADUe_uW6Z%G28v z8}x}E&IJrz^r*hnms~UVz~l1+zC04XH-(q1cFb`<B0tn3T0f%lg}y8XH(k!vSrm?M zqSv3=Lcab>RDR%<86Ok9{uDl6|N5l<R@MKf)Q?~5TV*~To$nV7YaC~%)4&;9jbzX# z9G3;W(~!dFY4~)GhL;Bo@~u_(b)k#0;~k4GUL-sZ_hzza8-p%>nb3hQUH~0AU95F{ zW6{L{wXr1uKL%a=FsUD1{Ac)voGvCg&avp?UxZ`-D>4~$jzJe+%hB-Dph3Fma$OLo z(=KjvyzOoiX&;ogOZu;+0q=CA@OhhPN$5Zq8==E>Vg6V)Io<J1^7>Q%p0EFlD*yD^ znH(m0{V9CD{)aE{cA$2NE^Y}qxGpSC5Dj-a&Mv2+Ym|2J5#hKx;GKpPK2O8;91T|n z4bnwtP8XeycPzS?FFen@Jd*|MYxuO$bkUj9#haibr;81aZ!Eg#QTbH?KL%a2CH13= znIVUqF1j7(Sak6M;b;r^G3esaoG!{igLJ`IfcOMIOS{;pZ{87y7ThKp`N^j=_p>@+ zorZwT+d^MbKkZ?^%7zX&Cl(()%W;*xUeW_!zCHYm`Ko~Tx>NXk{gtGCbg+~9lYW9e z5gP9GvsfxlLuC{i?iP;Q0^Vsz;qx>ceEsk?`SlzP)IZnpRlWY|DD{6{<);U{*Pp`Y z>;Jc0{WnJavH`}BsSWJZ_wB}F10NKQI|KF*Ht?E62iU*|sJ}0Z70@00FLYdEv4OX$ ze0RW)!3JKO)Q=6kG5Gg(7&h>*zdth;8#qfi_<kR<s*J$~T5~j<mZJd~EOC5ev4P`M zzAxa%U;}$|HgHtbFB@Q90UJ0TUC0kS;p0)}sqwMIQjOZ<Z!SFW__ly|I#T$&E%qjK zU<*(D|Lnbgn4VR6@B7X>6EX}VJP9KV$p~*?up=Gy4UA=gv5YXaqfB*>vCi3KdqzlW zx|?1nt=TPYQ+G&WO*NJ%X-$QeSV1weYf7m*r71=dciEKg6D2*Rn7U^Y1}LEwEh;LI z{r#+G-EZz$d7jDetEbnw&L8jfKF?bBy4UyqvF>%R_54zM^M#Y6FRYIII%5BR?UKfW z2i1Pq=wtt$KJCBD^^Y$+K>sctgmtED@l3q7*Bvo*&!U4n#p3~^j~G0Cis46Zn;8$j zU>IZzTO*q-u8Vx<VvEh<Gh*~}u*HPa1-AGda17?-(ri(Q{N`edRcgQg{CrGw%)u6e zu77Ot3#NxSF3lDjBG0+l;+^6#ZuE1o#aRi4VZ$I>us_0HPmjg`_w9uBo&LkVwf=`x z&U%qGYS@=jSy&tDpLHc|Y#j(K<AVKuuJ2Z}>nB-fHf6dV%fHrze!a>y1@?QW?~4DO z`p>TwtPk&|BW}UZ=)(F|e4+FFpo1U%8bA8?{eq8N%J4zw@masf1D)Z6kH=^IvVLvf zcg4Z_#=m;JzPVcI)30B@yKc}k+WOV?>(lSR@9J4?{g&zX%*U#ghxA*mUzdJ0{che= zt!&e;Q@<|#_I|Wlnb2=YzsZm2n|=B%)2~IpcKtT}PPMXGzgGR)_1m~nW%~8$xBtWX z9-n^W`t|F#|F?xjzcKxu{g8Hc^}j~{YxR3(gUa-~Rlh;~y7k+=URd-S(9hQ6O$YRD zY3)Zmn`s|)iJq0z`y}?pbua$2P4}>IpUix{&w5*YmkeVZ|6q@#qIYTdb?!5=kzbb| z#y@NMHGcd9-)kA<ewX6*&nE4^5&fHIzUa%Z9U6V@zVVp42A^7f{TSc9UH3WN>h5#m zzI@&#@C%A(;KI*tRsV()Ke;`g)3?nbX}?yU_6fhTK1Yb5;_36Ql&`N#d4p|-<hi3j zo;O8#$W6j~b|r)PKXNj^+@A5?j-%yZK}RM_ipAHZSm>ur&V^CV?pb*Ix|BCq%jEpg zaBesJuSiaOC6yETYw|zj?QxjWerapZA#2o3J%AsMYEMq>u&e1QZ3h<L?w;ts^SI|& zK1~1Jv478}q3`IgDW5xB{~mYRF2(&vN&n!-cMN}{eH=r+E|m>`EVJ`g*#h3Zv+(wH zDQ|qB%+A+GJ0o|Io#C6>87%l^nVh~Z#X>)2a=tgpS)YZsuS<D@wM@>Rj&jnzNY1{1 z>)3JY^TpJjzAnW=KV@=uM=bqdaWQd#HtwAD7kPzUgKESq?IUyFD{FM>Gqp3ChJHlD zehT#=zR34EZp4GggZ(ecgDjB-T?E^ThP_I1oIQ%=A&*hnQ&t8B;+)3cq{`}%u2=ue zQ%_o%=*WYhJD@W9Gg+)XvRFUVn;f(;ISjk;0=xA|8^cW-aKoE=usrV0seef4@S#u6 zAJI9vl40Mkb9jb067|xE4dUnZPdqXGV^h<e;cj>Jjd2=znEr_^#sfbv9!2`!2UcMV z7@}TxtITv^GCW{qPXD{2TqaAI{!I?Af5Tp;f5Tm*|NGRh*@OC>I`{hDt8=gayLA3k zl(A38PsZbZ9q-fefc_uQ|DgT{sFQzkJ;icy@(k>U?+;2x_h!0B99@Nbaq>ERaDY16 zW=Hd4+Tm-Vo$C5s-K6T!JD3i{V=(R3F<5r#A8hboTn7H?yD#aR@m9p2cKCi7E_}R5 zp8M1eOndbY9{TIoF}^?6p><bf+thaycLtP?q6c(^9r|P4Vb$?%na3laM<O5aFb3d< z4#DMhh;PG>I&k?qe9X7A{2!k9l5b~qJ7fQM#r{3kO{eB^?2dAH8CS)+zld@?6#49r zeCU&L>hXB2jK3m0v|}vzc7~NYeBQS+p3S;{qDywLYmxeHVH^2L7*~oXtOXaIqw8au zOD!i3<Hy%&Jw+Wf_;IK7ThYB+UHV^ec5)3<W!%ekOugD-Kibxd>eYwU_Z8KvJvOF& zYf*h%^HJYkRIm1o1M0I`>Ra^gJ*$Vd2ii(5YbIGuudFeRUq=zYSkHYKo?mYnKjC96 z(r0H8zgQ1G>krym89()J{JM(x#d`30e%&Sf&enBh?Lme6(lhxC&!XzymHRp7z7KFQ z#xr4Br~9+38i(L(s;!$$eWB4N-V11L@Efjy2OTH=MH{=Pl6$HB+I@6wHGi*aypNW9 z>+P9udp-f|tr`ap>A3*>EEE3bZ{M)_&64Z&`dy;m#rj>OpRU(GaiM-Z`}8LL`t-X% zzj^xU{l8D>Ig2OWsNWm(qpkGt1bpLtoZFk!S9pe2|2!WT_E+@JSVJe=1Hd!dXMg|5 zVZK@VV%nbb%n`jK;Kj9l=0`^k=g&1x2A#AD7jfC{O)k4<ts~;kg#W>XS3QP4t*yUr z%<dKAxqkm#26k>&Tb{qz_)}U-)b-4~e!lOyw5<*0ZGAh#+^s(C9%`NeBA-M5VC5bL zp3`mJy?A=E{p_hq{hEW<51c(U)qc*@+JSSlPrx2?{%ljbuoCmI8Mryd=ZfSUOzwAJ zzT=rk`X*Q1BN=;iY~`2hnQnZUoD09S+=_9;+{HL*S6z?V+Ve+N4!!}Ecj!Ol!D_=? zNSn@BW^JsT_z&%R#;Km)vhteBZCtd92mNtR+Bv$fu3g8vFHp~d>iHAZwPcqa?8-#1 zdoJ(Q*zTaLvhE=7F(E#ZLyamv+ML9A<(afh?eY1RjIn*ReJ!-V>>&5a`1TfG@hiJ; zj^_~S+M{Y#4%D3~zp3b*Vfc^pS@WA=*@FDRf17Stys-a}{!Is7pMxq#pZEzn91^xF zekpzFT6DOtkmvF3UO)61c!>rb8ehI+fz3z6kNY^EtMWZG^uW6{C8vA>yW&&4SL{pY zU!nH-v!U$2p=ay}|L>iDwVo-(9^0n=oBX|3GR?Uid}Je@Dc$+jyzNWE;rLxEy}wv2 zzc)uL!B?f*WAx#0yd~lwCZXRB=@%bdCm&&~ViU&QP_z%WvEvY@lkc9svnkJuu**Hp zF8HpEt-0v`d1tr9$^rXiH*d?+REGYF>_J}kvh*MI)K^(N{eAgP14AswFTNdp>Xqno zvFu#b=c{M2|0{uGXNl~07RYWs$2csrxzTvP4EA>VJ|Mp=lKuaQ{_5i*xxD#nnIFHR zeiGx$EtfmYvFuYS!%trcyWCi!qmM-$y`nNZTh&Ya<Gcd@usB`j8&;pj@zg)YN@Rb> z9A!5je5ro=ZEy3a6XL?*X!jTDr?=_3=9kS^q7VL!k0Y_{zyBM@kk6Iq>C>;^`1qR= zzx-<S%YUo!v7$uwYYJq4x%_fdiR`}}Wq+Z5`HJc)`s6z=J2rm4U1hIS{JgwGM{oW& z_K!&~w~HYUzk;&2l*s;k^hxY(dA5&7K6guF@}HE*aeI{Gh5Fpj>Alcl4WRXpUq`SX z>hXC@W%Gy69sm3-FFyDFlG6|GwRu775NF$KqfX|G-L?Hahk@tAz|b#yvCd-sNuJF* z&GWXn;&ZN`6UX-_Bc`$(YDj$?FaQ6%_C>vIyziK8Uew$lW5io!yGC9Z%ia?0`LgvD zbwb{Mv2@+&&*`eq*}(kZmFWK;yu7ae2VX&%pDP*1-;e%*eP{DKuLtwHmzrmNvP2Ib zk9v5avE_>ROkz=tEAmsn9=&Za_X#g&X&dKDpNo1$e{=PjG{(L=>fwd<z0vh;w(~sF zelCgql<Bo-#`*1BZ9>C*h&9X&zr{CnaYo9=sKd9Pv?$CR@_M_aB9aL&FGdgIy! z=j<=_MOyZGIOdv4pq0+qTV>B@>L<0orM-+mtNje4<Jy`X2YzZ}`$V6X>~m?u-ktTc zWtKL`VYrc_tluxqf)&|K7bbg=ytmE5qpaVbn+3aX<K-Qnr490OZNTj2c@X<e&%ZGX zR^&Av$ZLE3pVQbYvyJiQok!P-H+!P&MY2a4uDj_Nowd|I8un<}!(~5tF1`pJ^E>3@ z`l6RF^`T7qp?@#C*I(-_`YXdszg+Y5{hAM$?D%~5arD|~llY>?cj_!WyiC5|2WPR3 zZ{z#<?{jS9`+4%s<vx)54LalcU6IZ_j=!IUr^oJbd~z1-=C9`}Pbl+O!^U+BaCgWb z$=kTbOrF&$Keg-4x)ye-t}!&*drov+tZlpY3X0<Jr1tI~lJ6bJPMV&qoizQ3cs?Zl z%sKGqnCmL!jU4yr_!RBe5q~*HSHxdCCVmsQ+Er)QL=I?7k!K!A$|qy_q{{c{S_5O3 zcDxUZYam5?#<xk91ES$N#{p>6KRTI=WynAoF}p)$9QW%u)3J@i0iD|z?H2~_ZDuUI zK{nz#26g851FGl#5b9qWZ5Y~WelR-p1b-WE#@~4OK8B<36!8FWqfNwU=N`v}v+yuX zL2f78_b<(TtEgY!#`p8Y9NT#LvRSYppT%jjiH)~ZXCB9o2Ihv{<M_*2un)+d<m+!! zp2K)6(n+VVa=nVVfMe_s<`x|@_V96R4u1T9R5_yg@O|gr5^@v1lf(6oUG98X=S_Nd z3AqdPjNK8HF@9{EF$TEq#e3Y=>w3x~!om2lvDqu1t~OnD=+873Xvg`ec+l>0t?L-8 z#~VjK6|cSECtafVGIC5g*V%meXr?hFz5RyfBc9J^?g1b9y2r>`lCi6IuW#=X_7R<f zpME$W=3Li2bv=AL$5zgoF_u5fv6c7gn0Io2p!VfQAJH-2MFb1)_kK^DJIk<;Ya15k zcEf^foTpf<JjG(=MOaK<FI0~`|Bm!H@85wQuhbZ7m%Zld!&~J4ru**1SFOA!DKGPr zZs#Z5t7v`#U(QoMvGUYUth~ri%KGkceRChA^$m8;)4r`d?c2(W`Zj(1|9T>a$@N;K zr}xPRxj%#X-tNsg@?R<yzR_d%I~3pRl;79GoY1FtFvWL<F2d%#`<Iy5DO*~u_XFlM z#m-h?N$(3HUg`Z(ZDnosMAD4=FzlHl?!y>XTpr0ZA1MzS6K{NnTn?EzW{x3u<Cqvv z?!+;e$(ed|%-lwq<$BE3eZubdRf+rD8&Ve?_iHdW(uVy4|1RJ4S-k%h`gm^#ZJTue zX<a;RUceU2h0LYs5FLC&-!kKvcB7FN%ma~z@)1`)sPd5W4d(Y)KBfB#_+}WkyoJ03 z40?W#F#uMZN9Re`cFsK<+^_T%<qzG`CC6>#5`%g9e2&G3?^re0x+nX^hq;OGI_o{{ zcSHX?>!C=Key3P{Jps*k<C@9ZLwAq9S?A->J^Ef9bL$86ZD8uqh0hDdYPtUIS#tFh zb7CWZl>Cf$axHW~zJm_lYdWYMeYbCDGnhX&7IL%ETzBDp5Ke#Zw6^sRh39QTE*IN{ z{R*|C&+u%f>+>xI?b>6zutyR5Bfs+Yx}cz47TblKG4^NeOvZBy+I7TsAwQ4(8BX($ z(+k>l#&%)d5c@N|SbrxLwCjrP!gCI>KeL7P7joL*k4N>%^Hb>1+w9vhPVkIV*%+ja zjlm)se2Bcu#u~QkmcA{AwQ*M?_Q_8g&u7MW3(Xc+Y%CF1EXFWKEyfU6h%xwe8dr!n zjQi5qA^i|D4R?=d4Xee7ua(3IVwS}YA0vnz$X|&u!t7%9{Jp4e;so)8``+3Zs~Z0t z&v#>+@!uz2e*8o8eDn!oMA7(%=DX0;^1a58+s5%f2)39zzg**=XBfixH`(Se{%w4i zUfyYK=Q#eY&$kq`n{E7Ce-{+An{E7Cf9DpoD;odlI6l3g-E8CE`a7|pUD5dWWBS=k z^7*0J>C%sV<NcjT$Jl4CESi7)*e|0Y_aHv7J}Ddf=Ots`=Q`=Vy{xIoTQtXod(+{+ zUcMa0o7Q#uCRTVCG2@+a&wfr3_ST5Yc-gv@Z!PH?U-yUlT7DlV&qUJ?bAG#Y5#DjG zKFN`g4gE5A|2K4|a^$2O4DDc0yo3Lvk~82{YylUTc@_q~7Hc}hf1P;PJ}|z*J}|U) zKm1pszAQ&HeWlkmh*`u&VjQ;Gqkgdi@fe+u3xSjV$)|{ioSQDlhw3Urj^ni<?(Pu} z=)sPh#7p#xE{Q98e`k2#F8kTmhqXgK=F>(F20!5={<8i>r__UmW7f~~18?iczG1Mw zKptd+x7pG1Klq`0%CUvV+hKTZPcX_Dux7%V<@<f$q-_JI{D%8ei!eSW+jX<ws6Kl$ z?f+F4Pyfk<@|()hoZr5?FqGV9J|wLD!ih~y57-d<G9LQkf6$@$qbK$>hIwx)$I{Dy z%F$`iyV~Lp)Ztr2^~i+pr2d-nv9(<_@#~bXC-z5QgAq$trkp^>{$6s!V>H~$&wA9; zz+))kVfT}JnT*DGcpAnR`npqg>5KQAvrb~3yz*jQKXqk8D*LozE;eYF4SLm%W4<9; z*RjPU%4&L^D(GDLKUXoy^dGQP)=k=ZkZ<?VbHiGhjP0GC$Qx*f&AIm(I}&>`9TPLy zOGdV*+<UcKM0>L8c(3*yichq+II=&+5qqbj#Sy-%md0Itpi?r1xFJl$3G_xe@0> zU}9_sdd7?T_hU-$s|+!qsxiVod$+KImo<d#QBVdSe2VxvS6Uwn>|OPIXT7TTTo8X= zrM?5MEMG71+$-ngiR36j7SXe2W)0O^xoP_9=Z_rLcb&q$j=TdBnz^)Fsxb{M{Wrz_ z^=+%rKV>bktVLzS*4FGMeRpy3^w0h4k;6QP<ja0r7)193bDuANTIB(ACC7ywI43^f zBfNvWVHf$pCCpEfGo3d|?JYjon0fSs+T<bPZCE45e)y(eRo{2X%hm_~$JSuz5)Jks z{&dGV+5E!mWS+ir5a{Gn#7m1!&{{b%hw_YTK{rWvA5+~;!A|%Lb27TSLpn!Zz8z)z z*Y*qtb7<}#n$yMm@8&p%5>tD`6P<zyf5fNJ3w;xZDI*qHU&LeD5CiJ^C(iR-!=G0? z3FYDiJ#&4tVu3FU<63s3tXu7^4n6m&?A?(^cL5K|(1qm`<Rqua<~7BzpreT6P}EZc zgT|WqG&V+u)LBlVoF>?w`Gk4H=8Uv`sCVsyeBzD$;LCGz=pO!lpN8C{l|JPw@0YKD zm2;EB_%!-X>J6v$!@Xre2KDXb$m_4s^X`%{^1!cV$PwiWc$^N5cZzLh-?Q@uS5?nS zGQZ?=Q2uR(l&8s?iH<hRc}49EqtTmw((>c+F<qqkHkskaoPq6b(6}kGpVxPa=NS3| zy&gj&pYS{j^(<VeANe)`M=g(mGrnWT*pqIX>(_@os8U}yT@)ADYb~4y8E0|aTP$Gi zCl-YM#XrOXjcsBfaUjHQ_4#ub<?}*KJn(yucSalP#RnS@$KgXf2>euMarer|FT{gc z_!Y&5R>hJTcr_L}^gbxN?`1)MSS#kwj0#7f)fio(eA0Z(Vje!+q-O@bzqVvI&Gd80 zz`R5*Nqh6R1`p{cj1lE9`1{QE`PlNl$ai+U-BxMODAW6>$7HwkTbZNkj~E`-KRU*4 z<hIytME}eu<Quj=U=ATR^r(!se$M_y&Dpdg&Qphdu?z7_&k2Wb-C(;OY&RI+&8G8^ z*Nh%LAE#b@Fm9J+wBI)MHFQ3a=OXYJE1<bgH1uoVTtuhvAr~AKeWqur887SP4{1Iq z+*2p0d|oE~s=ptL{=@i2p8KU!c$=@i6q&FeGTl6jOh$9#%P7-##0z_*GI<;7IqpSf zyJeys%OrDU@$_#+9ASK#%_{3A18p3W!6sQ=hMugBF-cCa(s-y2-s9rkBi=u6<&jVD zkA!#diCK8RJMyskKloJSL4F==C;m3J$N^54jjg=lm&a+-q&6dQ?Gx5#!v8Ae4ZaMS z{$u3rb$gW?ANV1$4?nt1aU+Zq(`)qo-Z<`v3)CC-pr1&?`ifX+^>%-ctrZwU<Z8y> zx9xZ3Mo&)GFMiCe_i8+l6EOD6Fc^J4Z(nn;(PkD*ed?p0^pWB-nv^ee=D+`yI2YrM z*XNZb`ee_2U=BKkZg38Ig^s<46gxVnZrIhCe%VVMPGp}=zeb<xVK$o&sSnoA-i9eg zqe=OC{eC{qBiX(y4zAL>A#EMZ_u2gW44B`UfBgDIYqdpu581!>fjpR;ig}cGAB=0A zrf(oVVQp>gH(%q#zNH-260XfZK6m6W-}x!4|N65>4jVsP-<~9XlrhgS&NJq)8td_V zt;8IcWj6&(pZ&p+!)+1MT<G7c_fPn_)^x<4V_A-5Ye%ljexUZPM^Df<8~I)v_XaMg zUlG=lEd_N8V;%mLwmVgIj0JL0Z0OgS=eu=gt8|G@i95Q+z5VN4&y>6m>c2xgXzT4b z?}e;GD>qK>|H{=<UlT9-A;123wK|!9bG16TPVt2GJU)lM+p~}9C%x<6zIWEHd6=B3 zqWH|(^>oE`Y-f4)UnjYZ?FriVt2#2tul*D9nWrwhMepCdVX{Bdp162@LU9_KXK{}~ z@+)7NJoH7$@5}X$lSTP@I^Q2r?xMXJ;jXXOxBTLsv(|ncaZT5x<34@&6F;hHKV^aF z2lcOanrI9xo?dzOEs}Z5V|*u<^ND!Qw{kfji|4k+Y<s=zs5<cpYl{A)eQ(mfmb9N2 z+e<#h$H_y#mdJN`BHyLK#yNKOqQS1~1p)hgOLFXnZC5-uS$4#8lf`s_TqXy{td-H1 z_B?`2s~lf+I~Z-E>-8G@i>H?*{fxSP6dwYQ!GxyI(ZHh`?NWxt^us%Bpy8Xv^=K3F z+|GE++|m_~iMur`C!U0S@uullpRfE>{tch*SkF33?_>xzW=}{q4c9h$Vwv5O!hI#) z--v(aOD)k3-1lL7&DLIPfkVCG#kg-)K56@v-Cu34j4J?dRN&jC|4bWo`*plcznwZC zSAcs)|4-_-O~?Hz-=Lqxu2vV{8GGyzvPZ`;afx#^%g;6DLu^%!Rn^#CulO3Sl}L7U z^UbB~t;r9CuV{ZQeLoR;XpQ?=e(qq7#15=a8OxO;io5EMc$c?n>}3YOHJlPL_!IBs z#x}(C^|F)43eJ!IL>_0*<6LmU3!5D6Ki_+s4fBJV@4(C&nf8WJ*VTgkTjLmzZgUwN zX1?{CVt%hM=W}7iBK?FMQSzXpk4Q&h53WEa-brM-2MadUJDze~MH?@T=fQWi4hs7Q z$~$d6Z~kjz*5|tTwCTGh-nu_(5%WLSq^y09e1<aSBH|9mr{uH`pCX@zPW~Uhb$d$X z1BWzTx1X$dmbOP`?9iI!zA+-X=^MO^mDK<29ZBtppEK`-@g#i}z2Atu$8=_M41O8M z!y<AUljjSP$8s+AGt6(dz3KVGw@M~!_fE~tXK8*4-v(C<;U3=5PQDOi692F-pgE0x z(&q>mhrySKEuslAC)4|gGSMgR4&%G-@V;DQbS}Jq;|1`ZD~6Yw?r$Yi(53Qi^vL-A zE$OlSW!59Uab<kR-wV}a&vEqVdC#VwSCS4r`WS6vguIHFg+JX>zhdg1y7ENnVtw`6 zh7X~0KVFX4cF!Ez+IK?b@7izIbx7T7cc=17<^b}_^$VMi+yC)+?3n`(pI2fVWdBU{ zoa6Rg)b7w6+8JicV~Hn6Wj=ntv$fx|u)Mv^{mcvL+71k?H<;%yR-Vh8@`2isaDLZ0 zdqU1*=R0){J+W$@{GMZCev@*sg*-2y`zAv?R(xlT@TCjx)%C>1(`Ur_mpqXiEcB)8 zkG!8y_Zui5SDsu`E?T*2iu`CK9&3IN*U1Jsuic>gSJhVWmG*U4rsp0)neji8`1=yQ zL~!2PN@dxSYGwEweWPH<>!&N)Gc`M6`<>_LnzH`y>fWP!K=ZX0{cvBgFx^ibGHLB{ zsJd{^W7OHY<!SXtJ^c>|qa6>1`Dy0(F<Yeb4Q&Qu&S8Bu#lDz(=&$+we9se~A@}6^ z+DFL2$O#gf_DndEGVm!+4fyD*DdYWow@lx-Wc}o4G>?TGL}QX1uSxrQ0h8!M---j4 zJAGmM_U&bBGkhZCv(lUL%0*y&pTijDzbFUy6NG*;ayOIj`bjYAy7d#_KU%Ie{h)FR z@%tJ031<r!3)-gbEEfy8SHhEZIyvGoZKOY+lkV3&;OK)g^8wBW=cvcv3-T-CspazM z(R|VJ6?A=9--F@V8;-wp!GqzMCB_ze-u&Zt{By6P_Cd6_@MRqzc{GjH=4*CMhrR#1 z7hEy5YsnSiy8jOCo!_mv&t4^C`n4K+4d0iXwwExZ+zel=N%z6ugkzW5-CetS>TbpD z90OxtIgEG^4?-N!|FfD?s`YaMM%wIBn_X(NuKC)Whw70F9Prx}={ZM!8)FYMrlr4- z+c<1`FX?v5nZM?O=Xr-G%y|w^;E~{AP6U67=O2X!-=t5wj|2VN7^%m5c^T(LdqwD; zdCzn&IfCxlKf)Kezku9X>(}kfjm>?s{ot1$<@oY3`B1dSYvWj8e`#LO^S6SZgllNZ z=jjLkXo)tUPy80W(ih)<Mt^C)+MhVuubu;=-*dna{gC}}t|c0OvvJD*pQ4`bjQ7mb zH+r&ro-K|nm!8Iz*DX^nGNGJcTy%_sJN2Hz3EC)Tj7u+E^WmD!GL;c$@Hwrq7I8kh zTkp@D)b;<$J&&JKxkJDFe}3hU9-m*?^f>k+hK#buFASH|V;s>Mqf)!}AmvrX0_wJ? zjy)Rq^1Vm?x#q=x>u&J~-z$-yYdy=p*6ugt*I$TftO-1?>&1({Ee>h__)gY2zD#pn zxQ0eNnqS+abr5=bm$2m54=Be*>}yaL?4|!b%J=Qw1io#<7)N)k*U*iY{%zqr6J}lK zJX^TCRR6Pajm?^#yoYrbm=v?0fc{ITJ~+kyU78o6hYtPH-ei81HLqk1ShdGVd-G@R zJ4*Rj`#=-*_ICw5;0N}z4SSS@eG2MYbGaTixhO*q0h?mZStYU=Uu~HjgN?SKUbq+! zUo60N=h;{1Iw41pk60WxA0|KJy#n2t_9qAP{YiM?uf)zjd1LNxXKFozuIP_<u5u3$ z_oTN=F0ipq4*Nv8oQrIHLT_tq@*w5UVcgEsvF7e@thIP!JcE%q!h2d(9@gmd;u<}a zXUzvkH2*hOwmcTbrEIxQdlBrPi+702iW8IT7x4U$?wM6N7#M@iOE*7;T%DXdU2NFV zT<O$Ao6c)Zq6uS5eMp|E6SW^rA8q<4?>I^S#QW2Qb%}JqzkK)pdHUy`RQ@Hy{p4dx z=h`MD=K>v{rsEF%zfS*GtL(>gtoK~E@eloL^xvZMG1c85*=c`erSg%V)_Gg~>V|HH zm*(F~8&UaSJbs&_k-iuGgXRMK5?$6J&7f#H<1z2q_B1WA{6dvKi=Oq3!oG5z_aBHf zKQ5a6@mT9i&-4D>vHWb6?~KR1U)y9!aNfT)(nwEFY>vlVmvK1nUlYs8xmL$xnXthV zc_(7IbgB4|%R(%|$M8>lz^@aZ{6cf3<&NeG|NNfOFVi{yluyQT>NwsXf1C8r&&Jey z{@2eOoM_UVpm)O)=N?gvwtE<efi}MQXH4P8+|T}9**^HH;)2~{NA6aYe=~RG*T(XD zk@9hs-wW(%^<MXbMfCVQ-w-zc$H%0j5Wmlqk5LX!<<a5(V$ZXPUp}UerG2UWbMJWb z9Oa)^Ks#Ii;ky8m6J5+ze(twJ)&{POSaSU&*Sv@++>27Ax7pe;Z>?EG4BIyKE#*Qz zioZdhPHy;fy*(}G`Zm{Y@rBFe7hDG+F78o0>ZM$~4O4TXAH&qpTOv!NzZcMs{&t*^ z%d$(d)T1oqYTk~>(--AQ>$tWausfN0qfC8KCc~EcC+{7vi-v2<rjHr+QeCi9r1N?U zx=nDR-yZsOSfFd@Eb=ot->=V6X~XkTjPDbaPZ9(Ab^M-7uL#%t8T)0ifO!A@rhNU* zI>W{$`W%S;TU_8dpt88&X>D8-(VI>^{RuIS6w#YsdHVUY(A(JY^n441xKhO5bnWS1 zH48m@PIa?z7W(-G^ry~3&+~sNf4&7$hX2F@`ZH#s_q>PYBg68Y@SLq;56AW`Ec|$6 zmU_nGXsi#<&Bpfj&KcT|%~DVMan+B=$Hvqz=MTL)AKPEmdSIExw$*to#FY`zlWT#O zm=yj8Z=Aka?MEt$r@x`KhI~Fe-_3KA$N?|bCiDX?J2&2=swZFOd_3a#jN#DvsQ7-> z@m(f*XwgAk_2a7lr0B`_^M2L``M?&QM~?dGmc1;VPpEBKJvf)g`tW>lY;W%jqVE;6 z)YE>Y>L-MAMU?xx_<f~cigH;UybKHDXIO3c4hz>%pvlL4u4n3b=A<rO6OwtY(+RqU z4{c1>V6=1VXSwQEMqNJ{zm+r`F-_`xx%mDk$Jca?KK819rRoO~T_Y>H#Fs}h@mC)n zH-2s9#8LAbe0NOrVDjbov6Xv1*m6SjthGHob{$uFsxNFes`3>H9_+Y6<@lZPNn<)W z6fu2^-jzixA4HeR^M>?)yqJEA%kPHN2fDX7&NJU-aop2d98c-VY0v|6#a!|m&yzTo z^7C_}r+umY<Ez9w&$Fz5n+H7YOYPt03eU5wf14*f?Mv<7<`U1dtbdzFJnd}#Gmm5c zGM`<>zL|1P+XHy*$B!KOT`ejrJB}RL_3OIl;t!7;S^Kr4?=az>G20vHsqq|s?&G$f zY5RRz`)+TQ|E-r@*+*ipL|8(OOpar9*uED1o_NbRvO3?6y~N96Zfo_vEqgz{o_rEa z+-J`9jvn>TKGc8scYv!M8HFk6O7kPvjllK>t-Uxd(iyotdb4^jJ9?uY-SwhpU1#r= zZP?TNlJ-g2|E8>^_R&zbQ)S2SspL3j^qsArd`A1F+%NJy{j*<&AEE2_zn=Tl6ceRq z<l)})hD?fK=zd%DE!#`Bef;yj`7;N%R!^F~d7<8u(4Ais+j@S!7x-btPvjtO2A@(N zCoA{8S#gpw`l8=vmC48MH#xZWL40be=o#n?T=Khcedc|WK_=D5F%W#PQeQhmm)!f% zT)DomExP9VjIHskt;x=wK7F&s!lsps?@1w#<q+40Z-4g0`jE#(nxlDGPQ!SjEqxlF zkXOjY^pBnEktXCTk<Zb5Bd6&TO;4sZlz25~*K7R;u6$hx?|MbgPO82sTdQxr<>iK# zcD!e&KlWq&*JC;NC!2iSN6xyZlD)6N2YTc0%S~43;cv1U_JBv_V23|?>My_vA1n9# z(Z@gm9{5|i$%`+*pD~5)$UE>mVheV~_x?}W^~0xJad2DM|N6vZ`2W^;JfQvAmTcRh zo!Vc;XNj@5>A$9be3?BS@5A`(&m=yKUoZAP?BZm5P0xVv4MX`Y`G8`)a-sOlnK0th zJ_Z>5jPLR}dh^vu$;2M+xV|gr$I}cfj2mHLznqvIcq{gTg;;$I7SV&HOLgQgMh})+ zMm*BqNC_7566}Ef=#OJ`=k4$(!hExIN}QXgI2Mkzo?zax*wXz+&6Rd-_AS?DtL?e1 zQ=H*?WKXN&V&_TIJ1@)kvU~cu9(&UCum7Z;m(o5LKeHG9fN!7=-IE+*4t{};u%AuL z;n?D2(2?R~e(k|x&NX?=kq(j1=DkY&`oPC*7xb0!+!i!5+oDhGjy{pw+G0oW5OcU6 zYgcc6O~&hRZPa0mcfrU1hv<L(WXW3@48I-0kGBM$zC9j4C7;gZ)6Mc}uN!>&`lzeM z`;4VS;vGI@IzvC^<EAt7E3Y%=VswJs>-0U-BEK?v^w1OaVDv?P1-<D8A15x|^26N6 z3$f@r1wKxkX<&&yPJiCV0~XPPrQ2f>Jy?jB-p5lc<UZI3Jz88tciukuc&~Jdt>-g; za~yr#a<iR(p#5a|_^r;ze;9rI_ES!pzT>Q;K7RY9xsQMQ1^W0|{|<e8-g(FRc+)^0 zC%g{v@oyi;$IpC&uK&x&->zpgyl$|~4-y|ohpCUFpBL)m)$SMO<IvC5#~;<RAdJBx zALm;83-NL2Uuhq|LpsIBb#KhUaGdz~{@-t|?9fHz7U$#p6~p&wpJ{)l_uVS5UGs)K zXWXZ8Rg*pD>$=W<jrZSt-SdYZQW^YpU(vyEEdHCDD|*MS@-fls8dDqpx<(YP$^BwA zzb2>aLH9F9|DN7&%XOE3)&DxR;~K5LF&nOBzO}j1_FF1@N@Z8;n19+0=>Mm6KB)h< z>3_9o&OG_5L)YlI+J4oc<@#^Z|GV`6OR59wJAV8q)@FzG=cpG}<|F17_R;wF`+ekq z_$%eMr^j(!F$US0Gw@r=u&43pcJ=TeAB865cd?&7M`QWf9>qyw7<}(j8)8_%pjgQM z)lQX>XF?a&S)$u(W%Lv2?uz}HEaVcjx41}qF9&rdhhaBfV7ESLW4LJpZg_{>S6Ftt zbLw~K96ovMzjkt$&WY=W{SKYOlbCI~>v4MV`VTp6)Lp-$G29_XkM+H--s?Z)zmaCZ z(G=<bcCaS;->Ndxg~@QMl{x)yiE^1NW%@Tcy#5V)nf?uTk^Z--U$Y1Gn|1E>f3wcL z{x|9Tz9?f|$9v;(pN?<Walig=)&GG0`>B)P)b-C^Gj?O%<R9N3kX`T1;=4pc9-7zT zgZ<ReHe<fOChRrR4qprHR2SAHv2Lg8up5}}ipOBus$;Nh(LdPW!MF_k)i>9o^86t0 zoAFk}pLUGlGF<q0kv!W%JFTbn4<7pK(=p?9EMAAJC^q&hhW4orU15j*SoedT=MN94 zZg=FfEAjykV*q~W5L{jkd>ek$fy>w7W4@i&FTUj4S>5K?|EAc#$GWLAzvl2ig%vrx zjH_bZUq?B1L_T*!KFGm1^>{p1#$OR0+A$V<JHtvHKJVKZ&oJ*O4zuSHj^&Tv(s#y) z>zVA6=^wokTR09eJjU(8S?aOb#?x~>{Je6aA?bnk@EO!U{-2+(pHa@U?bPGD@UT9x zpJBi!ZSEM37>ep?-x4wWlrW4$42-o*K0w~W^@w5T4`8C6zJ_%S9{vrF^@mQ_a~@G! z)3fQv%1y_VgO6u~)4q^pSmo@I8lM}Y{yQXFhuVULf3JJ+jK+Gi4>b6W=?0pyNMkZV z<Mjv4c%(5MLW7@qKFdTiDvV>QvwM<=UC_dt>lDkJ9w|4xw8It?u^;PyJeDty<<N6o zV@&0y3-~~9{C&B}3O)QyR>L0fs2uF@K~EFnpW=j%m3#i^V|f7{_*=Qz*v3(l8%M8+ zcI;IDow0vx$+6`X#Jv@>)Fao*SReEm+nemPUo}fT?N_UQg><w^{c`?vygs&8arQcm z39Iv1z_~*7*c!apI{XjbIK5NtS5y{H|Nf87ye5hq@VYMc11>u^-YZqV8ot84I^uY* z;fUAa);hk|i5^;XFrxa^>i1ou=bC8V&-x%A*vx-9?v{<rf7hsOSv~q#8|#B#M*W%( z(f5W~>S@1G^=pK4LzH{V!aVNvM7gXEUWSD+)2TKVgP<{A0&5tr()EaVt&z-^IGu1! z6h5@MF7^pVJGXw;s(z#DId6@anj@xX7u+(vR(#KOd`;KrV^Z}SRsVg>Q(o7|3O>ft zicI{~hsTXyTe*!T=<(fEq6d>N$B(Vt^TC#DM87(r$F8eYp6UzRtyKAj1P^xHpmO}q z`sLn0)-{)X??__}=I1}2Uw%k!pm|nn)*sh-bzs|}ec3JI@rlPy(3+gO&%XBPx`@5L zhwAw_;od-Ne}eWdwQm~QZ;tJ`kDT_u@7lAEV(m|H?Z2q@T3&|sqp|&ovHfqm_N-B@ zeYiica`ZacQ#b1EZ@QRNcD-yu9oW62JfGvAS2AAyK0~`UvQM=4DSq6C+{y{aZ8;v4 z&cnIp7JQF6oN|kKMmLer4Mn=(`;OmGLf0DU@CD!RayyUxwu^4C#<lHy4D5C1jN7|( z-m3ccSijqyQ@<n9dzmOl9_DMxO$N#hzu|>9<%ZYrvFA*=;j{jC#r`;_{to)lvGLg% z`)!SQZ`U~(Y@Ri}jwX6A{nxEL+G&-YM|~N7o1cx}SVCv=^jUf2x7yB2^nYuV51Ei} zi_X3Nx4CobH%EG8G?^&(`ZpOUH~faz^k#SsUzz@Ij{TYbH|gB#e=Fy*o#}t0&cPP) zFXykri5^V<Jyss|wZhI5{fBwX@f%6#OrBmVkNj5Jd5QivMEOkr<ON>;Yu!2eWd3IS zAfw5Y>fdDW`Zv6({taK5{+ZM0&-A}i=U)HUaqjfLLg!$!T*&-&Jkf*czu(HEzOJ+L zME^GT8^2`<o#}tT$|Juuc3z_Y<xxJ<|Cr9b{wLfy`W%h)$Y?U9`ZpQ8{ta)cf5TU% z|7Ed1)BlLhz5d5JclsaJ`K`i+ep%Nu{`TshH3d3ijm~kqj>DQxdTLb}IVCcYQ}W*; zy}|e1Otkv9Jb*gp419vUkJjwy98O)gwNqWVjvn_uHmeRyTl5d6yYz3EcEn>a!6P&N z>O1Hw?z>ReQNo|Py0t67)o1Mzd6ugkxF+-ut_}J(Tx;X8;Tkml1-O`B%Jjv2RHiTH zpU^JR*J#8w7IBfE8!pxi92+j;aNu8ni@00FAAJ$0%Wx5wi{!ak?QGxYH@o!?N#z<_ zRn{H%f__zH9V+XPe`G4RF<|GGd+bsj{<u^BCP%CK#NPKx4sdy&YgZk9NFBI*T~E@^ za!O?EP1;%ACe_)#&)bB#Q<yiZY+2k38d4eWspwK)ohr96Zs*8>zuciZ<hWh`CP!z2 z$7Ag(!2{O*q@7`<ZXjuAJeR5N_PC#Nx-fHZ)ws&G#Il7d3*Qrx95t1jJ-Xw$*<+3B zkmEZ2n;gt9W%gh`DYFOjk8kJYV7~F~tZqd8PM(&p(WcMIpI;bO*#og`Qf0l8tyj2v zRBraLbF;@v)gi|U{hJ)bX^+QrhhB-xMR=$qj{A0ol{(_KZ|8XqDo-G$KsTgg{Dfo6 zzrn{jG1kh!`eNg8BQ6!hy+&M0;tTyxIBd%uX5zcyGOXRM%=8LfS=@oXEbh!H9%`JU zU$0kujy({t<C~S;(sOpj!67}fczd6GN6(dk+n&pO|B~kqL(4OxCI`=@8va)C@b>k6 zwX3eozUjE|evys~Ux)7-e#Qv+hlGDn_@BJsSo{}8{5;=l_<J4xo>}nsCip!L`u1}B zIxv>W%{+sC`{N$bkIv4Y%|XY^Gt_m(x~Emwr}5e+8`f2CamUUr?$9=K^6?%fvrm@b z^!DjE4$d<9!0F}lvNInd!+6}6*&`XaRscrkL+S=%-7eK}&0|3F^+)*_^LB3Wh_*a~ zZ1(GO^3}!D<Mi_N9S5gx=Vbt=m(TMg)|vki6aDyE74G4=VKO|Mt^3q?miv>neEje} zF~i^G@OO%b$Km_xngvH1k3Ig`;xRGT@DrQ;__-@Si|O&dKjQCq_<7%l`B(oe_y-dF z9wU8wxqTfNi}YWq=-!BZdS+bj7-ipQ<jvK}rh#gu{o-n6<RU#asrMwb=v^$Q>wcUS zdd_o&?*B(t{@02pzK2hd_pv6Re30@;v)j>3#QHG5#QF`c9v&T$X2|i_>u5SvPfpBw ziyVW#Czk4c1M>G!E*^~OQI(M&LDv!KmRTA75W__`65D!tC`T6ShdPskI+Me&8!xb1 zpR_UDv;j95sR#3T?3Z)uhjmVW#%qjo(Hr(5ox`){^s>$A#p{2<(M&oT!`<!bZ*}!v z|H~cCBaWs>|ASE$um8HrOcy4@fR#D@_r|u!X7Uv2-{kQ6H|(afRR4y%NdNt@U(<h& z&b|KoICuK*);So7{pQ=7onE~DM;*;RM`QZ$aP?bUz1RPkquK9hiu7NLvUvSxDogd> zWo1tP?XfMgnLI`MH#xli4SSjX4R?|LJ7d45|5lxQ{daKg^xvX$FxH)3b~wFw{jYK~ zPdOUXf1j(r%hh}RuXZ#~JDMW>SE4Ll|4+GCVE+HCl{x)C8RG)7nLI`MH#xli4SSjX z4R?|LpK<Ys`p0$d_5U>IPXCYS9E`0_FB_d+y#9wB&3%r>^xy94H@SMR{}D&?fTJnW z|74WK>wllhQvW|-WlsMO#J0$0@)YUc<na18>}C2l+(r6-DE4dqf1l31{`Yh4^uJf< zVC->vx!vi->wkr#dEC*M{(D{h9j@N%f2E^&($N&@e|MC{>wkyJQvL6;GN=DLVq0W0 zd5ZLJa(Mk4_A>n&?jrr~jQyJaZ`Zlk|6QCr{okr{Fm^h<Y;}6^`X6^R4>=msf0wJj z+0}dfFLN{p98Hn_w?$dJ{x_>E)&I>_=JdZQwna9Rr%3-Mhu6PhFVnx_F4F(j*stk- zqt3nlw{Y(Czd`3<?00(E>Gb0Df1RUw#?hGm2VDIwSMT+|#?d_MXo~c|Hp=4lze;7P z{?}NU)BnoY7THXmBK?~jUjK%@O#g<vNdMQxeog-?bnf-PnscZB<vIsrtNu?5_mlIj zvHTf{cIB-#tpk>+j^l0}qic>?ADCV_Z;8633|*4LH*$3C^|#VSd;R=F3x<2M{8=Ge z$5B^P9r-kS{T<oSy?*Mtt)1#RT^;?i&NZB@e+_5maCJoN9j*+l@P;n*D@;M}@frYi z&<DIpztq*OT>;)cYnR9g-X7JV!%AG=?>#f$|D~=s);*&8FPbacrv6HG?6cOSmoC+t zuh=>34wId|CzF%CCzG#LJdq2XBd6DSyXv?Pg*xQ)b>Q^vZ0(8c;PmaR4jKAYhkUgt z!zRhVzA$wIv92Z7eMoh@Kc+{0cSre<$IioAFxrm20h5ot0h6yY!Rck_D#3{i;4G65 zoL)Z9b5M1R8RX%(UB_I1;5}hkJm#HMP4#W3>UoD|-V?~V?&ELk(Q_ZIuhlzI&#hKA zc2_I+ol_0>W^6o5$7fb6t@;hWrdp{lu2xnps#bQKQLQ}HS*<Wm2PHGQ;dn^L7W@2o zr0#g*5gNv$(FXrc{FFLmD;kf~4XG})OU4Ct6As&Qhnex6Vr5)g8TO<-bVcKly0SQs z_gjv4x#2C4bGO5|*I{4lu;F*~vB8xYUg*m3LSLre-PSINAM~@=+7;+`(qVkWVc(`U zrc1+nt1C0S(3RnZzRa$Z)~*2WBi61!zay%%_4P2v+KXPMz32(v|98Pz$LytVS^WHA zbYSs}V~b~b`OI-^V>72K9=FudchPvK4vc=hTRfv~rNh4>;-3)yWx~I&0RQrcpS^Um z1AFPF|1_?8{AF<!9Q0j=AB-Nq=lOuce_zCJ`rp)dtp58V{*4a*CWn7xg2VT<X%-yx zU4|cw9>3TBld3cSd7NYUkLiE-O~>MIiTH1K`0sG|Z%=S|{CCWPgTBk~gVE#nJV#Z> zxP0o>!dlTia$WiLMQl12>)KDt>%O8o-a*EF{Jn8LB+lEp&G)qBT88--*D}n%$Y(rG zkA-|@Hk`hlw*fePJ72dd%CIlWuvs#2JqC=cW8IUn?srtjb&h_?*B9kuPP22H?`cae zXY!HbnSA739;cVD?>IPpJ1+w`y?mbMz9_?v({me*O9rmTfN_7Udmz?bsk%Yc4NATN zXFogl_S@{_+v4QgES?^x$Fk)(IDI=WA2_{yzV4|g!{*LhzM5p<c@5-yI@aA0>&{T! zu<C{--;lGPoqPN3aPr;d<l7;h9;cV@uH)eJ?Ys=&^zwP0%a9>nn;7TV%|B}|lFYi6 z+ai2+E%)g&^7+T|P4r;-CdXy@W=>a*gTBk~gVE#nvaNCWuZ#FC{taAwEdIR_Ki8sc z{BSMG#!r8O!|N)|dp!>NF2fH-kKgk=0OqLwhd6fnf2IKcmWY3=!+*2Gzcs<(`?`4+ z9Q0j=AB-Nqm-|`O8UAND7Jk$JU6&lI|K$<?PKSS&!@o1Z;qmX91qXeX;RmC~?|H6O z-?nbppyOA1-LO_z%GM1VR9BW??snM7!wvJG+N62ykSjC4hOR8Hg}%Jsa=d%3T|r*E z2@KJ%H*)O!`o1^kenAdvapjwxuS{M`-(`LQM(-EiuOD#u?~C}&uQ&YUvH1Ta;vbew z7FR}eZ2BKgaCjdanFR-Zm*EGa$M1P=QJv|ZIn(QZ@X{PVeq;LoV8s7&=S}H+?R5-B zkKfnrclh^3{HFhB3-G@q;vaSTA9MO26%VgRudA_HaL~7JmtyqzJ<prL9Q}VQ$Ikz6 zz3`SWueLk=pBeGL-191Zm*EGa$M0o3;P5{b@tgi1|A}Mq|I6w5_#JopU*_~bp5XAh zS~d#~`Yyu{Mvvd~+@?DGdobR&c&Fwao^d4)xi!{x$GR`5Zd7$Vi#g)*Qakr~Y0b&k z?c}Q^I6ao`<KQfl51d{;Z=cC1!$f>{>TgJfu_)gov2G~VeL!{NsvDPlV=gbXbDx(^ zIQf=4`6k5E<Mi?^KMqdc&dUH!FQ4am2QtL*b34aw{H%)i7!s>2e!V05UysAz>+tu8 zhsWXj>YW7#efxGEKNvlJU-zWy4FBUC3%`w@yDrGbkH>#z#J|GfU+M6#NN{-kD`&w$ z-(~p0=<$1=cd5?s@8H<!|C#f1{4K&~`u~^H^6_7H_+RY0)Z?J<GW=ll_`Uw0cKDx) z_)Y%<1^DlY_*XgntDXK=B{)3B)wAHB?=t*g^!Po`U8*zv@8sC&f9=v-{~b>MzZ>!Q zJNz$pUE^`kcNu;#di-Ah&pQ0iMEs`zz40DFkN>?9|8)-k8mIs35*!}mnptqrcNu;# zdi=)I-y>Mp^@UZZ=hq>g>Zn%g`mH)u*B%z?+QR~!>u2w&8_+YK?B5Jz>~ZK{v9??L zH(a}E)%A~>j%zx`uKc&Ef99xW<<C{^eZ5w3x-yu*qo;+sNY|dwbwO9>`OyuNd-Tq} zuE>`*jXvNjo;xBfbmXPJ|Iml){{%-%-U_Yp9Mm!2hS{Tj{dJtT>bgzf8T(^>Izxt7 z{<{fgY{I;AJWNx{i)QdE(cRxe=X8Qy;cs%7E>oTVj}rc=&cB@S?~44<y}!PNF6aY0 z{JE}YneBs}Wsec3;~vp)Ezj<k;v7AnwDj`u9%Y^lK?ZC4X4ls1k3M*xA2QD9FZ$Ky zh#ep3RUf_L%XM&gb55W0(>^QtyGRPLi0^MYo?h4B>Vfy*y6{c)OH6Nr8>V_Ii>EJi z=e+mu0z0p72;aH-hUP)+$o0ayuyN1&2|Di6F}yinsCNza>z{89qCa28xB9^2%lLjc zGW#;V4~`9e8Q&Gp`Rd+!@n?N%WAjpQYHU*8Aw7qGS8sCh4M6I;BQJ79#^Dd5Tpa(3 zj@ie~>GW=Q(VI-P<DBpCQs1L<_JV0=?+>iUZ@G;t-jLVXH_EtYf%^;4)r9{0^}k&I zyw8m9!JMG`7Z`6%dS-rJJeIBx1wRy>#VU&-_%_$o8AD(ohT$*Z;u!m|4<E*qbi%QZ zXWv0)=?r;{hGS3jPo|gJhVU&XzB^@p4<6q(<^OQx?=htOzZUsp7seU<@fmy{xsi*p zV{&nfT<9&mX06v~w>2=x9{)%5iAJ9)8#8})^7!!)+DBcb@%OV%UyNn=rZj(8pf4Yb z8f^;f@w-l6fp6@?+v7t8`l>~J;TK-l4PC@I^Q#VjnZ19h0RLR={a%N^jQ_g}@Oyh_ z&aU7`57^%HhV9oWZkxYb?EPl!+kD^3A1aV%Ks*Mdvrh5H&p5}QESB~~eHxFyj=Vih ze?oIlK|kKFXlpS%<^M&;-)K_)!S@t*o6T=8*E`dKel)Md7#4hQG{#<y6D$8@1KWoh zW2{B@*bYi=uI-o}IB)Qj@6FJ0^r30xffi?NPMe|gNcRosJYJ3KA@S!~H)0lg=e$ra zl^e_LA^v+K2H&=!ucU3GJkAAwUVzJwPh>H<isZj7_U-jlB>zpZA0O9-CGW80CkH`( z&gUY-41baQ8w%ua&>Tnp|6G8}$B%|T)YeUrACo7L2P}>4nw2LE>HPKXocCP6&YchI z{9Je5t@9=BoOcGl#?E72@zq!7{z6P2kzPjBH*;)<{<&{#RApeJoVj>h|KYt(Nf|i@ zW82e_b6{g%M$UmR`Z973bm7Z7Rff%cSxsfcL|;a3LLBpDT`B`-i^dZFK3_RC%D+eR zFLmTB;os#fZP1M7^|e@EbM@7R4nGv0cf!};L5>psV_dj5>Xsbk5*@S8meb|m4l;ex z4*XT=oqBScQT@{{{r+mYmSQY#c}xD@Z~W%f`er5hf$k&Aa~l1Vr>xe!bG%djN@4f+ z&N1(2(CgjU-D<y3=lB9T<$J;80t0G`?_6eb>)q^>Lqngm;XKSCmoy*bzBT1l;Txd( zhH7}9H+5CL)40jicdCqf@MYrvU!)_R*N3+Gl5JDx=m)mYR_~W3SIhgjwsFrK@11Rr z<<)__JpX>8zLkj#OK*IPdF<KquMX?MAL^g^THjxMVntYQAEjfCdp^=VbwN(oB`h7{ z^NHr>$>ttC_YY>-hgiZqW937!JmmPYo8_dt-`rd|FmX@MmH+(V<-9Y=o}=qgj*1<6 zvy+4|zkimt=&noh^v2`)I<D3A9o(AMD4Bdidb%^q$84+c@?I*V)oX>fhhyoqR#O|r zEa*QQ>CrW9&g0!sOD7L;OrDEA&Q+Q9f2Q#f7V&&Ilt-Rmz%M_Z@YJ_`XW+<rU8@`- zx3S?_@33P7WcN7q9o_I<R9}X!$<K*NCq(^le1?vdvp;-B^z~NyQrQVAqkg`|(~7t! zgdenvN00a$opih1=!P5}dV*HpdJb4P);p5JH!xUp;jh7W)fe_TE7KU0p1*sF>>@kC z|5U9hkpUUa&!IzihaKHj4LaQ?cxrA}`fC>t_7qran0@ho{E;zH6JINr|8LLr9p2Y` zH!=6R;M=?}^Q38PLs{<cd6~Y=+ORi#M@0{<Ucc_kw-3bf7FRBvH@<Zn#;RnpXGfnt z(o}gsKm7fR3$MHB^WVGt{P&!=>u+r@s4wmXed<klTsrmQZHJI?we*i4_Deo&I8QPW z!@v~EWRrd!vqr;bt$c8a-j!XsYU*^or<(Zom(nfw4RgOY^WUo#Q^NZt#J75(-fu4+ z^*EloMMImZ7^m^Ey6EQ1#*Cc~)oqbYcwY$ba|6fzTHc@Dw|4&n(oIjq_k7>_gX?V{ zL3DfM2iQdO_$2H5j@SqJAN>gL6ZCzu;j10Z&%oH1VBG02_K7d+OvCt#5hHUb{>;2h zAK0cS7DIy{T8yfE>%+^BZ2n+V&$1h;pOU>SM)_}|cL-0Wn8G(%@%8_pZz#0JSj{_j z;CFY2zL}#k;wAnI4$93p=E8R<@&%*uy*2VBp2L?Mu81!&HT`x|r*L-&H?}5U>Mh{E zDe`BWTAv?Q8FLXaKFFduK8!KNe&h>&Ut^z0I#!wA8#P}~zm>jRHrY9p&(#xZ$N0wQ zIUbbHYaA}J{RjNKMShMQYnq$U2Xi&Pu}sIT^N2&lM&@h#UI%r2?}0I8;|Ci2F(0e% zn))q`_lYP&u#x8Tah;=A_R|BMFPqHE$h|(%T%8=q@^?Z!6|UE8d5qY~^^TJzPrLg0 zQ^k0EG4R1wo|pJr-7$TuA75wv@eYb%-8Z|oq`%)&f6Tw=b4YRz$KzoglWPvd^XhKa zUb!xyX`Un&>R<S*uMzddH{&}>`uYv^75GU``b1~M0DJ=-kLaKG|Kdydg)eWGzjVcN zj{`lxgEp+Y$*b;F{NXyQT|1y%T9@z3U!(oa^+DHsAB4CV{5bjt?T8il!y2vM@r4=o zsNFc-6R!JgdF-kF2d9WB)rxYBg?XMhE_&9pjd&(`IbKG&`sE*7_z&N}0XO);eXr=C zq0i5}F@LWkHfmP+gvy%rE&3T)@Qsw#`;M@h?=fFA*S9=2C~Wv%RebTih4>!4)oz(^ zV4nf~do1Y5*AKe-<vL!L<+0-Hno9ys#|u5eA34x9{=<4Ht0|Y#7*3zxP_ES$bfkA} zE`vsRd(|#2tE;R_yjTO%2glI%m6S6VVjHcyq<iHE!i}zd8EezDtX@#oAIttm{;@pv z%ezg(v3L^OY_90|iRMa=k_5lk$~^*O8Q0N~OW1!Zk8xl@PsBKmFIW7+SBPQ6v~HCV z)A0RK9V7Rc{?RM+wkI<teAqF>LY2eQaxiq?iCznIuWz`w1)WNkE@-6B0r5`D1`Eot zQA&r624es48H~rYXC43-?dtIudi(<$;UD-R_V8t9H{yGXWa$tc{s^5fGrN67Ho~vR zvfM{sCm%&;%m?TV-}LhVb>aIzs$)K|IfF6WsXD&P_aV&(0h4&3BkDrmb}qTlKfXx0 z(a<IwtDYE!PX?YEFT?=mib2KG0makyB%b!EEq?b};YX+I#lv*UF*<GVk9e#v!*V># zh6#PrU-Rxf7W8v0c`B2vJy~z(Scip`cQsAKc$m&>KRQ|Wi-?vsHg^%D;Wey(Y-aLX zIr9(Y_zL5ZIS6@?y*hdAB=eo|OL06DV_b^kAB4l&(KoTo`ZF9>pW-w;^hq4VAJC)u z5B6ogV63fn^M#E;@`K#R@)+7EpDc*ovK#Z?jn$)m&{87Pt;i(Wbe<SjnavX>Blbk6 z$Iv@H*jO7=d-GS0i9ZcL(tJEhedN{9<0#*ZE^o*D&bo;C$IqD;Y0hNtwNn33i0|}6 z99<UsAdcF8PJL+}M=e+EQtsMWQOwDRja(bop2c7uM_I@Gj`RcXGqnz4oMSV_Ie7~) zlyCYde{7qt|AqQLNBLuyXm+t)sp>l94tis(q7UFMChu&&r9TTcS+WB{x2Xe^AGJ zsNu6F;nP~cXDqhQgy}?mC&Ba4K0@H5_3<Iow;ktw<>lze&o__%cyon)lTOV!t@_y- zVwLnYA$={EzE((ItO<#?%vp^%T+{dGHKzMCrYZl-kt1O~Z;f<z-C;s_8Aq(UZEZ<B z5A(YIiIJBoMz-sidwYmetvbfO#3_y`C-;Pg@?jkh>{ebsnU8yPkAKmR#YE_Q-hAj) zdQL)ZhFlxVRYHu3@hNThcWTF&2$*EE98dl&6?9EZ2)J~d%aFhOu2MUiJ8F¥nei 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libdbi.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libdbi.so new file mode 100755 index 0000000000000000000000000000000000000000..5ab3801132e03499c113e23e2450999c871de37f GIT binary patch literal 42704 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libdci.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libdci.so new file mode 100755 index 0000000000000000000000000000000000000000..9905a545b50d546b54c2550056a7227a78191726 GIT binary patch literal 13636 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 S`{TFl)-xkmQ)wY&n*4vd>hf~{ literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libdsp.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libdsp.so new file mode 100755 index 0000000000000000000000000000000000000000..c0efde5f85e479aff141dfac121681b9c838e4d3 GIT binary patch literal 88184 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 ChIW+z literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libfh_crypto_api.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libfh_crypto_api.so new file mode 100755 index 0000000000000000000000000000000000000000..c1877470e714a6460b62db339f736f68fdf31d46 GIT binary patch literal 33616 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libhd_arm_vbcli_linux.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libhd_arm_vbcli_linux.so new file mode 100755 index 0000000000000000000000000000000000000000..0c64880e821397c80e3637e8685a15dbfc60ccfd GIT binary patch literal 18724 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%0A@NO1)t}Z|&@Zd8j>cSDrom(`PC%0&1{(%m# z1iN5Yv_sTwN`Qq`wLP5{b^JvU>xHPp@nBsrlS$zx9Q=SF*SJ3?<>wEVNo)<xv%<4T z4`QDow?5o5F!Jme_wo{?;~663CFD!#W}}QJd8FgnqItdu2IN6nrd*rn*sw`A0d$Bw zW0pZ~b?}@NI}?i^&y*ScfF&vUxe>pDNV+A6Jfmd1h&<`|JuB%}AWz<0`nfk`q&zZ^ zj)8n6ojiBmCWQiybd0MNI-b2Teq8)Uw`f2jniV>8&xC!`)!Mz!rlVeX7R1Qk#buE4 z1yMk8NXKs`GfE<s+4-*{<&hrsVExaV%Q%wAemsagzo<yZGr1b_L|z6-w*v)imvsC# ztGx;x>+C|L*rek(8ULrw8RR8Trf$T2h?1ZAE#}1@5M?sRb{|K9q~kYS7IZv!kU{c2 zhywCuyZrV$3Oe<>LDD@1Joy1_2GT9J^Gt|i{1GB}C6SonBhb}L04Zr0m~t#+@Xi&& pca3#+!gETt>p`TAQZ^ZqFx<(?_)31XS(Waajpl`QS*_Ua{{y%O)kOdR literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libisp.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libisp.so new file mode 100755 index 0000000000000000000000000000000000000000..6f07ad63b3adde51d413a9dbe30fb7e346dad4dc GIT binary patch literal 81376 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 RO1|3`mpIQ^A>1wB{{{5w8UX+R literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libispcore.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libispcore.so new file mode 100755 index 0000000000000000000000000000000000000000..58ae00da0223cf95ffe3d3fea53c684c13174377 GIT binary patch literal 197484 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libmipi.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libmipi.so new file mode 100755 index 0000000000000000000000000000000000000000..35a189f642ce27f2a62af093b29147390dcc656c GIT binary patch literal 14828 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 LXQP?mY4Cpls=GRc literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libvlcview.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libvlcview.so new file mode 100755 index 0000000000000000000000000000000000000000..a2570624e3528d10abb14e9e580a5fea9eec49dc GIT binary patch literal 28616 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 GNd6xhxXt$f literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/lib/libvmm.so b/general/package/fullhan-osdrv-fh8852v100/files/lib/libvmm.so new file mode 100755 index 0000000000000000000000000000000000000000..e03d3fbe6c18464b3702373c6c3726df940499c5 GIT binary patch literal 12636 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 Uu$*!ZTJFU*nJl46*&m7j0Y`lV&Hw-a literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/script/S95fullhan b/general/package/fullhan-osdrv-fh8852v100/files/script/S95fullhan new file mode 100755 index 00000000..0340d7c1 --- /dev/null +++ b/general/package/fullhan-osdrv-fh8852v100/files/script/S95fullhan @@ -0,0 +1,73 @@ +#!/bin/sh + +DAEMON="majestic" +PIDFILE="/var/run/$DAEMON.pid" + +DAEMON_ARGS="-s" + +# shellcheck source=/dev/null +[ -r "/etc/default/$DAEMON" ] && . "/etc/default/$DAEMON" + +load_majestic() { + printf 'Starting %s: ' "$DAEMON" + [ -f /usr/bin/$DAEMON ] || echo -en "DISABLED, " + # shellcheck disable=SC2086 # we need the word splitting + start-stop-daemon -b -m -S -q -p "$PIDFILE" -x "/usr/bin/$DAEMON" \ + -- $DAEMON_ARGS + status=$? + if [ "$status" -eq 0 ]; then + echo "OK" + else + echo "FAIL" + fi + return "$status" +} + +# The daemon does not create a pidfile, and use "-m" to instruct start-stop-daemon to create one. +start() { + logger -s -p daemon.info -t fullhan "Check MAC for Xiongmai devices" + if [ "$(fw_printenv -n ethaddr)" = "00:00:23:34:45:66" ]; then + logger -s -p daemon.info -t fullhan "The eth0 interface has a lousy MAC, let's try to change it.." + XMMAC="$(ipcinfo --xm_mac)" && [ -n "${XMMAC}" ] && fw_setenv ethaddr ${XMMAC} && reboot -f || logger -s -p daemon.info -t fullhan "It is not possible to install a new MAC on the eth0 interface.." + else + logger -s -p daemon.info -t fullhan "The eth0 interface has a correct MAC - $(fw_printenv -n ethaddr)" + fi + # + logger -s -p daemon.info -t fullhan "Loading of kernel modules and initialization of the video system has started" + export TZ=$(cat /etc/TZ) + #load_fullhan + # + #load_majestic +} + +stop() { + printf 'Stopping %s: ' "$DAEMON" + [ -f /usr/bin/$DAEMON ] || echo -en "DISABLED, " + start-stop-daemon -K -q -p "$PIDFILE" + status=$? + if [ "$status" -eq 0 ]; then + rm -f "$PIDFILE" + echo "OK" + else + echo "FAIL" + fi + return "$status" +} + +restart() { + stop + sleep 1 + reload +} + +reload() { + load_majestic +} + +case "$1" in + start|stop|restart|reload) + "$1";; + *) + echo "Usage: $0 {start|stop|restart|reload}" + exit 1 +esac diff --git a/general/package/fullhan-osdrv-fh8852v100/files/script/load_fullhan b/general/package/fullhan-osdrv-fh8852v100/files/script/load_fullhan new file mode 100755 index 00000000..b62fab60 --- /dev/null +++ b/general/package/fullhan-osdrv-fh8852v100/files/script/load_fullhan @@ -0,0 +1,34 @@ +#!/bin/sh + +set_gpio() +{ + if [ ! -d "/sys/class/gpio/GPIO$1" ]; then + echo $1 > /sys/class/gpio/export + echo out > /sys/class/gpio/GPIO$1/direction + fi + + echo $2 > /sys/class/gpio/GPIO$1/value +} + +cd /lib/modules/3.0.8/fullhan + +insmod vmm.ko mmz=anonymous,0,0xA1D00000,33M anony=1 +#insmod vmm.ko mmz=anonymous,0,0xA2000000,64M anony=1 + +#reset sensor +set_gpio 13 0 + +insmod rtvbus.ko ra=0xa3e00000 rs=65536 fn=rtthread_arc_FH8852.bin fa=0xa3f00000 +#insmod rtvbus.ko ra=0xa7e00000 rs=65536 fn=rtthread_arc_FH8856.bin fa=0xa7f00000 + +#reset sensor +set_gpio 13 1 + +insmod media_process.ko +insmod isp.ko +insmod vpu.ko vpu_mode=buf_0_3,buf_1_4 +insmod enc.ko +insmod hevc.ko +insmod jpeg.ko +insmod bgm.ko +insmod vbus_ac.ko diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4623_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4623_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..a48df75b5dc7bcb975abd24b52e9cd1ce6e45d77 GIT binary patch literal 24440 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 HPon<@t}fgO literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4633_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libgc4633_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..a24bf3265b73e6ce55f66d7440283a8717e31280 GIT binary patch literal 24620 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf22_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf22_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..31115458f04732ac214aa174c0b921954c36c13a GIT binary patch literal 31360 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 N>c<m8kqBIj{x9PC)ouU) literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf23_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libjxf23_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..0b385fbda97bebb7f5e277d248d17aae2676baa8 GIT binary patch literal 18344 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libmipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libmipi.so new file mode 100755 index 0000000000000000000000000000000000000000..35a189f642ce27f2a62af093b29147390dcc656c GIT binary patch literal 14828 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 LXQP?mY4Cpls=GRc literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libmn34425_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libmn34425_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..05cdf030d26db7ef4af44b66cd5629f6d39508fc GIT binary patch literal 24896 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libov2732_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libov2732_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..9c0670ef944a6827d43a29db0c6a91ef2fe1004e GIT binary patch literal 22516 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 Z!GL0xyPuLro3-)<U_ei+M!<^izW|$33H1N~ literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libovos05_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libovos05_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..36d44d29bcad67589a80fde1568527def502d3a6 GIT binary patch literal 44280 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 RXYgJ21djhiB4}dp{{mlrj)VXJ literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/libps5270_mipi.so b/general/package/fullhan-osdrv-fh8852v100/files/sensor/libps5270_mipi.so new file mode 100755 index 0000000000000000000000000000000000000000..5f0c423ae08393e33528995c1cafdb46a1bca54e GIT binary patch literal 25264 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..a1f7b6b81aec72fef3debe52f2e9ace89fc4d6cf GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4623_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..b8c3dd5da2f651b14cc38d7211e3665c62ac2c4b GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..26b6c87c26f1955748db176545adb14799ff0bf7 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/gc4633_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..26b6c87c26f1955748db176545adb14799ff0bf7 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..af7a40905db75f76270d217bc667a60102f293d9 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..50e4d5b534ea83ee991e2d2060874c7fe0a04bf2 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..e610c1b8bcbedd9bf654e8fa0f45d53529d3de59 GIT binary patch literal 2924 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 Jc>I64{wKwyfj$5L literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf22_mipi_wdr_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..dc8136521f1023e351e4ea0578ed29d6494b2c25 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..fe7a5444a1a8b1627a5c88967660f18d22f70ac9 GIT binary patch literal 2924 zcmbVO4RDm@5q@^}F1aK}I3UC%1nz_0-HU(_O(awiu22wv0>@8A6sT9kluBCDQHDyZ zoK74{DKsijeoK&_0wpC;QV}5yzXc=_B34>#iKPa#FwFqAsW3_RyW>dA)R|6q=l#BY zfA)Rf-F<ey4<Otk2BdC5ZX|J-<JDdvr#)`VcDtTF!717=6sNPC8fC4+(q5uAfF1~g ztT2|Jn4joU@@U)OT+2ZOag7}Md=y(HALIob43E{;)~3gHv329LEMZ*g(Zr1@?<YBv zQd090Q{i&Dk^FHHicqkl#IY~wx@&Rc6G>v7a*w!tp~s{?0e@?z-#0et_N><HT_f>* zI={2HNlz{CHt}ljYHyP_qBh!8pyPGk0&kYsqfOr2PUD%fdZay`cXPasvXF(<s&DU? zg{GTsE8q*>dhd8|rmXQ^P>!$HBOK`ZRooVviQeSPk2~Yt+<CT_zLL_?GqSR?EsKId z*n#r&1kzmkR_?0(EN!k7PxmxknC-RvPM6DVDdi}6M*_ASC#qCEheI`8=#rrqcO<(# z9;?4i_5}vbh_NkS(UxohK|R+KSvXoR*_M)$oa{<WNN_qG4xi7mGSa%Irl)6QSh`3l z9EsG{Zn2e>2F@5bqt4Xd;yTl@S0C-gMmj$2^>#nLy0aXg?YM7TC-#nMw9m&hVmrom zZQrwVKc>}ww!JcbmyUA#o-xVRh@TtRj_b9*<9BLb5#J~Nw)Z&kCAQa|Fz+hIp2t-> zZjMFUG4p%nBhhx)95#o{0p<PXcc#YdHG9l%^IKDG-ZWLF!fZEN&1SQ~tTU_3GPBhD z)Rda%%{)_LW}C2i#5`<9nS3+Ac#X%1xfVDdXb98>DgvtlrGf7S3IihozCd!I+5dt6 zZT~O*FZql75BZ1q)BIof&iRh`Dtya*FZjOeEA)NSm*+FSY+rX@iqGk@QzwiF610A} zkc4EUpm<hz>Xa#=P-yD(=~1BEd{8KuQ=$|O1%o*m9#6O2e(-p5ETB!xQJdI!wsGus zyIds-wz%xMNiLVe(NUhLTI29ALYRW7n5_4hh1n=Z37*9d@ngMJDSm>Vp$yBg5^GV8 zP1uSZsKhSp#$MFo5RT#mPU1Aq;3G8RZ@7p{XvQ_P;D#1M4_TB$K?+frN+?2QR8Eyt zODCz3nhES-i*q>0Ar5m1N4Sj3xsq%7BsX$1Lp)+hjsztnVJVS_lu5Z%O0ArfMrqdD zyEIR4gBSfV1o;?&F>1|Zt*~J{i8=TI=HYp~h=ppyD_DUwYQaXepaNB>RtxrF|1AsN z$A|bM{v5TT37_GzT5%Ph<KMWBRuDNTfs)8gscKUX>PZ=tMcEXfA(XH7jngo))*1_W zxF6G$i}3=M=!skPqyu<Q_dc(l`KNL#5~z#r(2M#}f4YP2qG5C&jiNEi4^jb5qC$F% zX3$Lf4i(eW^ejE6ynsq+5iO<HXeF(q4YY-Rt)8q_-a|EXkdD$B`joB^aVn>CUmnQ0 zd@qmT0-nTE)w@q}v3hte&*vBUWnRQf`4wKqt9UK1=Z(CDxA6|%$#3#5-pz0GUasN& ze2@?GQ9j1+a=k|6jK<`mM&)1J#!hidnq)~|F)~>4<X-uPjFa&)MW)HOWwv}@=E{7H z*Fsq$ugXeUFPmk%RLNViR}RQAc~4HuS@~F+<dR&K7P0XwngcGyzZ<C<)$T|`y2dsW zz0ezd)U*BYHTYpP)&npQcVIAba3^wcH-=&uzK(k^9QR=)f*6I-iiEL>?FaCnBBB5j z6yp;W8B<V*M-=OiX@sWZTX<ZNG80cI?u!&JC76r(SfHq1gr#^*F~1J4<5y9{S7Q%q za4?GZQ}_UX!a0p-4DB{bTEUb^Db$tH6dT#pm;7{lG`d6S9vVTTX)?{ySeDXq+DyCX z5S^y;bd{L9X|!^9B#-CmJV)cRh<~B+*rnb-#pn1k-{54)kbru5luVErGDn_Mzb=#4 zWvA?u<8nqmQ6K78Ons8C){nz@wQ^cC2cE*yc&0-xFUHT+t`%6Nmf5+m1>4lRop>Xf z5ASG3)T)h#)ym_jQ`9zSX4`pj7Jt#q_$xla1$>IXYj*rYzkb&g%`NysGrd)F-KCjv z8}(7U2T`ut9Hg;|=E?LZJ+78NrTIUXexx<vWm>FtU^%U(^|Xn$Q3bt0Z_zti6%Nxe zs;36}1D&OF>YWR8Nvp&)YM~p^TH)ovJe(g=JQwjZS}m3+em8R!?^BGPR$qO_pKHxX zk)Gm}0qU<2a=%PeM9xw?&QmllQY@~KO;RD%QX@wcg&)c}xu}(-MKpnLQ794<?eDoQ zky5LYEi;Sy+8(nd{ZaTI$eG~r^z3c<hveKH6sODG#nYo_Z~YJH)=9TY&l#>igWG4O zx?DFBDa{hPqBjWYI=8lRt;l!j(V8exvhNj>{(HaU-2W?Qc%Ya7W~DaN*z&OChMJNU xeS*zZnZfv;A1xr*w)8I>s$VdmRM%|%O=i%(oUL~{rJ<&5P>-NJZtGY&@gJUmzs&#u literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/jxf23_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..50e4d5b534ea83ee991e2d2060874c7fe0a04bf2 GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..a57db8ec35ce3f31fdcf242801174ad73b7603d6 GIT binary patch literal 3076 zcmeHJX>3$g6#mY=Z)P6Tmc9<9Gq%;4*7s&=!8)byT`M9T3Mh+cMNli23=}GhNU11l ziq_!1L<ve%5?tekqH#%$5&|R!P*4&TPz-3m$l?m9sOWg!ypAQVKlO*_<lcMEx!+yh zcb9ho!f(Q++<blA<AD*{t9jEkKUZ`G>NVG2Up8Hn?52h01AW|(){<Ns$Tp>>G$@wN z+PQ3>FRi6;Hx7TJb3PeQ$x}fA4G=J5nM@`H=sB!g&e0YWZ1pV)9u9Qssl2j4K6GEM zzIjWN|2%zapSec{`TN8OTK`eT$dZZX``1_%lSl78?w6kmyK>mymv!_Y>TvV~ck<N; zMmGr$;l&ZHlbfT!=4f3{yp7rz-xYmHY;Gv!c<CSG(PQJ&Xa?guqpym$qsQUxXju=Q zkSY8p{ry~Bzn0e^%WC_Av*s`OGsJH(qo~NU-4!h16bk|d)2bttt<dugBh)`qY9^b~ zx*p7m?$@;X2F7|4F^qhjUI0QyjN2LrMtF%dpWg@-7njGX+(pK~7EfLKAg3S?mP(~u z7rd02yu4sg5BU8)pQf2+EEXva^(`rhL}CnLNq2RvS(C}4fdMT8S~^sRx`LCNd!^_1 zdR~p|=QM|P@gA<%a(l|P=(T!#&LO>s=k?;e)^7V;&$&nr)7$qv<!VPy?v-AwU3ofJ z%~hAP&QX_T(=0Vx%~Ug3FI8=7nrc;3R9a0|Eozc#Ru`!W>U?#s8mGpnk!rYVP^T-U zYSqaqt}0ZS>aPk^KxLfoov)qGoSn{l&Rfn}r`vhfdDywvxy|Wx<~gm-1<q*a45!A4 zIU&dAd}r^qci5Zk)%NrD!}b#UM*AvzhTUwBv4_~F*cEoM?X$m0Y)h<4JeIgUF)z`a zXh>8giV{D>cgHuyyW@|<?}%R&pAsJzua8@CBmT3s&w9^VYpt{%ux_^ISuNHmYmilL z`K_<b?dCdjg?X>J(41k8H;0<lW~rHP3iEJye|UFzS9mAuuJ9+}J>k9K1K}^jhr-{7 zkA~g-nnG94j_``c#>Nq@aM^fl1tn9dWHMP(U1i21p}zUYS5_1mMteK&JU-DG+0K%7 zr74xn*~zMy;Ym=}bxrGW^nCWxLxE8^8%>zN!w_Fb8hr5cnd^ff@{o@L6!JMJLJ0lP zpU+ho5tO0~<v1QEAchK5;zXE;BY`TMgaH_clTm|HP>Vr)7uaxcD(Z0>2IF*`fuU&N zuN{Wr7=e*ElSdzoF&N8pI0xf#Auhobv|%>dF(239IxNC1xD$)96wB}s9>>#Ii5Jn0 zRalERuo3UzU2MZg_ynI~Kfb~t9Klf#`6)<+)Q=)mP8DQPHPujx##1ZJr<-UgJxSfP zfwt3LIzj;v773xmNHIaQiVksuxJNuBo)fFYo8klUnfO*{G9+WNMh=l<WwUIPSIR|l zv0N^nm9NPSa;w}U4>JEE%bm`=6)<NmV<lO(T&60RC5suVW`=5zWNsWN=4CL3FeAgz z$ZVX&T%3(@yc**%k-2EbB>q>VF%{EsDQ038=3p*5n3*eaHLk@%T#p-=p__0kZpU4? z56kfc^V7}Tyve-mz#e>oZ}AKK%te@DR7JHkn1<6>I-e#n7qgj-PP&oqpe3}79-|fX z61`6AXd`W*ZM2g<rO)XQ{YWGNqAzpQASQ~LqEp-{mWijuD`E{Z^sd+;c8dezp!h*# zgkKiOVp%3D<w>$uo+gLM(egZbv22yI<$SqN-YoBy_sd7+3i+~JE!WE}@<V3t3)cVl z-~apX-`s!R>y7{Cd=na7oaJ+Jg~+|4|5}8UqDTG;B!s4Ee!g&7{6VAGC@xPX>w6vz z$24*WD&*VZnW=qs{b&HiF+LW5ChlXDg{SuSbMs*T$-FY;J=jJ}aOzyMC@VlESLEJu I|Hj0B1(hH!YXATM literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..2138fd91c2e3d7b8f3338cfc8be17a43f8596d42 GIT binary patch literal 3076 zcmeHJeQXp(6#vc4-raKj+8zgY(gH`hyH<*&l=~=xaNyoul}ZjW3W}JMS`dxeSV%)8 z(n^R4_(e28A_yo!L_lJUC;`hyOe<m_Y7rC=P_TYLp+H+L@tobgYYUMW{?VB5US{5V z^WMzt{^sr50SLNCsO*acBi30|>7%qt$t)bTmQqQx8*(ZoChRzsOtm;MHZBzl%c4&u zu{ek;uIs7JVvb88ti+|=y+r>IHn1RwB^{tpT!};?1jwmaO+F#jWE?Urv|h5zmqTee zB2qS`{2>qt3Y5-Rg?I#lw&qz`_eCl_zs@%0Jy2JW^JiyPZ7Q~>3~2^Uj@-C(=`(M9 zo<5Brk@ZiUe6p*=aB&6(s@dbJYp!x#V<_3#*~XA|f_+7ESs`GO1&4HpoUSOgKF)sb z;!sGItvYF-myQ*&20618MIl=Oo8r<ShSez`lT2pCX1C|M3baGU(CG$idaGzwu~{e- z(oBe>Or)h*t+K^zHkl;J?RL4Gc3WoOzD}o01PO}Q*6!Ms5Nm5xIK6Os2mf8?4z6jb z-q19w+pmpjvBqe(-gACR?<rGjq-GdvbVnHep5E@A+Qn{0Yu9CJZ_R4wZC$NR=xzM6 z;7k0X&aI+v6?|UsIi1h)-}ujhoB0`jnxEn)`Eh=fAK{026aSJQ;QM(4-^=UycK#vX z$~W=#d<|d0m-5B@IsOc<=8y3>pTh6q<9R7B<b$}K%e*~$Ji0f!A-W`573I-D)EVuJ z9E;RP)<o(e6%jS!iI^kJ;eFwa;TOYCg(rnag!_a$)bG?!)V1m&b+$TDEm56nXRtB& zT5v|NBuIh>18)W92Fe1tfeZdd|7w4YKjt6eH~UZd>V2zx^L^8NqkIE=C}_xkDSv8y zUVe*rr+0~WnzzUcZ<A-EXMty`r`RKVPPuoum%Hb<xqGC0u-oRgxD$>x$9cy&$63)@ z9IcMajt<8ahnBA))N1L_MX^|Ud3l*2RaLtNbtM!k7BsZL?Q+^O)B7umNZG0?k$IvP zBv_S3kH%wVYN%M(MOR$l5?L)MGc#S5CCM<9bYaNxF+ds05d#;i6Hy){m|zy)TrXIW zhIC{gOXO-cZ0L<X;=6LdiGIjIF8X5tTo{Br42BzC<f8z$q7XxI8;URt!%>0}@WGED zN-+|*V-)Vd7>pHfI}Ue3MHmsW`(3yj6T~x2#AHmtgLoJ-@i?k52lMbO7UFrlfTdW5 z*RdMw@D8@%eQd)H?8c|~3<vNPzQIwP#A*D37F<LJu7D6Tv63v(n>a}>8ALo}2q_{V zGMQA6Ib;!8M&2gdNFzB+nn?$-PzTMY0UD;9R?w$u9estarkm*wx{n^AKheunVm9Vt zMQk*i!0u-=*<7}eEoE=8O>8@BWQW*~tW~eY6igtf;U^~%%(x0cdlJE0k{Axaz`wz8 zND{?iDDFZr&;!NM0!IVI@j8wXM0Feu1g9a6O3cQSs74LuqYjI(7%$^htiUR)#d^Gp z_wWHe#!l=(1NP$}n(!^Y#}8=6SzJIHI+1{h^dgyE2zp5&8AB$KM@S7>OjePtWDjW) z=>0)5=s;RRReCR-Md#5abS2$F>*)b{f}R&}C~Tm>?T#dF)ocM<!j`i)*=Dwl?Pi~| zuh}tnhPANvBz`yZ?`Hn}H~DAWGmL7h)Cy_*qD5IGT8X|sQ6_R%+!F*{KS+`!v#e;> z46{|SEB0J*3yH<9jn_8H5_NUsj7(X+Vu9VIFMVwoM2Y#|Q(m6&3VAy9d>wI>OWx&r Ij{aNvUy7(=AOHXW literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..fd06ae92cb3cbdfbfea7dc3a7ab70dcb82811009 GIT binary patch literal 2924 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 PJqvq&c-<fMzuEs2=0cOD literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/mn34425_mipi_wdr_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..dd649b3ce477d351e6c50bf267db6a34c4096238 GIT binary patch literal 2924 zcmeHJdr*|u6+h?R1s3G7$QD+#;Y(N^3ei=bkwms;0nN~4#pThcb;~o3*sgXLh}Fq9 z?t(^>VzUcsQj3{=SRxkd4QMnO;v+SdG&*V1)W!*-nYOW$K$@u<GScΞkwvbf$mx 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..8cb59ef26eb498b9b169ec59acd5bef386ea9fe6 GIT binary patch literal 4096 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 St{eOzy1oDZ4*$cw!~Ywt0oYvt literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ov2732_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..34d9a065493258253eda4a347069ccc7e9b40a9b GIT binary patch literal 2940 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 T{hhF^SUpBxosTVi1BHJ9gSa1P literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..6b4f2f0392f7fc4bed24af180b0de6ab97f55f94 GIT binary patch literal 3268 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 Q9lto5cloHgmcBmt4>$(fIsgCw literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..b7681b5d121d146de9862752f85abc1232352d91 GIT binary patch literal 2923 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..35dcfe19362100bc824f98fbe6b885ec7723951d GIT binary patch literal 2924 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 Q-SsT&`Qde6)c<DxPZ{Bp!T<mO literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ovos05_mipi_wdr_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..05ee5ac1af8b41339bdf11d63a959089cb4d76fb GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..473c21c45ac87fc061c84e27bba6e2202ea2666b GIT binary patch literal 4096 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 BQ>_31 literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_night_attr.hex b/general/package/fullhan-osdrv-fh8852v100/files/sensor/params/ps5270_mipi_night_attr.hex new file mode 100644 index 0000000000000000000000000000000000000000..5fe664e1407e0d7dfb378fbc7992e9665af25b0f GIT binary patch literal 4096 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 AOaK4? literal 0 HcmV?d00001 diff --git a/general/package/fullhan-osdrv-fh8852v100/fullhan-osdrv-fh8852v100.mk b/general/package/fullhan-osdrv-fh8852v100/fullhan-osdrv-fh8852v100.mk new file mode 100644 index 00000000..d6ef3a00 --- /dev/null +++ b/general/package/fullhan-osdrv-fh8852v100/fullhan-osdrv-fh8852v100.mk @@ -0,0 +1,38 @@ +################################################################################ +# +# fullhan-osdrv-fh8852v100 +# +################################################################################ + +FULLHAN_OSDRV_FH8852V100_VERSION = +FULLHAN_OSDRV_FH8852V100_SITE = +FULLHAN_OSDRV_FH8852V100_LICENSE = MIT +FULLHAN_OSDRV_FH8852V100_LICENSE_FILES = LICENSE + + +define FULLHAN_OSDRV_FH8852V100_INSTALL_TARGET_CMDS + $(INSTALL) -m 755 -d $(TARGET_DIR)/etc/init.d + $(INSTALL) -m 755 -t $(TARGET_DIR)/etc/init.d $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/script/S95fullhan + + $(INSTALL) -m 755 -d $(TARGET_DIR)/lib/firmware + $(INSTALL) -m 644 -t $(TARGET_DIR)/lib/firmware $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/firmware/* + + $(INSTALL) -m 755 -d $(TARGET_DIR)/lib/modules/3.0.8/fullhan + $(INSTALL) -m 644 -t $(TARGET_DIR)/lib/modules/3.0.8/fullhan $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/kmod/*.ko + + $(INSTALL) -m 755 -d $(TARGET_DIR)/usr/bin + $(INSTALL) -m 755 -t $(TARGET_DIR)/usr/bin $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/script/load_fullhan + + $(INSTALL) -m 755 -d $(TARGET_DIR)/usr/lib + $(INSTALL) -m 644 -t $(TARGET_DIR)/usr/lib/ $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/lib/*.so + + $(INSTALL) -m 755 -d $(TARGET_DIR)/usr/lib/sensors + $(INSTALL) -m 644 -t $(TARGET_DIR)/usr/lib/sensors $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/sensor/*.so + + $(INSTALL) -m 755 -d $(TARGET_DIR)/usr/lib/sensors/params + $(INSTALL) -m 644 -t $(TARGET_DIR)/usr/lib/sensors/params $(BR2_EXTERNAL_FULLHAN_PATH)/package/fullhan-osdrv-fh8852v100/files/sensor/params/* + + +endef + +$(eval $(generic-package))